//
//  StitchingCameraSDK.swift
//  StitchingCameraSDK
//
//  Created by xiexinyue on 2022/2/22.
//

import UIKit

private let sharedInstance = StitchingCameraSDK()

public let SDK_VERSION: Float = 1.1

public class StitchingCameraSDK: NSObject {
    @objc public var callBack: ((_ images: [[String: Any]], _ pano: UIImage, _ stitchInfo: Data) -> Void) = { _, _, _ in }

    @objc public class var shared: StitchingCameraSDK {
        return sharedInstance
    }

    private var ratio: Int = 0 // 分辨率 0: 720 1:1080 2:4k

    private var isCameraMix: Bool = false // 设置相机的拍摄模式 true：混合模式 false：截帧模式

    private var imageMap: [String: String] = [:] // iamgeId: filename.path映射

    @objc public func initCameraConfig() -> CameraConfig {
        let cameraConfig = CameraConfig()
        return cameraConfig
    }
    
    @objc public func initCameraConfig(language: String) -> CameraConfig {
        let cameraConfig = CameraConfig()
        cameraConfig.language = language
        LocalizationHelper.setLanguage(withCode: cameraConfig.language)
        return cameraConfig
    }

    @objc public func getCameraController() -> ParentStitchController? {
//        AddToLog(type: .sdk,"","getCameraController")
        if #available(iOS 10.0, *) {
        } else {
//            AddToLog(type: .error,"low ios version","error")
            return nil
        }

        // 加载视图
        let stitchController = ParentStitchController(
            nibName: "ParentStitchController",
            bundle: Bundle(identifier: "com.clobotics.retail.StitchingCameraSDK")
        )
//        stitchController.yawLimit = UserDefaults.standard.object(forKey: "Clobotics.StitchCameraSDK.yawLimit") == nil ? 15 : UserDefaults.standard.double(forKey: "Clobotics.StitchCameraSDK.yawLimit")
//        stitchController.pitchLimit = UserDefaults.standard.object(forKey: "Clobotics.StitchCameraSDK.pitchLimit") == nil ? 45 : UserDefaults.standard.double(forKey: "Clobotics.StitchCameraSDK.pitchLimit")
//
//        stitchController.yawLimit = 180
//        stitchController.pitchLimitValue = 90
//        stitchController.angleErrorTip = "请保持水平拍摄"
//
//        stitchController.ratio = ratio
//        stitchController.isCameraMix = isCameraMix
//        stitchController.imageCallBack = {[weak self] istake, image, imageId, yaw in
//            guard let `self` = self else { return }
//            if istake {
//                let filename = getImagesDocumentsDirectory().appendingPathComponent("\(imageId).jpg")
//                self.saveImageToLocal(url: filename, image: image)
//                self.imageMap[imageId] = filename.path
//            } else {
//                self.imageMap.removeValue(forKey: imageId)
//                removeLocalImageById(id: imageId)
//            }
//        }
//        stitchController.callBack = {[weak self] images, pnao in
//            guard let `self` = self else { return }
//            let stitchInfo = self.buildStitchInfo(images)
//
//            var returnImages:[[String:Any]] = []
//            for pimage in images {
//                returnImages.append(["imageId":pimage.id,"imageUrl":self.imageMap[pimage.id] ?? ""])
//            }
//            self.callBack(returnImages, pnao, stitchInfo ?? Data())
//        }
        return stitchController
    }

    @objc public func setLogPolicy(isOn: Bool) {
//        AddToLog(type: .sdk,"value:\(isOn)","setLogPolicy")
        UserDefaults.standard.set(isOn, forKey: "Clobotics.StitchCameraSDK.isLogOn")
        UserDefaults.standard.synchronize()
    }

    @objc public func setYawLimit(value: Double) {
//        AddToLog(type: .sdk,"value:\(value)","setYawLimit")
        UserDefaults.standard.set(value, forKey: "Clobotics.StitchCameraSDK.yawLimit")
        UserDefaults.standard.synchronize()
    }

    @objc public func setPitchLimit(value: Double) {
//        AddToLog(type: .sdk,"value:\(value)","setPitchLimit")
        UserDefaults.standard.set(value, forKey: "Clobotics.StitchCameraSDK.pitchLimit")
        UserDefaults.standard.synchronize()
    }

    // type: 0:1280 1:1920 2:4k
    @objc public func setRatio(type: Int) {
        ratio = type
//        AddToLog(type: .sdk,"value:\(type)","ratio")
        UserDefaults.standard.set(type, forKey: "Clobotics.StitchCameraSDK.ratio")
        UserDefaults.standard.synchronize()
    }

    @objc public func setCameraMix(type: Bool) {
        isCameraMix = type
//        AddToLog(type: .sdk,"value:\(type)","isCameraMix")
        UserDefaults.standard.set(type, forKey: "Clobotics.StitchCameraSDK.isCameraMix")
        UserDefaults.standard.synchronize()
    }

    @objc public func resetLogFile() {
//        AddToLog(type: .sdk,"","resetLogFile")
//        removeLogFile()
    }

