//
//  NSAttributedString+Frame.m
//  GMAlpha
//
//  Created by zhb on 2018/11/28.
//  Copyright © 2018 Gengmei. All rights reserved.
//

#import "NSAttributedString+Frame.h"
#import <CoreText/CoreText.h>

@implementation NSAttributedString (Frame)

/**
 * 计算属性字符串所占大小
 */
- (CGSize)attributedStringSizeFromMaxWidth:(CGFloat)maxWidth
{
    CGSize size = [self boundingRectWithSize:CGSizeMake(maxWidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:nil].size;
    return CGSizeMake(ceil(size.width), ceil(size.height));
}

/**
 * 获取字符串有多少行数
 */
- (NSUInteger)getLineCountWithMaxWidth:(CGFloat)maxWidth
{
    CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)self);
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, CGRectMake(0, 0, maxWidth, MAXFLOAT));
    CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL);
    NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frame);
    
    CFRelease(frameSetter);
    CFRelease(frame);
    CGPathRelease(path);
    
    return lines.count;
}
/**
 * 获取字符串某一行的frame
 */
- (CGRect)getLineNumRectFromLineNum:(NSUInteger)lineNum isLastLine:(BOOL)isLastLine maxWidth:(CGFloat)maxWidth
{
    __block CGFloat lineY = 0.0f;
    __block CGRect lineRect = CGRectZero;
    
    CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)self);
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, CGRectMake(0, 0, maxWidth, MAXFLOAT));
    CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL);
    NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frame);
    if (lines.count) {
        if (lineNum > lines.count) {
            return CGRectZero;
        }
        
        __block NSAttributedString *lineAttrStr = [[NSAttributedString alloc] init];
        NSUInteger index = isLastLine ? lines.count - 1 : lineNum - 1;
        [lines enumerateObjectsUsingBlock:^(id  _Nonnull line, NSUInteger idx, BOOL * _Nonnull stop) {
            if (idx <= index) {
                CTLineRef lineRef = (__bridge CTLineRef )line;
                CFRange lineRange = CTLineGetStringRange(lineRef);
                NSRange range = NSMakeRange(lineRange.location, lineRange.length);
                
                lineAttrStr = [self attributedSubstringFromRange:range];
                CGRect lineAttrRect = [lineAttrStr boundingRectWithSize:CGSizeMake(maxWidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:nil];
                
                if (idx == index) {
                    lineRect = CGRectMake(lineAttrRect.origin.x, lineY, lineAttrRect.size.width, lineAttrRect.size.height);
                    *stop = YES;
                } else {
                    lineY += lineAttrRect.size.height;
                }
            }
        }];
    }
    
    CFRelease(frameSetter);
    CFRelease(frame);
    CGPathRelease(path);
    
    return lineRect;
}

/**
 获取属性字符串最后一行的frame
 
 @param maxWidth 最大宽度
 @return 获取属性字符串最后一行的frame
 */
- (CGRect)getLastLineRectFromMaxWidth:(CGFloat)maxWidth {
    return [self getLineNumRectFromLineNum:0 isLastLine:YES maxWidth:maxWidth];
}

/**
 * 获取字符串某一行之前的所有字符串
 */
- (NSMutableAttributedString *)getLineNumBeforeAttrStingFromLineNum:(NSUInteger)lineNum
                                                 deleteStringLength:(NSUInteger)deleteStringLength
                                                           maxWidth:(CGFloat)maxWidth
{
    __block NSMutableAttributedString *lineNumBeforeAttrSting = [[NSMutableAttributedString alloc] init];
    
    CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)self);
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, CGRectMake(0, 0, maxWidth, MAXFLOAT));
    CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL);
    NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frame);
    if (lines.count) {
        if (lineNum > lines.count) {
            return nil;
        }
        
        __block NSAttributedString *lineAttrStr = [[NSAttributedString alloc] init];
        __block NSAttributedString *handlingLineAttrStr = [[NSAttributedString alloc] init];
        [lines enumerateObjectsUsingBlock:^(id  _Nonnull line, NSUInteger idx, BOOL * _Nonnull stop) {
            if (idx <= lineNum - 1) {
                CTLineRef lineRef = (__bridge CTLineRef )line;
                CFRange lineRange = CTLineGetStringRange(lineRef);
                NSRange range = NSMakeRange(lineRange.location, lineRange.length);
                
                lineAttrStr = [self attributedSubstringFromRange:range];
                if (idx == lineNum - 1) {
                    handlingLineAttrStr = [lineAttrStr attributedSubstringFromRange:NSMakeRange(0, lineAttrStr.length - deleteStringLength)];
                    [lineNumBeforeAttrSting appendAttributedString:handlingLineAttrStr];
                    
                    NSRange appendRange = NSMakeRange(0, lineAttrStr.length);
                    NSAttributedString *appendStr = [[NSAttributedString alloc] initWithString:@"..." attributes:[self attributesAtIndex:0 effectiveRange:&appendRange]];
                    [lineNumBeforeAttrSting appendAttributedString:appendStr];
                    *stop = YES;
                } else {
                    [lineNumBeforeAttrSting appendAttributedString:lineAttrStr];
                }
            }
        }];
    }
    
    CFRelease(frameSetter);
    CFRelease(frame);
    CGPathRelease(path);
    
    return lineNumBeforeAttrSting;
}



@end
