//
//  KBStreamTextView.m
//  KeyBoard
//
//  实现：一个接收“流式文本”的可滚动视图。
//  以分隔符（默认："\t"）切分文本，每个分段创建一个 UILabel。
//  标签可自动换行并可点击，整体置于 UIScrollView 中以支持滚动。
//

#import "KBStreamTextView.h"
#import "KBResponderUtils.h" // 通过响应链找到 UIInputViewController，并将文本输出到宿主

@interface KBStreamTextView ()

// 承载所有标签的滚动容器
@property (nonatomic, strong) UIScrollView *scrollView;
// 已创建的标签集合（顺序即显示顺序）
@property (nonatomic, strong) NSMutableArray<UILabel *> *labels;
// 文本缓冲：保存尚未遇到分隔符的尾部文本
@property (nonatomic, copy) NSString *buffer;

@end

@implementation KBStreamTextView

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self commonInit];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)coder {
    if (self = [super initWithCoder:coder]) {
        [self commonInit];
    }
    return self;
}

- (void)commonInit {
    _delimiter = @"\t";
    _labelFont = [UIFont systemFontOfSize:16.0];
    if (@available(iOS 13.0, *)) {
        _labelTextColor = [UIColor labelColor];
    } else {
        _labelTextColor = [UIColor blackColor];
    }
    _contentHorizontalPadding = 12.0;
    _interItemSpacing = 5.0; // 标签之间的垂直间距 5pt
    _labels = [NSMutableArray array];
    _buffer = @"";
    _shouldTrimSegments = YES;

    // 初始化滚动视图并填满自身
    _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
    _scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    _scrollView.alwaysBounceVertical = YES;
    _scrollView.showsVerticalScrollIndicator = YES;
    // 留一点底部余量，避免最后一行视觉上“贴底被遮住”的感觉
    _scrollView.contentInset = UIEdgeInsetsMake(0, 0, 6, 0);
    _scrollView.scrollIndicatorInsets = _scrollView.contentInset;
    [self addSubview:_scrollView];
}

#pragma mark - Helpers

// 仅去掉末尾空白/换行（保留前导空白，避免“段落在完成时向左跳动”）
static inline NSString *KBTrimRight(NSString *s) {
    if (s.length == 0) return s;
    NSCharacterSet *set = [NSCharacterSet whitespaceAndNewlineCharacterSet];
    NSInteger end = (NSInteger)s.length - 1;
    while (end >= 0 && [set characterIsMember:[s characterAtIndex:(NSUInteger)end]]) {
        end--;
    }
    if (end < 0) return @"";
    return [s substringToIndex:(NSUInteger)end + 1];
}

#pragma mark - Public API

// 边输边见：实时更新当前 label 文本，遇到分隔符就新建下一个 label
- (void)appendStreamText:(NSString *)text {
    if (text.length == 0) { return; }

    // 若在子线程被调用，切回主线程更新 UI
    if (![NSThread isMainThread]) {
        __weak typeof(self) weakSelf = self;
        dispatch_async(dispatch_get_main_queue(), ^{
            [weakSelf appendStreamText:text];
        });
        return;
    }

    // 容错：若分隔符为空，退化为直接将所有内容作为一个段落展示
    if (self.delimiter.length == 0) {
        [self ensureCurrentLabelExists];
        self.buffer = [self.buffer stringByAppendingString:text];
        self.labels.lastObject.text = self.buffer;
        [self layoutLabelsForCurrentWidth];
        [self scrollToBottomIfNeeded];
        return;
    }

    // 确保有一个“进行中”的 label
    [self ensureCurrentLabelExists];

    // 将传入文本按分隔符切分。parts.count = 分段数；分隔符数量 = parts.count - 1
    NSArray<NSString *> *parts = [text componentsSeparatedByString:self.delimiter];

    // 1) 先把第一段拼接到当前缓冲并实时显示
    self.buffer = [self.buffer stringByAppendingString:parts.firstObject ?: @""];
    self.labels.lastObject.text = self.buffer; // 不裁剪，保留实时输入
    [self layoutLabelsForCurrentWidth];

    // 2) 处理每一个分隔符：完成当前段（仅裁剪“末尾空白”）并新建空标签，然后填入下一段的内容
    for (NSUInteger i = 1; i < parts.count; i++) {
        // a) 完成当前段：对外观进行最终裁剪（若开启）
        UILabel *current = self.labels.lastObject;
        if (self.shouldTrimSegments) { current.text = KBTrimRight(current.text ?: @""); }
        [self layoutLabelsForCurrentWidth];

        // b) 新建一个空标签，代表下一个段（即刻创建，哪怕下一段当前为空）
        [self createEmptyLabelAsNewSegment];

        // c) 将该分隔符之后的这段文本作为新段的初始内容（仍旧实时显示，不裁剪）
        NSString *piece = parts[i];
        self.buffer = piece ?: @"";
        self.labels.lastObject.text = self.buffer;
        [self layoutLabelsForCurrentWidth];
    }

    [self scrollToBottomIfNeeded];
}

- (void)reset {
    for (UILabel *lbl in self.labels) {
        [lbl removeFromSuperview];
    }
    [self.labels removeAllObjects];
    self.buffer = @"";
    self.scrollView.contentSize = CGSizeMake(self.bounds.size.width, 0);
}

#pragma mark - Layout Helpers

