//
//  MWIconFont.swift
//  Test
//
//  Created by MYK on 2019/5/2.
//  Copyright © 2019 MYK. All rights reserved.
//

import UIKit

/// IconFont
@objcMembers open class MWIconFont: UIFont, @unchecked Sendable {
    static func printIconCodeEnum() {
            guard let fileURL = Bundle.main.url(forResource: "iconfont", withExtension: "json"),
                  let data = try? Data(contentsOf: fileURL),
                  let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
                  let root = try? JSONDecoder().decode(IconFontRootModel.self, from: data) else {
                print("Error loading or parsing JSON file")
                return
            }
            
            let list = root.glyphs
            var set: [String] = []
            
            for obj in list {
                // Convert name to camelCase and make first character lowercase
                var name = obj.name
                    .replacingOccurrences(of: "-", with: "_")
                    .replacingOccurrences(of: " ", with: "_")
                
                // Simple camelCase conversion (you might need a more sophisticated version)
                let components = name.components(separatedBy: "_")
                name = components.enumerated().map { (index, component) in
                    index == 0 ? component.lowercased() : component.capitalized
                }.joined()
                
                let code = obj.unicode
                let result = "case \(name) = 0x\(code)"
                set.append(result)
            }
            
            let printStr = set.joined(separator: "\n")
            print("\n\(printStr)\n")
        }
    
    private class func iconFont(_ size: CGFloat) -> UIFont? {
        if size == 0.0 {
            return nil
        }
        let iconfont = "iconfont" // 字体的名字
        loadMyCustomFont(iconfont)
        return UIFont(name: iconfont, size: size)
    }

    private class func loadMyCustomFont(_ name: String) {
        guard let fontPath = Bundle(for: MWIconFont.self).path(forResource: name, ofType: "ttf") else {
            return
        }
        var error: Unmanaged<CFError>?
        guard let data = try? Data(contentsOf: URL(fileURLWithPath: fontPath)),
              let provider = CGDataProvider(data: data as CFData)
        else {
            return
        }
        if let font = CGFont(provider) {
            CTFontManagerRegisterGraphicsFont(font, &error)
            if error != nil {
                return
            }
        }
    }

    /// 将Int类型的转为String类型的Unicode码，eg: 0xe624 -> \u{E624}
    private class func stringForIcon(_ iconInt: UInt32) -> String? {
        var rawIcon = iconInt
        let xPtr = withUnsafeMutablePointer(to: &rawIcon) { $0 }
        return String(bytesNoCopy: xPtr,
                      length: MemoryLayout<UInt32>.size,
                      encoding: String.Encoding.utf32LittleEndian,
                      freeWhenDone: false)
    }

    /// 生成IconFont
    ///
    /// - Parameters:
    ///   - iconInt: Unicode-Int类型的 eg: 0xe624
    ///   - size: fontSize
    ///   - color: fontColor
    /// - Returns: font?
    @objc public class func attributedString(
        fromIconInt iconInt: UInt32,
        size: CGFloat,
        color: UIColor?) -> NSAttributedString?
    {
        guard let string = stringForIcon(iconInt) else {
            return nil
        }
        return MWIconFont.attributedString(fromIconStr: string, size: size, color: color)
    }

    /// 生成IconFont
    ///
    /// - Parameters:
    ///   - iconStr: Unicode-String类型的 eg: "\u{E624}"
    ///   - size: fontSize
    ///   - color: fontColor
    /// - Returns: font?
    @objc public class func attributedString(
        fromIconStr iconStr: String,
        size: CGFloat,
        color: UIColor?) -> NSAttributedString?
    {
        guard let font = MWIconFont.iconFont(size) else {
            return nil
        }
        var attributes = [NSAttributedString.Key: AnyObject]()
        attributes[NSAttributedString.Key.font] = font
        if let color = color {
            attributes[NSAttributedString.Key.foregroundColor] = color
        }
        return NSAttributedString(string: iconStr, attributes: attributes)
    }

    /// iconfont生成image
    ///
    /// - Parameters:
    ///   - iconInt: Unicode-Int类型的 eg: 0xe624
    ///   - size: 图片宽高
    ///   - color: 图片颜色
    /// - Returns: image?
    @objc public class func image(
        fromIconInt iconInt: UInt32,
        size: CGSize,
        color: UIColor?,
        edgeInsets: UIEdgeInsets = UIEdgeInsets.zero) -> UIImage?
    {
        guard let string = stringForIcon(iconInt) else {
            return nil
        }
        return MWIconFont.image(fromIconStr: string, size: size, color: color, edgeInsets: edgeInsets)
    }
    
    @objc public class func image(
        fromIcon iconEnum: IconCode,
        size: CGSize,
        color: UIColor?,
        edgeInsets: UIEdgeInsets = UIEdgeInsets.zero) -> UIImage?
    {
        guard let string = stringForIcon(iconEnum.rawValue) else {
            return nil
        }
        return MWIconFont.image(fromIconStr: string, size: size, color: color, edgeInsets: edgeInsets)
    }

    /// iconfont生成image
    ///
    /// - Parameters:
    ///   - iconStr: Unicode-String类型的 eg: "\u{E624}"
    ///   - size: 图片宽高
    ///   - color: 图片颜色
    /// - Returns: image?
    private class func image(
        fromIconStr iconStr: String,
        size: CGSize,
        color: UIColor?,
        edgeInsets: UIEdgeInsets = UIEdgeInsets.zero) -> UIImage?
    {
        if size == CGSize.zero {
            return nil
        }
        let pointSize = min(size.width, size.height)
        guard let aString = MWIconFont.attributedString(fromIconStr: iconStr, size: pointSize, color: color) else {
            return nil
        }
        let mString = NSMutableAttributedString(attributedString: aString)

        var rect = CGRect(origin: CGPoint.zero, size: size)
        rect.origin.y -= edgeInsets.top
        rect.size.width -= edgeInsets.left + edgeInsets.right // 运算符优先级注意
        rect.size.height -= edgeInsets.top + edgeInsets.bottom

        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.alignment = .center

        let range = NSRange(location: 0, length: mString.length)

        mString.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: range)
        // render the attributed string as image using Text Kit
        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
        mString.draw(in: rect)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return image
    }
}

struct IconFontRootModel: Codable {
    let glyphs: [IconFontModel]
}

struct IconFontModel: Codable {
    let name: String
    let unicode: String
}
