//
//  TUIBotRichTextCell.m
//  TUICustomerServicePlugin
//
//  Created by lynx on 2024/3/1.
//  Copyright © 2024 Tencent. All rights reserved.
//

#import "TUIBotRichTextCell.h"
#import <TUIChat/TUITextMessageCell.h>
#import <TIMCommon/TIMDefine.h>
#import <TUICore/TUICore.h>
#import <WebKit/WebKit.h>

@interface TUIBotRichTextCell ()<WKNavigationDelegate>
@property(nonatomic, strong) WKWebView *webView;
@property(nonatomic, strong) UIColor *webViewBkColor;
@property(nonatomic, strong) UIColor *webViewTextColor;
@end

@implementation TUIBotRichTextCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        [self.container addSubview:self.webView];
        self.webViewTextColor = [TUITextMessageCell incommingTextColor];
    }
    return self;
}

- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
    self.webViewBkColor = nil;
    [self.webView evaluateJavaScript:[NSString stringWithFormat:@"document.body.style.backgroundColor=\"%@\"",
                                      [self hexStringFromColor:self.webViewBkColor]] completionHandler:nil];
    [self.webView evaluateJavaScript:[NSString stringWithFormat:@"document.getElementById('content').style.color=\"%@\"",
                                      [self hexStringFromColor:self.webViewTextColor]] completionHandler:nil];
}

- (WKWebView *)webView {
    if (!_webView) {
        WKWebViewConfiguration *config = [WKWebViewConfiguration new];
        NSString *script = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";
        WKUserScript *wkUserScript = [[WKUserScript alloc] initWithSource:script injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
        WKUserContentController *wkUserController = [[WKUserContentController alloc] init];
        [wkUserController addUserScript: wkUserScript];
        config.userContentController = wkUserController;
        _webView = [[WKWebView alloc]initWithFrame:self.bounds configuration:config];
        _webView.navigationDelegate = self;
        _webView.backgroundColor = [UIColor clearColor];
        [_webView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
        _webView.scrollView.scrollEnabled = NO;
        
        NSString *bundlePath = TUIBundlePath(TUICustomerServicePluginBundle,TUICustomerServicePluginBundle_Key_Class);
        NSString *path = [bundlePath stringByAppendingPathComponent:@"markdown.html"];
        if (path) {
            NSURL *url = [NSURL fileURLWithPath:path];
            NSURLRequest *requset = [NSURLRequest requestWithURL:url];
            [_webView loadRequest:requset];
        }
    }
    return _webView;
}

- (UIColor *)webViewBkColor {
    if (!_webViewBkColor && self.bubbleView.image) {
        UIImage *image = [self.bubbleView.image.imageAsset imageWithTraitCollection:[UITraitCollection currentTraitCollection]];
        _webViewBkColor = [self colorFromImage:image point:CGPointMake(trunc(10), trunc(10))];
    }
    return _webViewBkColor;
}

- (void)layoutSubviews {
    [super layoutSubviews];
}

// this is Apple's recommended place for adding/updating constraints
- (void)updateConstraints {
    [super updateConstraints];
    [self.webView mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.leading.mas_equalTo(10);
        make.top.mas_equalTo(2);
        make.width.mas_equalTo(self.container.mm_w - 10 * 2);
        make.height.mas_equalTo(self.container.mm_h - 2 * 2);
    }];
}

- (void)fillWithData:(TUIBotRichTextCellData *)data {
    // set data
    [super fillWithData:data];
    self.webViewData = data;
    [self loadMarkdownContent];
    
    // tell constraints they need updating
    [self setNeedsUpdateConstraints];

    // update constraints now so we can animate the change
    [self updateConstraintsIfNeeded];

    [self layoutIfNeeded];
}

- (void)loadMarkdownContent {
    NSString *content = [self getMarkdownContentWithMarkdowString:self.webViewData.content];
    NSString *js = [NSString stringWithFormat:@"javascript:parseMarkdown(\"%@\",true)", content];
    [self.webView evaluateJavaScript:js completionHandler:nil];
    // Set webview background color
    [self.webView evaluateJavaScript:[NSString stringWithFormat:@"document.body.style.backgroundColor=\"%@\"",
                                      [self hexStringFromColor:self.webViewBkColor]] completionHandler:nil];
    // Set webview text color
    [self.webView evaluateJavaScript:[NSString stringWithFormat:@"document.getElementById('content').style.color=\"%@\"",
                                      [self hexStringFromColor:self.webViewTextColor]] completionHandler:nil];
    // Webview disables sliding and zooming
    NSString *injectionJSString = @"var script = document.createElement('meta');script.name = 'viewport';"
                                   "script.content=\"width=device-width, user-scalable=no\";"
                                   "document.getElementsByTagName('head')[0].appendChild(script);";
    [self.webView evaluateJavaScript:injectionJSString completionHandler:nil];
}

- (NSString *)getMarkdownContentWithMarkdowString:(NSString *)markdown {
    markdown = [markdown stringByReplacingOccurrencesOfString:@"\r"withString:@""];
    markdown = [markdown stringByReplacingOccurrencesOfString:@"\n"withString:@"\\n"];
    markdown = [markdown stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""];
    markdown = [markdown stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"];
    markdown = [markdown stringByReplacingOccurrencesOfString:@"<br>" withString:@"\\n"];
    return markdown;
}

#pragma mark - TUIMessageCellProtocol
+ (CGSize)getContentSize:(TUIMessageCellData *)data {
    if ([data isKindOfClass:[TUIBotRichTextCellData class]]) {
        return CGSizeMake(TRichTextMessageCell_Width_Max, [(TUIBotRichTextCellData *)data cellHeight]);
    }
    return CGSizeZero;
}

#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    [self loadMarkdownContent];
    [self updateCellSize];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if ([keyPath isEqualToString:@"contentSize"]) {
        [self limitUpdateCellSize];
    }
}

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    if (navigationAction.navigationType == WKNavigationTypeLinkActivated) {
        if ([[UIApplication sharedApplication] canOpenURL:navigationAction.request.URL]) {
            [[UIApplication sharedApplication] openURL:navigationAction.request.URL options:@{} completionHandler:nil];
        }
        decisionHandler(WKNavigationActionPolicyCancel);
    } else {
        decisionHandler (WKNavigationActionPolicyAllow);
    }
}

