//
//  String+TUIEmoji.swift
//  Lanu
//
//  Created by OneeChan on 2025/12/17.
//

import Foundation


private class LNEmojiDescContent {
    var range: NSRange
    var string: String
    
    init(range: NSRange, string: String) {
        self.range = range
        self.string = string
    }
}


private class LNEnojiImageContent {
    var range: NSRange
    var string: NSAttributedString
    
    init(range: NSRange, string: NSAttributedString) {
        self.range = range
        self.string = string
    }
}

extension String {
    private static var regex_emoji = "\\[[a-zA-Z0-9_\\u4e00-\\u9fa5]+\\]"
    
    var getEmojiDescContent: String {
        var content = self
        
        guard let emojiGroup = LNIMEmojiManager.shared.emojiGroup else { return content }
        
        let re = try? NSRegularExpression(pattern: Self.regex_emoji, options: .caseInsensitive)
        guard let re else { return content }
        
        let resultArray = re.matches(in: content, options: [], range: .init(location: 0, length: content.count))
        var waitingReplaceM: [LNEmojiDescContent] = []
        for match in resultArray {
            guard let range = Range(match.range, in: content) else {
                continue
            }
            let subStr = String(content[range])
            guard let emoji = emojiGroup.emojiFor(subStr) else { continue }
            let text = emoji.localizableName.isEmpty ? emoji.name : emoji.localizableName
            
            let content = LNEmojiDescContent(range: match.range, string: text)
            waitingReplaceM.append(content)
        }
        guard !waitingReplaceM.isEmpty else { return content }
        for item in waitingReplaceM.reversed() {
            guard let range = Range(item.range, in: content) else { continue }
            content = content.replacingCharacters(in: range, with: item.string)
        }
        
        return content
    }
    
    func getEmojiString(with font: UIFont) -> NSMutableAttributedString {
        let content = NSMutableAttributedString(string: self)
        
        guard let emojiGroup = LNIMEmojiManager.shared.emojiGroup else { return content }
        
        let re = try? NSRegularExpression(pattern: Self.regex_emoji, options: .caseInsensitive)
        
        guard let re else { return content }
        let resultArray = re.matches(in: self, options: [], range: .init(location: 0, length: count))
        var waitingReplaceM: [LNEnojiImageContent] = []
        for match in resultArray {
            guard let range = Range(match.range, in: self) else {
                continue
            }
            let subStr = String(self[range])
            
            guard let emoji = emojiGroup.emojiFor(subStr) else { continue }
            let attachment = LNIMChatEmojiAttachment()
            attachment.name = emoji.name
            attachment.font = font
            attachment.image = LNIMEmojiManager.shared.getFaceFromCache(path: emoji.path)
            let attachStr = NSAttributedString(attachment: attachment)
            
            let content = LNEnojiImageContent(range: match.range, string: attachStr)
            waitingReplaceM.append(content)
        }
        guard !waitingReplaceM.isEmpty else { return content }
        for item in waitingReplaceM.reversed() {
            content.replaceCharacters(in: item.range, with: item.string)
        }
        
        return content
    }
}

extension NSAttributedString {
    var toEmojiContent: String {
        let sourceStr = NSMutableAttributedString(attributedString: self)
        
        var waitingReplaceM: [LNEmojiDescContent] = []
        sourceStr.enumerateAttribute(.attachment, in: .init(location: 0, length: sourceStr.length))
        { value, range, _ in
            if let emoji = value as? LNIMChatEmojiAttachment {
                waitingReplaceM.append(LNEmojiDescContent(range: range, string: emoji.name))
            }
        }
        
        for item in waitingReplaceM.reversed() {
            sourceStr.replaceCharacters(in: item.range, with: item.string)
        }
        return sourceStr.string
    }
}