- (void)addLabelForText:(NSString *)text {
    if (self.shouldTrimSegments) { text = KBTrimRight(text ?: @""); }
    // 创建一个可换行、可点击的 UILabel
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
    label.numberOfLines = 0;
    label.font = self.labelFont;
    label.textColor = self.labelTextColor;
    label.userInteractionEnabled = YES; // 允许点击
    label.text = text;

    // 添加点击手势
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleLabelTap:)];
    [label addGestureRecognizer:tap];

    [self.scrollView addSubview:label];
    [self.labels addObject:label];

    // 依据当前宽度立即布局
    [self layoutLabelsForCurrentWidth];

    // 滚动到底部以展示最新的标签
    [self scrollToBottomIfNeeded];
}

#pragma mark - Streaming Helpers

// 确保存在一个可供“进行中输入”的 label，不存在则新建空标签
- (void)ensureCurrentLabelExists {
    if (self.labels.lastObject) { return; }
    [self createEmptyLabelAsNewSegment];
}

// 创建一个空白的新段标签，并追加到滚动视图中
- (void)createEmptyLabelAsNewSegment {
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
    label.numberOfLines = 0;
    label.font = self.labelFont;
    label.textColor = self.labelTextColor;
    label.userInteractionEnabled = YES;
    label.text = @"";
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleLabelTap:)];
    [label addGestureRecognizer:tap];

    [self.scrollView addSubview:label];
    [self.labels addObject:label];
    self.buffer = @"";

    [self layoutLabelsForCurrentWidth];
}

- (void)finishStreaming {
    if (![NSThread isMainThread]) {
        __weak typeof(self) weakSelf = self;
        dispatch_async(dispatch_get_main_queue(), ^{
            [weakSelf finishStreaming];
        });
        return;
    }
    UILabel *current = self.labels.lastObject;
    if (!current) { return; }
    if (self.shouldTrimSegments) {
        NSString *trimmed = KBTrimRight(current.text ?: @"");
        current.text = trimmed;
        self.buffer = trimmed;
    }
    // 无论是否裁剪，都重新布局并滚动到底部，避免最后一段显示不全
    [self layoutLabelsForCurrentWidth];
    [self scrollToBottomIfNeeded];
}

- (void)layoutSubviews {
    [super layoutSubviews];
    // 处理宽度变化（例如旋转/键盘容器大小变化）时的重排
    [self layoutLabelsForCurrentWidth];
}

- (void)layoutLabelsForCurrentWidth {
    CGFloat width = self.bounds.size.width;
    if (width <= 0) { return; }

    CGFloat x = self.contentHorizontalPadding;
    CGFloat maxLabelWidth = MAX(0.0, width - 2.0 * self.contentHorizontalPadding);
    CGFloat y = self.interItemSpacing; // 顶部预留同等间距

    for (NSUInteger idx = 0; idx < self.labels.count; idx++) {
        UILabel *label = self.labels[idx];
        CGSize size = [self sizeForText:label.text font:label.font maxWidth:maxLabelWidth];
        label.frame = CGRectMake(x, y, maxLabelWidth, size.height);
        y += size.height;
        // 标签间距：下一个标签位于上一个标签下方 5pt
        if (idx + 1 < self.labels.count) {
            y += self.interItemSpacing;
        }
    }

    CGFloat contentHeight = MAX(y + self.interItemSpacing, self.bounds.size.height + 1.0);
    self.scrollView.contentSize = CGSizeMake(width, contentHeight);
}

- (CGSize)sizeForText:(NSString *)text font:(UIFont *)font maxWidth:(CGFloat)maxWidth {
    if (text.length == 0) {
        // 空文本段仍保留一行高度，保证可点击区域
        return CGSizeMake(maxWidth, font.lineHeight);
    }
    CGRect rect = [text boundingRectWithSize:CGSizeMake(maxWidth, CGFLOAT_MAX)
                                     options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
                                  attributes:@{NSFontAttributeName: font}
                                     context:nil];
    // 向上取整，避免像素裁切
    return CGSizeMake(maxWidth, ceil(rect.size.height));
}

- (void)scrollToBottomIfNeeded {
    CGFloat height = self.scrollView.bounds.size.height;
    CGFloat contentHeight = self.scrollView.contentSize.height;
    if (contentHeight > height && height > 0) {
        CGPoint bottomOffset = CGPointMake(0, contentHeight - height);
        // 使用无动画滚动，避免在短时间内多次追加时“最后一行没完全跟上”的错觉
        [self.scrollView setContentOffset:bottomOffset animated:NO];
    }
}

#pragma mark - Tap Handling

- (void)handleLabelTap:(UITapGestureRecognizer *)tap {
    UILabel *label = (UILabel *)tap.view;
    if (![label isKindOfClass:[UILabel class]]) { return; }
    NSInteger index = [self.labels indexOfObject:label];
    NSString *text = label.text ?: @"";
    if (index != NSNotFound && self.onLabelTap) {
        self.onLabelTap(index, text);
    }

    // 将文本发送到当前宿主应用的输入框（搜索框/TextView 等）
    // 注：键盘扩展无需“完全访问”也可 insertText:
    UIInputViewController *ivc = KBFindInputViewController(self);
    if (ivc) {
        id<UITextDocumentProxy> proxy = ivc.textDocumentProxy;
        if (text.length > 0 && [proxy conformsToProtocol:@protocol(UITextDocumentProxy)]) {
            [proxy insertText:text];
        }
    }
}

@end