//    @objc public func loadImageById(id:String) -> UIImage? {
//        return getLocalImageById(id: id)
//    }

    @objc public func removeAllImageCache() {
//        removeImageCache()
    }

    /// 为图片添加水印
    /// - Parameter imagePath: 图片路径
    /// - Parameter watermarkObj: 水印配置model
    /// - Returns: 添加水印后的图片路径，注意：当水印添加失败时此路径可能为空
    @objc public static func addWatermark(imagePath: String, watermarkObj: [String: Any]) -> String? {
        if let image = UIImage(contentsOfFile: imagePath) {
            if var datas = watermarkObj["data"] as? [Any] {
                datas = Array(datas.prefix(6))
                var watermarkStr = ""
                let watermarkSeparator: [String: String] = watermarkObj["separators"] as? [String: String] ?? ["item": ":", "items": "/n"] as! [String: String]
                datas.enumerated().forEach { index, data in
                    watermarkStr += ImageUtils.watermarkFormatter(separator: watermarkSeparator, data: data as! [String: Any], isLast: index == datas.count - 1)
                }
                if let outputImage = ImageUtils.addWatermark(to: image, with: watermarkStr) {
                    let saveImagePath = ImageUtils.copyWithSuffix(imagePath, "watermark")
                    return ImageUtils.saveImageWithCompressionQuality(outputImage, saveImagePath) != nil ? saveImagePath : nil
                }
            }
        }
        return nil
    }

    /// 为图片添加水印
    /// - Parameter imagePath: 图片路径
    /// - Parameter watermark: 水印内容，如果内容过长会自动换行，同时支持\n换行
    /// - Returns: 添加水印后的图片路径，注意：当水印添加失败时此路径可能为空
    @objc public static func addWatermark(imagePath: String, watermark: String) -> String? {
        if let image = UIImage(contentsOfFile: imagePath) {
            if let outputImage = ImageUtils.addWatermark(to: image, with: watermark) {
                let saveImagePath = ImageUtils.copyWithSuffix(imagePath, "watermark")
                return ImageUtils.saveImageWithCompressionQuality(outputImage, saveImagePath) != nil ? saveImagePath : nil
            }
        }
        return nil
    }
    
    /// 更新语言
    /// - Parameter language: CameraSDKLanguage
    @objc public func changeLanguage(_ language: CameraSDKLanguage) {
        LocalizationHelper.setLanguage(language)
    }

    // ----------------------- private ----------------------
}

extension StitchingCameraSDK {
    func buildStitchInfo(_ pimageArray: [ParameterImager]) -> Data? {
        // 生成拼图信息
        var imageStitchingInfo = ModelStitchInfo()
        switch ratio {
        case 0:
            imageStitchingInfo.resize = 0.25
        case 1:
            imageStitchingInfo.resize = 320 / 1920
        case 2:
            imageStitchingInfo.resize = 320 / 3840
        default:
            imageStitchingInfo.resize = 0.25
        }

        // image 当前 index
        var imageIndex = 0
        // 上张图片id
        var lastImageId = 0
        // 最佳图片id
        var bestPov = 0

        for pimage in pimageArray {
            // 如果不是第一张,创建Pairs
            if imageIndex != 0 {
                var imagePair = ModelPairs()
                imagePair.image1Index = lastImageId
                imagePair.image2Index = imageIndex
                imagePair.homography = transHomography(pimage.homography)
                imageStitchingInfo.pair.append(imagePair)
            }
            // 如果这张图的index 是最佳图片的 index
            if pimage.frameIndex == pimage.bestPOV {
                bestPov = imageIndex
            }

            // 赋值为上张
            lastImageId = imageIndex
            imageIndex += 1
        }

        imageStitchingInfo.bestPov = bestPov

        return try? JSONEncoder().encode(imageStitchingInfo)
    }

    func transHomography(_ array: [Any]) -> [Float] {
        var floatArray: [Float] = []
        for item in array {
            if let fv = item as? NSNumber {
                floatArray.append(fv.floatValue)
            }
        }
        return floatArray
    }

    private func saveImageToLocal(url: URL, image: UIImage) {
        guard let imageData = image.size.height > 1920 ? image.jpegData(compressionQuality: 0.6) : image.jpegData(compressionQuality: 0.7) else { return }

//        if !FileManager.default.fileExists(atPath: getImagesDocumentsDirectory().path){
//            do {
//                try FileManager.default.createDirectory(atPath: getImagesDocumentsDirectory().path, withIntermediateDirectories: true, attributes: nil)
//            } catch {
//                print(error.localizedDescription);
//            }
//        }

        try? imageData.write(to: url)
    }
}
