//
//  PrinterManager.swift
//  HYUtility
//
//  Created by ldc on 2024/3/26.
//  Copyright © 2024 swiftHY. All rights reserved.
//

import Foundation
import PrinterSDK
import RYCommunication

class ConnectStatusListener: NSObject {
    
    let block: (S1V1ProtocolPrinter, RYAccessoryConnectStatus) -> Void
    
    init(block: @escaping (S1V1ProtocolPrinter, RYAccessoryConnectStatus) -> Void) {
        self.block = block
    }
}

extension RYAccessoryConnectStatus: @retroactive CustomStringConvertible {
    
    public var description: String {
        
        switch self {
        case .disconnected:
            return "未连接".localized
        case .connecting:
            return "连接中".localized
        case .connected:
            return "已连接".localized
        case .disconnecting:
            return "断开连接中".localized
        @unknown default:
            return "未连接".localized
        }
    }
}

extension RYAccessory {
    
    func connectWithResult(complete: @escaping ((Result<Void, Error>) -> Void)) -> Void {
        connect {
            complete(.success(()))
        } fail: { error in
            complete(.failure(error))
        }

    }
}

extension S1V1ProtocolPrinter {
    
    struct Key {
        static var escPrinter = 0
        static var cpclPrinter = 0
    }
    
    
    /// 从通用设备创建ESC打印机实例
    /// - Warning: 这里这样写是为了应用方便访问不同类型的打印机 <br>实际应用连接前创建需要的实例即可
    var escPrinter : S1ESCPrinter {
        if let temp = objc_getAssociatedObject(self, &Key.escPrinter) as? S1ESCPrinter {
            return temp
        }
        let temp = S1ESCPrinter(self.accessory as! RYBaseAccessory)
        objc_setAssociatedObject(self, &Key.escPrinter, temp, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        return temp
    }
    
    var cpclPrinter : S1CPCLPrinter {
        if let temp = objc_getAssociatedObject(self, &Key.cpclPrinter) as? S1CPCLPrinter {
            return temp
        }
        let temp = S1CPCLPrinter(self.accessory as! RYBaseAccessory)
        objc_setAssociatedObject(self, &Key.cpclPrinter, temp, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        return temp
    }
    
//    // MARK: - WiFi热点扫描
//    /// 获取WiFi热点列表
//    /// - Parameter completion: 完成回调，返回WiFi热点信息数组
//    func getWifiHotspots(completion: @escaping (Result<[WifiHotspotInfo], Error>) -> Void) {
//        // 使用getPrinterWifiHotspots方法获取数据
//        getPrinterWifiHotspots { [weak self] data, error in
//            if let error = error {
//                completion(.failure(error))
//                return
//            }
//            
//            guard let data = data else {
//                completion(.failure(NSError(domain: "WifiHotspots", code: -1, userInfo: [NSLocalizedDescriptionKey: "未获取到WiFi热点数据"])))
//                return
//            }
//            
//            // 解析返回的数据
//            let hotspots = self?.parseWifiHotspotsData(data) ?? []
//            completion(.success(hotspots))
//        }
//    }
    
    
}

// MARK: - WiFi热点信息模型
struct WifiHotspotInfo {
    let index: String        // n/m 格式
    let name: String         // 热点名称
    let security: String     // 加密协议
    let encryption: String   // AES或NONE
    let signalStrength: String // 信号强度
    
    
    /// 解析WiFi热点数据
    /// - Parameter data: 打印机返回的数据
    /// - Returns: WiFi热点信息数组
    static func parseWifiHotspotsData(_ data: Data) -> [WifiHotspotInfo] {
        var hotspots: [WifiHotspotInfo] = []
        
        guard let dataStr = String(data: data, encoding: .utf8) else {
            return hotspots
        }
        
        print("WiFi热点原始数据: \(dataStr)")
        
        // 移除开头的"WiFi_scan_ap:"部分
        var cleanDataStr = dataStr
        if dataStr.hasPrefix("WiFi_scan_ap:") {
            cleanDataStr = String(dataStr.dropFirst("WiFi_scan_ap:".count))
        }
        
        // 按行分割数据
        let lines = cleanDataStr.components(separatedBy: .newlines)
        
        for line in lines {
            let trimmedLine = line.trimmingCharacters(in: .whitespacesAndNewlines)
            
            if trimmedLine.hasPrefix("AP=") && trimmedLine.contains("\t") {
                // 解析格式: AP=n/m  \t 热点名称 \t 加密协议 \t AES或NONE \t 信号强度 \r\n
                let parts = trimmedLine.components(separatedBy: "\t")
                
                if parts.count >= 5 {
                    // 解析AP=n/m部分
                    let apInfo = String(parts[0].dropFirst(3)) // 移除"AP="前缀
                    let name = parts[1]
                    let security = parts[2]
                    let encryption = parts[3]
                    let signal = parts[4].replacingOccurrences(of: "\r", with: "").replacingOccurrences(of: "\n", with: "")
                    
                    let hotspot = WifiHotspotInfo(index: apInfo, name: name, security: security, encryption: encryption, signalStrength: signal)
                    hotspots.append(hotspot)
                }
            }
        }
        return hotspots
    }
}

class PrinterManager: NSObject {
    
    static let instance = _init()
    
    static func _init() -> PrinterManager {
        let temp = PrinterManager()
        return temp
    }
    
    // 存储多个打印机的数组
    var printers: [S1V1ProtocolPrinter] = []
    
    // 获取当前默认打印机（第一个打印机）
    var accessory: S1V1ProtocolPrinter? {
        return printers.first
    }
    
    // 获取所有已连接的打印机
    var connectedPrinters: [S1V1ProtocolPrinter] {
        return printers.filter { $0.connectStatus == .connected }
    }
    
    var connected: Bool {
        return accessory?.connectStatus == .connected
    }
    
    var connectStatus: RYAccessoryConnectStatus {
        return accessory?.connectStatus ?? .disconnected
    }
    
    fileprivate var connectStatusListeners = NSMapTable<AnyObject, ConnectStatusListener>.weakToStrongObjects()
    
    /// 添加打印机
    /// - Parameter printer: 打印机实例
    /// - Returns: 打印机在数组中的索引
    func add(printer: S1V1ProtocolPrinter) -> Void {
        // 设置连接状态监听
        printer.connectStatusListener = { [weak self] status in
            self?.notifyConnectStatusListeners(printer, status: status)
        }
        
        printers.append(printer)
        self.notifyConnectStatusListeners(printer, status: printer.connectStatus)
    }
    /// 移除打印机
    /// - Parameter index: 打印机在数组中的索引，如果为nil则移除第一个
    private func removePrinter(at index: Int? = nil) -> Void {
        let targetIndex = index ?? 0
        
        guard targetIndex >= 0 && targetIndex < printers.count else { return }
        
        let printer = printers[targetIndex]
        printer.connectStatusListener = nil
        printers.remove(at: targetIndex)
    }
    
    /// 移除指定打印机
    /// - Parameter printer: 要移除的打印机实例
    func removePrinter(_ printer: S1V1ProtocolPrinter) -> Void {
        if let index = printers.firstIndex(where: { $0 === printer }) {
            removePrinter(at: index)
        }
    }
    
    /// 获取指定索引的打印机
    /// - Parameter index: 打印机在数组中的索引
    /// - Returns: 打印机实例
    private func getPrinter(at index: Int) -> S1V1ProtocolPrinter? {
        guard index >= 0 && index < printers.count else { return nil }
        return printers[index]
    }
    
    /// 通知连接状态监听器
    private func notifyConnectStatusListeners(_ printer: S1V1ProtocolPrinter,status: RYAccessoryConnectStatus) {
        if let enumerator = connectStatusListeners.objectEnumerator() {
            while let item = enumerator.nextObject() as? ConnectStatusListener {
                item.block(printer, status)
            }
        }
    }
    
    func addConnectListen(_ observer: AnyObject, block: @escaping (S1V1ProtocolPrinter, RYAccessoryConnectStatus) -> Void) -> Void {
        
        connectStatusListeners.setObject(ConnectStatusListener(block: block), forKey: observer)
    }
    
    /// 数据请求（指定打印机）
    /// - Parameters:
    ///   - data: 指令数据
    ///   - printer: 打印机实例，如果为nil则使用第一个
    ///   - complete: 结果回调
    func dataRequest(_ data: Data, printer: S1V1ProtocolPrinter? = nil, complete: @escaping ((Result<Data, Error>) -> Void)) -> Void {
        let targetPrinter = printer ?? accessory
        guard let printer = targetPrinter else { 
            complete(.failure(NSError(domain: "PrinterManager", code: -1, userInfo: [NSLocalizedDescriptionKey: "打印机未找到"])))
            return 
        }
        
        printer.dataRequest(data) { data, error in
            if let error = error {
                complete(.failure(error))
                return
            }
            complete(.success(data!))
        }
    }
    
    /// 指令请求（指定打印机）
    /// - Parameters:
    ///   - generator: 指令生成
    ///   - printer: 打印机实例，如果为nil则使用第一个
    ///   - complete: 结果回调
    func cmdRequest(_ generator: S1CmdGenerator, printer: S1V1ProtocolPrinter? = nil, complete: @escaping ((Result<Data, Error>) -> Void)) -> Void {
        let targetPrinter = printer ?? accessory
        guard let printer = targetPrinter else { 
            complete(.failure(NSError(domain: "PrinterManager", code: -1, userInfo: [NSLocalizedDescriptionKey: "打印机未找到"])))
            return 
        }
        
        printer.cmdRequest(generator) { data, error in
            if let error = error {
                complete(.failure(error))
                return
            }
            complete(.success(data!))
        }
    }
    
    /// 执行指令（指定打印机）
    /// - Parameters:
    ///   - generator: 指令生成器
    ///   - printer: 打印机实例，如果为nil则使用第一个
    ///   - showActivity: 是否显示发送中Activity
    func executeCmd(_ generator: S1CmdGenerator, printer: S1V1ProtocolPrinter? = nil, showActivity: Bool = false) -> Void {
        executeDataCmd(generator.generate(), printer: printer, showActivity: showActivity)
    }
    
    /// 执行数据指令（指定打印机）
    /// - Parameters:
    ///   - data: 指令数据
    ///   - printer: 打印机实例，如果为nil则使用第一个
    ///   - showActivity: 是否显示发送中Activity
    func executeDataCmd(_ data: Data, printer: S1V1ProtocolPrinter? = nil, showActivity: Bool = false) -> Void {
        let targetPrinter = printer ?? accessory
        
        guard let printer = targetPrinter else {
            if showActivity {
                SVProgressHUD.showError(withStatus: "打印机未找到".localized)
            }
            return
        }
        
        if showActivity {
            SVProgressHUD.show()
        }
        
        printer.write(data, progress: { progress in
            if progress.isFinished {
                SVProgressHUD.showSuccess(withStatus: "Data sent successfully".localized)
            }
        })
    }
    
    /// 固件升级（指定打印机）
    /// - Parameters:
    ///   - firmwareData: 固件数据
    ///   - printer: 打印机实例，如果为nil则使用第一个
    ///   - packageSize: 包大小
    ///   - progressBlock: 进度回调
    ///   - completeBlock: 完成回调
    func firmwareUpgrade(
        _ firmwareData: Data,
        printer: S1V1ProtocolPrinter? = nil,
        packageSize: Int? = nil,
        progress progressBlock: @escaping (Progress) -> Void,
        complete completeBlock: @escaping RYEmptyResultBlock
    ) {
        let targetPrinter = printer ?? accessory
        
        guard let printer = targetPrinter else {
            completeBlock(NSError(domain: "PrinterManager", code: -1, userInfo: [NSLocalizedDescriptionKey: "打印机未找到"]))
            return
        }
        
        printer.otaUpgrade(firmwareData, progress: progressBlock, complete: completeBlock)
    }
    
    /// 使用蓝牙目标设备连接
    /// - Parameters:
    ///   - target: 目标设备
    ///   - complete: 完成回调
    static func connect(target: AccessoryConvertable, complete: @escaping (Result<S1V1ProtocolPrinter, Error>) -> Void) -> Void {
        let printer = S1V1ProtocolPrinter.init(target.convert())
        printer.connectWithResult { result in
            DispatchQueue.main.async {
                switch result {
                case .success(_):
                    complete(.success(printer))
                case .failure(let error):
                    complete(.failure(error))
                }
            }
        }
    }
    
    /// 多设备批量下发
    /// - Parameters:
    ///   - data: 下发的数据
    ///   - complete: 完成回调
    func writeData(data : Data, completion : (() -> Void)? = nil){
        var printerCount = self.printers.count
        self.printers.forEach({
            $0.write(data) {
                if $0.isFinished{
                    printerCount -= 1
                    if printerCount == 0{
                        completion?()
                    }
                }
            }
        })
    }
}
