//
//  UILabel+Extension.swift
//  SpeakEasyLearnEnglish
//
//  Created by edy on 2025/7/3.
//

import UIKit
import CoreText

fileprivate var textTapState = SpeakEasyAssociatedKeys.labelTextTap.rawValue
fileprivate var contentState = SpeakEasyAssociatedKeys.contentLabelState.rawValue

@IBDesignable
extension UILabel {
    
    /// 给文字设置边框
    func textBorder(width:Double = 1 ,color:UIColor = .clear) -> Void {
        self.attributedText = NSAttributedString(string: self.text ?? "", attributes: [NSAttributedString.Key.strokeWidth:-abs(width) ,
                                                                                       NSAttributedString.Key.strokeColor:color ,
                                                                                       NSAttributedString.Key.foregroundColor:UIColor.white])
        self.sizeToFit()
    }
    
    
    var contentInsets: UIEdgeInsets {
       get {
           return objc_getAssociatedObject(self, &contentState) as? UIEdgeInsets ?? UIEdgeInsets()
       }
       set {
           objc_setAssociatedObject(self, &contentState, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
       }
    }

    /// 设置文字间距
    func lineSpacing(_ lineSpacing:CGFloat = 5) {
        let style = NSMutableParagraphStyle()
        style.lineSpacing = lineSpacing
        style.alignment = self.textAlignment
        self.attributedText = NSAttributedString(string: self.text ?? "", attributes: [NSAttributedString.Key.paragraphStyle: style])
        self.sizeToFit()
    }
    
    
    override func setCutomFonts() {
        if cutomFont >= 0 {
            switch cutomFont {
            case 0:
                self.font = UIFont.montserrat(.regular ,size: fontSize)
                break
            case 1:
                self.font = UIFont.montserrat(.medium ,size: fontSize)
                break
            case 2:
                self.font = UIFont.montserrat(.semiBold ,size: fontSize)
                break
            default:
                self.font = UIFont.montserrat(.bold ,size: fontSize)
                break
            }
        }
    }
    
    var textTaps:[String] {
        set {
            objc_setAssociatedObject(self, &textTapState, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        get {
            return objc_getAssociatedObject(self, &textTapState) as? [String] ?? []
        }
    }
    
    func AddTextTap(_ text:[String]) -> Void {
        if text.count > 0 {
            textTaps = text
            self.gesture(target: self, class: UITapGestureRecognizer.self, selector: #selector(handleTap(_:)))
        }
    }
    
    @objc private func handleTap(_ gesture: UITapGestureRecognizer) {
        // 确保有文本和布局
        let attributedText = self.attributedText ?? NSAttributedString(string: text ?? "")
        if attributedText.string.count <= 0 {
            return
        }

        let layoutManager = NSLayoutManager()
        let textContainer = NSTextContainer(size: bounds.size)
        let textStorage = NSTextStorage(attributedString: attributedText)
        
        textContainer.lineFragmentPadding = 0
        textContainer.maximumNumberOfLines = numberOfLines
        textContainer.lineBreakMode = lineBreakMode
        
        layoutManager.addTextContainer(textContainer)
        textStorage.addLayoutManager(layoutManager)
        
        let textRect = self.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
        
        var adjustedPoint = gesture.location(in: self)
        switch textAlignment {
        case .center:
            adjustedPoint.x -= (bounds.width - textRect.width) / 2
        case .right, .justified, .natural:
            adjustedPoint.x -= (bounds.width - textRect.width)
        default:
            break
        }
        let characterIndex = layoutManager.characterIndex(for: adjustedPoint,
                                                       in: textContainer,
                                                       fractionOfDistanceBetweenInsertionPoints: nil)
        for (_,v) in textTaps.enumerated() {
            if let range = attributedText.string.range(of: v) {
                let rangeN = NSRange(range, in: attributedText.string)
                
                if characterIndex < (rangeN.location + rangeN.length) && characterIndex >= rangeN.location {
                    guard let callblack = callblack else { return }
                    Print(characterIndex,attributedText.string.count)
                    callblack(v)
                    return
                }
            }
        }
    }
    
    static func swizzleLabel() {
        guard let originalMethod = class_getInstanceMethod(UILabel.self, #selector(draw(_:))),
              let swizzledMethod = class_getInstanceMethod(UILabel.self, #selector(swizzled_draw(_:))) else { return }
        method_exchangeImplementations(originalMethod, swizzledMethod)
        
        guard let originalMethod1 = class_getInstanceMethod(UILabel.self, #selector(textRect(forBounds: limitedToNumberOfLines:)) ),
              let swizzledMethod1 = class_getInstanceMethod(UILabel.self, #selector(swizzled_textRect(forBounds: limitedToNumberOfLines:) ) )  else { return }
        method_exchangeImplementations(originalMethod1, swizzledMethod1)
    }
    
    @objc public func swizzled_draw(_ rect: CGRect) {
        self.swizzled_draw(rect.inset(by: contentInsets))
    }
    
    @objc public func swizzled_textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect {
        let insets = contentInsets
        var rect = self.swizzled_textRect(forBounds: bounds.inset(by: insets),
                                limitedToNumberOfLines: numberOfLines)
        rect.origin.x -= insets.left
        rect.origin.y -= insets.top
        rect.size.width += (insets.left + insets.right)
        rect.size.height += (insets.top + insets.bottom)
        return rect
    }
}