- (void)limitUpdateCellSize {
    uint64_t curTs = [[NSDate date] timeIntervalSince1970];
    uint64_t interval = 1; // s
    if (curTs - self.webViewData.lastUpdateTs >= interval && self.webViewData.lastUpdateTs) {
        self.webViewData.lastUpdateTs = curTs;
        [self updateCellSize];
    } else {
        if (self.webViewData.delayUpdate) {
            return;
        }
        self.webViewData.delayUpdate = YES;
        @weakify(self)
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(interval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            @strongify(self)
            [self updateCellSize];
            self.webViewData.delayUpdate = NO;
        });
    }
}

- (void)updateCellSize {
    @weakify(self);
    [self.webView evaluateJavaScript:@"document.body.scrollWidth" completionHandler:^(id _Nullable result,NSError *_Nullable error) {
        CGFloat scrollWidth= [result doubleValue];
        [self.webView evaluateJavaScript:@"document.body.scrollHeight"completionHandler:^(id _Nullable result,NSError*_Nullable error) {
            @strongify(self)
            CGFloat scrollHeight = [result doubleValue];
            CGFloat ratio =  CGRectGetWidth(self.webView.frame) /scrollWidth;
            CGFloat webHeight = scrollHeight * ratio;
            if (self.webViewData.cellHeight != webHeight) {
                self.webViewData.cellHeight = webHeight;
                [self notifyCellSizeChanged];
            }
        }];
    }];
}

- (void)notifyCellSizeChanged {
    NSDictionary *param = @{TUICore_TUIPluginNotify_PluginViewSizeChangedSubKey_Message : self.webViewData.innerMessage};
    [TUICore notifyEvent:TUICore_TUIPluginNotify
                  subKey:TUICore_TUIPluginNotify_PluginViewSizeChangedSubKey
                  object:nil
                   param:param];
}

#pragma mark Util
- (UIColor *)colorFromImage:(UIImage *)image point:(CGPoint)point {
    CGImageRef cgImage = image.CGImage;
    NSUInteger width = image.size.width;
    NSUInteger height = image.size.height;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    int bytesPerPixel = 4;
    int bytesPerRow = bytesPerPixel * 1;
    NSUInteger bitsPerComponent = 8;
    unsigned char pixelData[4] = { 0, 0, 0, 0 };
    CGContextRef context = CGBitmapContextCreate(pixelData,
                                                 1,
                                                 1,
                                                 bitsPerComponent,
                                                 bytesPerRow,
                                                 colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);
    CGContextSetBlendMode(context, kCGBlendModeCopy);

    // Draw the pixel we are interested in onto the bitmap context
    CGContextTranslateCTM(context, -point.x, point.y-(CGFloat)height);
    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), cgImage);
    CGContextRelease(context);

    // Convert color values [0..255] to floats [0.0..1.0]
    CGFloat red   = (CGFloat)pixelData[0] / 255.0f;
    CGFloat green = (CGFloat)pixelData[1] / 255.0f;
    CGFloat blue  = (CGFloat)pixelData[2] / 255.0f;
    CGFloat alpha = (CGFloat)pixelData[3] / 255.0f;
    return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
}

- (NSString *)hexStringFromColor:(UIColor *)color {
    if (!color) {
        return @"";
    }
    const CGFloat *components = CGColorGetComponents(color.CGColor);

    CGFloat r = components[0];
    CGFloat g = components[1];
    CGFloat b = components[2];

    return [NSString stringWithFormat:@"#%02lX%02lX%02lX",
            lroundf(r * 255),
            lroundf(g * 255),
            lroundf(b * 255)];
}

@end
