//
//  UIView+Extension.swift
//  SpeakEasyLearnEnglish
//
//  Created by edy on 2025/7/2.
//

import UIKit

fileprivate var state = SpeakEasyAssociatedKeys.UnsafeCallBack.rawValue
fileprivate var fontState = SpeakEasyAssociatedKeys.fontsize.rawValue
fileprivate var cutomFontsKey = SpeakEasyAssociatedKeys.labelTextCutomFont.rawValue


@IBDesignable
extension UIView : CutomFontProtocol {
    
    @objc func setCutomFonts() {
        
    }
    
    @objc public var callblack:((Any)->Void)? {
        set {
            objc_setAssociatedObject(self, &state, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        get {
            return objc_getAssociatedObject(self, &state) as? ((Any)->Void)
        }
    }
    
    @objc private func gestureTouches(_ ches:UIGestureRecognizer) -> Void {
        guard let call = callblack else { return }
        call(ches)
    }
    
    @discardableResult
    /// 添加手势
    func gesture(gesture:UIView.Gesture,_ complate:((Any)->Void)?) -> UIGestureRecognizer? {
        var ges:UIGestureRecognizer?
        callblack = complate
        switch gesture {
        case .tap:
            self.gestureRecognizers?.filter({$0 is UITapGestureRecognizer}).forEach({self.removeGestureRecognizer($0)})
            ges = UITapGestureRecognizer(target: self, action: #selector(gestureTouches(_:)))
            break
        case .swipe:
            self.gestureRecognizers?.filter({$0 is UISwipeGestureRecognizer}).forEach({self.removeGestureRecognizer($0)})
            ges = UISwipeGestureRecognizer(target: self, action: #selector(gestureTouches(_:)))
            break
        case .long:
            self.gestureRecognizers?.filter({$0 is UILongPressGestureRecognizer}).forEach({self.removeGestureRecognizer($0)})
            ges = UILongPressGestureRecognizer(target: self, action: #selector(gestureTouches(_:)))
            break
        case .pan:
            self.gestureRecognizers?.filter({$0 is UIPanGestureRecognizer}).forEach({self.removeGestureRecognizer($0)})
            ges = UIPanGestureRecognizer(target: self, action: #selector(gestureTouches(_:)))
            break
        case .pinch:
            self.gestureRecognizers?.filter({$0 is UIPinchGestureRecognizer}).forEach({self.removeGestureRecognizer($0)})
            ges = UIPinchGestureRecognizer(target: self, action: #selector(gestureTouches(_:)))
            break
        case .rotation:
            self.gestureRecognizers?.filter({$0 is UIRotationGestureRecognizer}).forEach({self.removeGestureRecognizer($0)})
            ges = UIRotationGestureRecognizer(target: self, action: #selector(gestureTouches(_:)))
            break
        case .edgePan:
            self.gestureRecognizers?.filter({$0 is UIScreenEdgePanGestureRecognizer}).forEach({self.removeGestureRecognizer($0)})
            ges = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(gestureTouches(_:)))
            break
        }
        guard let gesture = ges else { return ges }
        self.addGestureRecognizer(gesture)
        return gesture
    }
    
    /// 添加手势
    @discardableResult
    public func gesture(target delegate:Any, class gestureCls:UIGestureRecognizer.Type ,selector:Selector) -> UIGestureRecognizer {
        let recognizer = gestureCls.init()
        self.isUserInteractionEnabled = true
        recognizer.addTarget(delegate, action: selector)
        self.addGestureRecognizer(recognizer)
        return recognizer
    }
    
    /// 圆角
    @IBInspectable var corners:Double {
        set {
            self.layer.cornerRadius = newValue
            self.clipsToBounds = true
        }
        get {
            return self.layer.cornerRadius
        }
    }
    
    /// 边框颜色
    @IBInspectable var borderColor:UIColor {
        set {
            self.layer.borderColor = newValue.cgColor
            self.clipsToBounds = true
        }
        get {
            return UIColor(cgColor: self.layer.borderColor ?? UIColor.clear.cgColor)
        }
    }
    /// 边框宽度
    @IBInspectable var borderWidth:Double {
        set {
            self.layer.borderWidth = newValue
        }
        get {
            return self.layer.borderWidth
        }
    }
    
    @IBInspectable var fontSize:CGFloat {
        set {
            objc_setAssociatedObject(self, &fontState, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        get {
            let size = objc_getAssociatedObject(self, &fontState) as? CGFloat
            return size ?? 12
        }
    }
    
    @IBInspectable var cutomFont:Int {
        set {
            objc_setAssociatedObject(self, &cutomFontsKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.02) {
                self.setCutomFonts()
            }
        }
        get {
            return objc_getAssociatedObject(self, &cutomFontsKey) as? Int ?? -1
        }
    }
    
    
    /** 获取当前控制器 */
    func responderCtr() -> UIViewController? {
        for view in sequence(first: self.superview, next: { $0?.superview }) {
            if let responder = view?.next {
                if responder.isKind(of: UIViewController.self){
                    return responder as? UIViewController
                }
            }
        }
        return nil
    }
    
    /** 设置圆角 */
    public func cornerRect(radius:CGFloat ,_ rectCorner:UIRectCorner) {
        let maskPath = UIBezierPath.init(roundedRect: bounds, byRoundingCorners: rectCorner, cornerRadii: CGSize.init(width: radius, height: radius))
        let maskLayer = CAShapeLayer()
        maskLayer.frame = bounds
        maskLayer.path = maskPath.cgPath
        layer.mask = maskLayer
    }
    
    /** 设置阴影 */
    public func shadow(cornerRadius:CGFloat = 4, shadowColor:UIColor = .clear, offset:CGSize = CGSize(width: 0, height: 0), opacity:Float = 1, radius:CGFloat = 0 ,_ path:CGPath? = nil) {
        self.layer.masksToBounds = false
        self.layer.shadowColor = shadowColor.cgColor
        self.layer.shadowOpacity = opacity
        self.layer.shadowOffset = offset
        if path == nil {
            self.layer.shadowRadius = radius
            self.layer.cornerRadius = cornerRadius
        }else{
            self.layer.shadowPath = path
        }
    }
    
    public func shadowPath(radius:CGFloat = 0 , shadowColor:UIColor = .clear,offset:CGSize = CGSize() ,opacity:Float = 1,path:CGPath) -> Void {
        layer.shadowColor = shadowColor.cgColor
        layer.shadowOffset = offset
        layer.shadowOpacity = opacity
        layer.shadowPath = path
    }
    
    /// 添加渐变
    func gradient(colors: [UIColor], direction: gradientTion = .leftToRight, cornerRadius: CGFloat = 0) {
        self.layer.sublayers?.filter { $0 is CAGradientLayer }.forEach { $0.removeFromSuperlayer() }
        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = colors.map { $0.cgColor }
        gradientLayer.locations = [0.0, 1.0] // 渐变位置
        gradientLayer.startPoint = direction.startPoint
        gradientLayer.endPoint = direction.endPoint
        gradientLayer.frame = self.bounds
        gradientLayer.cornerRadius = cornerRadius
        gradientLayer.zPosition = -10
        self.layer.insertSublayer(gradientLayer, at: 0)
    }
    
    /// 为视图的指定边添加阴影
    /// - Parameters:
    ///   - edge: 要添加阴影的边
    ///   - shadowColor: 阴影颜色，默认为黑色
    ///   - shadowOpacity: 阴影透明度，默认为 0.5
    ///   - shadowRadius: 阴影半径，默认为 5
    ///   - shadowSpread: 阴影扩展距离，默认为 0
    func addShadow(to edge: [UIRectEdge], shadowColor: UIColor = .black, shadowOpacity: Float = 0.5, shadowRadius: CGFloat = 5, shadowSpread: CGFloat = 0) {
        layer.masksToBounds = false
        layer.shadowColor = shadowColor.cgColor
        layer.shadowOpacity = shadowOpacity
        layer.shadowRadius = shadowRadius
        let size = bounds.size
        let path = CGMutablePath()
        if edge.contains(.top) {
            let r = CGRect(x: 0, y: -shadowSpread, width: size.width, height: shadowRadius + shadowSpread)
            path.addRect(r)
        }
        if edge.contains(.left) {
            let r = CGRect(x: -shadowSpread, y: 0, width: shadowRadius + shadowSpread, height: size.height)
            path.addRect(r)
        }
        if edge.contains(.bottom) {
            let r = CGRect(x: 0, y: size.height - shadowRadius, width: size.width, height: shadowRadius + shadowSpread)
            path.addRect(r)
        }
        if edge.contains(.right) {
            let r = CGRect(x: size.width - shadowRadius, y: 0, width: shadowRadius + shadowSpread, height: size.height)
            path.addRect(r)
        }
        layer.shadowPath = path
    }
    
    enum Gesture{
        case tap
        case long
        case swipe
        case pan
        case pinch
        case rotation
        case edgePan
    }
    
    enum gradientTion {
        case leftToRight
        case topToBottom
        case topLeftToBottomRight
        case topRightToBottomLeft

        var startPoint: CGPoint {
            switch self {
            case .leftToRight:
                return CGPoint(x: 0.0, y: 0.5)
            case .topToBottom:
                return CGPoint(x: 0.5, y: 0.0)
            case .topLeftToBottomRight:
                return CGPoint(x: 0.0, y: 0.0)
            case .topRightToBottomLeft:
                return CGPoint(x: 1.0, y: 0.0)
            }
        }

        var endPoint: CGPoint {
            switch self {
            case .leftToRight:
                return CGPoint(x: 1.0, y: 0.5)
            case .topToBottom:
                return CGPoint(x: 0.5, y: 1.0)
            case .topLeftToBottomRight:
                return CGPoint(x: 1.0, y: 1.0)
            case .topRightToBottomLeft:
                return CGPoint(x: 0.0, y: 1.0)
            }
        }
    }
}

/// frame
extension UIView {
    
    var x :CGFloat {
        get {
            return frame.origin.x
        }
        set {
            var frame1:CGRect = frame
            frame1.origin.x = newValue
            frame = frame1
        }
    }
    
    var y :CGFloat {
        get {
            return frame.origin.y
        }
        
        set {
            var frame1:CGRect = frame
            frame1.origin.y = newValue
            frame = frame1
            
        }
    }
    
    var width :CGFloat {
        get {
            return frame.size.width
        }
        set {
            var frame1:CGRect = frame
            frame1.size.width = newValue
            frame = frame1
        }
    }
    
    var height :CGFloat {
        
        get {
            return frame.size.height
        }
        
        set {
            var frame1:CGRect = frame
            frame1.size.height = newValue
            frame = frame1
        }
    }
    
    var size :CGSize {
        get {
            return frame.size
        }
        
        set {
            var frame1:CGRect = frame
            frame1.size = newValue
            frame = frame1
            
        }
    }
    
    var centerX :CGFloat {
        
        get {
            return center.x
        }
        
        set {
            var center1:CGPoint = center
            center1.x = newValue
            center = center1
        }
    }
    
    var centerY :CGFloat {
        
        get {
            return center.y
        }
        
        set {
            var center1:CGPoint = center
            center1.y = newValue
            center = center1
        }
    }
}
