//
//  KMConvertBaseWindowController.swift
//  PDF Reader Pro
//
//  Created by tangchao on 2022/12/5.
//

import PDFKit

typealias KMConvertBaseWindowControllerItemClick = (Int) -> ()
class KMConvertBaseWindowController: KMBaseWindowController {
    
    @IBOutlet weak var titleLabel: NSTextField!
    
    @IBOutlet weak var leftBox: NSBox!
    @IBOutlet weak var prePDFView: KMCustomPDFView?
    @IBOutlet weak var numberBox: NSView!
    @IBOutlet weak var numberTextField: NSTextField!
    @IBOutlet weak var perLabel: NSTextField!
    @IBOutlet weak var totalNumberLabel: NSTextField!
    @IBOutlet weak var backBox: NSBox!
    @IBOutlet weak var nextBox: NSBox!
    
    @IBOutlet weak var rightScrollView: NSScrollView!
    
    @IBOutlet weak var batchButton: NSButton!
    @IBOutlet weak var canelBox: NSBox!
    @IBOutlet weak var convertBox: NSBox!
    
    @IBOutlet weak var rightBoxHeightConst: NSLayoutConstraint!
    
    var canelButtonVC: KMDesignButton?
    var convertButtonVC: KMDesignButton?
    var backButtonVC: KMDesignButton?
    var nextButtonVC: KMDesignButton?

    var itemClick: KMConvertBaseWindowControllerItemClick?
    
    var documentModel: KMDocumentModel?
    
    var currentPageIndex: Int = 1
    var pageRange = KMPageRange.all
    var pageRangeString: String = ""
    var settingView: KMConvertSettingView?
    
    var subType: Int = 0
    
    var fileExtension: String {
        get {
            return ""
        }
    }
    
    var progressController: SKProgressController?
    private var convert: KMPDFConvert?
    
    var limit = true
    // 是否限制次数
    var limitCount = true
    var oriDocumentUrl: URL?
    var subscribeWaterMarkType: KMSubscribeWaterMarkType?
    
    deinit {
        KMPrint("KMConvertBaseWindowController 已释放")
        
        self.prePDFView?.removeFromSuperview()
        self.prePDFView = nil
        #if VERSION_DMG
        NotificationCenter.default.removeObserver(self)
        #endif
    }
    
    convenience init() {
        self.init(windowNibName: "KMConvertBaseWindowController")
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        
        DispatchQueue.main.async {
            self.window?.makeFirstResponder(nil)
        }
    }
    
    override func windowDidLoad() {
        super.windowDidLoad()
        
//        if (self.convertCountIsReach()) {
//            Swift.debugPrint("转档次数已达到限制. count: \(self.getConvertCount())")
//        }
//        #if VERSION_DMG
        NotificationCenter.default.addObserver(self, selector: #selector(km_windowWillCloseNotifation), name: NSWindow.willCloseNotification, object: nil)
//        #endif
        
        if (self.documentModel != nil) {
            let document = CPDFDocument(url: self.documentModel!.documentURL)
            if (document!.isLocked) {
                document?.unlock(withPassword: self.documentModel!.password)
            }
            self.prePDFView?.document = document!
            
            let number: Int = Int((self.prePDFView?.document.pageCount)!)
            let string = "\(number)"
            totalNumberLabel.stringValue = string
            
            self.prePDFView?.go(toPageIndex: self.documentModel!.currentIndex, animated: false)
        }
        if (self.prePDFView?.documentView() != nil) {
            self.prePDFView?.documentView().enclosingScrollView?.hasVerticalScroller = false
            self.prePDFView?.documentView().enclosingScrollView?.hasHorizontalScroller = false
        }
        
        if let pageCount = self.prePDFView?.document.pageCount {
            self.settingView?.pageCount = Int(pageCount)
        }

        batchButton.title = NSLocalizedString("Batch", comment: "")
        batchButton.isBordered = false
        batchButton.wantsLayer = true
        batchButton.layer?.borderWidth = 1
        batchButton.layer?.cornerRadius = 4
        batchButton.target = self
        batchButton.action = #selector(batchButtonAction)
        batchButton.isHidden = true
        
        self.updateBackAndNextButtonState()
    }
    
    override func initSubViews() {
        super.initSubViews()
        
        let view = self.initSettingView()
//        view?.frame = self.rightScrollView.bounds
//        view?.autoresizingMask = [.width, .height]
        self.settingView = view
        self.rightScrollView.documentView = view
        self.rightScrollView.verticalScrollElasticity = .none
        self.rightScrollView.horizontalScrollElasticity = .none
        
        view?.km_add_inset_constraint()
        
        view?.currentLanguage = self.getCurrentLanguage()
        view?.lanugageDidSelected = { [unowned self] value, _ in
            guard let index = value as? Int else {
                return
            }
            
            self.saveLanugageSelectedIndex(index: index)
        }

        view?.pageRangeDidChange = { [unowned self] pageRange in
            self.pageRange = pageRange
            if (pageRange != .custom) {
                self.updatePreView(pageRange: pageRange)
            }
        }
        view?.pageRangeDidInputFinishCallback = { [unowned self] string in
            self.pageRangeString = string
            let array = self.findSelectPage(pageRangeString: string)
            if array.count == 0 {
                let alert = NSAlert()
                alert.alertStyle = .warning
                alert.messageText = NSLocalizedString("Invalid page range or the page number is out of range. Please try again.", comment: "")
                alert.runModal()
                
                self.settingView?.pageRangeItemView?.pageSizeVC?.stringValue = ""
            } else {
                self.updatePreView(pageRange: .custom, pageString: string)
            }
        }
        view?.tipView?.itemClick = { [unowned self] _, _ in
#if VERSION_DMG
            KMTools.openPurchaseProductWebsite()
#else
            Task { @MainActor in
                if await (KMLightMemberManager.manager.canPayFunction() == false) {
                    let _ = KMSubscribeWaterMarkWindowController.show(window: self.window!) { isSubscribeSuccess, isWaterMarkExport, isClose in
                        if (isSubscribeSuccess) {
                            self.refreshUI()
                        }
                    }
                }
            }
#endif
        }
        self.settingView?.tipView?.isHidden = true
        Task { @MainActor in
            if await (KMLightMemberManager.manager.canUseAdvanced() == false) {
                self.limitCount = true
            } else {
                self.limitCount = false
            }
            
            if await (KMLightMemberManager.manager.canPayFunction() == false) {
                #if VERSION_DMG
                if (self.limitCount) { // 未登录
                    self.settingView?.tipView?.isHidden = true
                } else {
                    self.settingView?.tipView?.isHidden = false
                }
                #else
                self.settingView?.tipView?.isHidden = false
                #endif
            } else {
                self.limit = false
            }
        }
        
        self.backButtonVC = KMDesignButton.init(withType: .Image)
        self.backBox.contentView = self.backButtonVC!.view
        
        self.nextButtonVC = KMDesignButton.init(withType: .Image)
        self.nextBox.contentView = self.nextButtonVC!.view
        
        self.canelButtonVC = KMDesignButton.init(withType: .Text)
        self.canelBox.contentView = self.canelButtonVC!.view
        
        self.convertButtonVC = KMDesignButton.init(withType: .Text)
        self.convertBox.contentView = self.convertButtonVC!.view
    }
    
    override func initDefaultValue() {
        super.initDefaultValue()
        
        self.totalNumberLabel.lineBreakMode = .byTruncatingTail
        
        self.prePDFView?.setDisplay(.singlePage)
        self.prePDFView?.layoutDocumentView()
        self.prePDFView?.autoScales = true
        self.prePDFView?.delegate = self
        
        self.backBox.fillColor = .clear
        self.backButtonVC?.target = self
        self.backButtonVC?.action = #selector(backButtonAction)
        self.backButtonVC?.image = NSImage(named: "KMImageNamePreviousPageImage")!
        self.backButtonVC?.image_disabled = NSImage(named: "KMImageNamePreviousPageImageDisable")!
        self.backButtonVC?.pagination()
        
        self.numberBox.wantsLayer = true
        self.numberBox.layer?.backgroundColor = NSColor.white.cgColor
        self.numberBox.layer?.borderWidth = 1
        self.numberBox.layer?.cornerRadius = 4
        self.numberTextField.focusRingType = .none
        self.numberTextField.delegate = self
        self.numberTextField.isBordered = false
        
        self.nextBox.fillColor = .clear
        self.nextButtonVC?.target = self
        self.nextButtonVC?.action = #selector(nextButtonAction)
        self.nextButtonVC?.image = NSImage(named: "KMImageNameNextPageImage")!
        self.nextButtonVC?.image_disabled = NSImage(named: "KMImageNameNextPageImageDisable")!
        self.nextButtonVC?.pagination()
        
        self.canelBox.fillColor = .clear
        self.canelButtonVC?.target = self
        self.canelButtonVC?.action = #selector(cancelButtonAction)
        self.canelButtonVC?.stringValue = NSLocalizedString("Cancel", comment: "")
        self.canelButtonVC?.button(type: .Sec, size: .m)
        self.canelButtonVC?.button.keyEquivalent = KMKeyEquivalent.esc.string()
        
        self.convertBox.fillColor = .clear
        self.convertButtonVC?.target = self
        self.convertButtonVC?.action = #selector(convertButtonAction)
        self.convertButtonVC?.stringValue = NSLocalizedString("Convert", comment: "")
        self.convertButtonVC?.button(type: .Cta, size: .m)
//        convertButtonVC.button.keyEquivalent = KMKeyEquivalent.enter
        
        self.rightScrollView.hasVerticalScroller = false
        self.rightScrollView.hasHorizontalScroller = false
        
        self.initUIProperty()
    }
    
    private func initUIProperty() {
        self.titleLabel.textColor = NSColor.titleColor()
        self.titleLabel.font = .SFProTextSemiboldFont(16)
        
        self.leftBox.fillColor = NSColor.km_init(hex: "#F7F8FA")
        self.prePDFView?.backgroundColor = NSColor.km_init(hex: "#F7F8FA")
        self.numberBox.layer?.borderColor = NSColor.km_init(hex: "#DFE1E5").cgColor
        self.perLabel.textColor = NSColor.titleColor()
        self.perLabel.font = .SFProTextRegularFont(12)
        self.totalNumberLabel.textColor = NSColor.titleColor()
        self.totalNumberLabel.font = .SFProTextRegularFont(12)
        
        self.batchButton.setTitleColor(NSColor.buttonTitleColor())
        self.batchButton.layer?.borderColor = NSColor.buttonBorderColor().cgColor
        self.batchButton.font = .SFProTextRegularFont(14)
    }
    
    func initSettingView() -> KMConvertSettingView? {
        let settingView = KMConvertSettingView.createFromNib()
        return settingView
    }
    
    public func initConvert() -> KMPDFConvert {
        return KMPDFConvert()
    }
    
    func setupContentHeight(height: CGFloat, animated: Bool = false) {
        if (animated) {
            self.rightBoxHeightConst.animator().constant = height
        } else {
            self.rightBoxHeightConst.constant = height
        }
    }
    
    func refreshUI() {
        
    }
    
    @objc func backButtonAction() {
        if let _ = self.prePDFView?.canGoToPreviousPage() {
            self.currentPageIndex -= 1
            self.prePDFView?.goToPreviousPage(nil)
            
            self.numberTextField.stringValue = "\(self.prePDFView!.currentPageIndex+1)"
            self.updateBackAndNextButtonState()
        }
    }
    
    @objc func nextButtonAction() {
        if let _ = self.prePDFView?.canGoToNextPage() {
            self.currentPageIndex += 1
            self.prePDFView?.goToNextPage(nil)
            
            self.numberTextField.stringValue = "\(self.prePDFView!.currentPageIndex+1)"
            self.updateBackAndNextButtonState()
        }
    }
    
    @objc func batchButtonAction() {
        guard let callback = itemClick else {
            return
        }
        
        callback(1)
    }
    
    @objc func cancelButtonAction() {
        self._clearData()
        
        guard let callback = itemClick else {
            return
        }
        
        callback(2)
    }
    
    @objc func convertButtonAction() {
        self.window?.makeFirstResponder(nil)
        if (self.pageRange == .custom) {
            let array = self.findSelectPage(pageRangeString: self.pageRangeString)
            if (array.count <= 0) {
                self.window?.makeFirstResponder(self.settingView?.pageRangeItemView?.pageSizeVC?.textField)
                return
            }
        }
        
        var pages: [Int] = []
        let filePath = self.getConvertFileSavePath()
        if (FileManager.default.fileExists(atPath: filePath)) {
            try?FileManager.default.removeItem(atPath: filePath)
        }
        if ((self.prePDFView?.document?.writeDecrypt(to: URL(fileURLWithPath: filePath)))!) {
            for i in 0 ..< self.prePDFView!.document.pageCount {
                pages.append(Int(i)+1)
            }
        }
        
        if (pages.count <= 0) {
            let alert = NSAlert()
            alert.alertStyle = .warning
            alert.messageText = NSLocalizedString("Invalid page range or the page number is out of range. Please try again.", comment: "")
            alert.runModal()
            return
        }
        
        Task { @MainActor in
            #if VERSION_DMG
            if (await (KMLightMemberManager.manager.canUseAdvanced() == false)) {
                let _ = KMComparativeTableViewController.show(window: self.window!, .convert)
                return
            }
            #endif
            if await (KMLightMemberManager.manager.canPayFunction() == false) {
                var isContinue = false
                if pages.count <= 10 {
                    isContinue = true
                }
                
                var limit = self.convertCountIsReach()
                if (!self.limitCount) { // 登录
                    limit = false
                }
                
                if (limit) {
                    isContinue = false
                }

                let _ = KMSubscribeWaterMarkWindowController.show(window: self.window!, isContinue: isContinue, limit: limit, type: self.subscribeWaterMarkType!) { isSubscribeSuccess, isWaterMarkExport, isClose in
                    if (isClose) {
                        return
                    }
                    if (isSubscribeSuccess) {
                        self._convertButtonAction()
                        return
                    }
                    if (isWaterMarkExport && !limit) {
                        self._convertButtonAction(limit: true)
                        return
                    }
                }
                return
            }
            self._convertButtonAction()
        }
    }
    
    func convertModelAppendParams(convert: KMPDFConvert) -> () {
        if let isAllowOCR = self.settingView?.ocrEnabled {
            convert.isAllowOCR = isAllowOCR
            if let idx = self.settingView?.ocrItemView?.languageIndex {
                convert.ocrLanguage = KMPDFConvertManager.defaultManager.languages_asc[idx]
            }
        } else {
            convert.isAllowOCR = false
        }
    }
    
    func getConvertFileSavePath() -> String {
        var path = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationSupportDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last
        path?.append("/")
        path?.append(Bundle.main.bundleIdentifier!)
        if (FileManager.default.fileExists(atPath: path!) == false) {
            try?FileManager.default.createDirectory(atPath: path!, withIntermediateDirectories: false)
        }
        
        path?.append("/")
        path?.append("convert.pdf")
        
        return path!
    }
    
    func isValidPagesString(pagesString: String)-> Bool {
        var valid = false
        for ch in pagesString {
            if ch != "0" && ch != "1" && ch != "2" && ch != "3" && ch != "4" && ch != "5" && ch != "6" && ch != "7" && ch != "8" && ch != "9" && ch != "," && ch != "-" {
                valid = false
                break
            } else {
                valid = true
            }
        }
        
        return valid
    }
    
    func findSelectPage(pageRangeString: String) -> ([Int]) {
        if !isValidPagesString(pagesString: pageRangeString) {
            return []
        }
        
        var result: [Int] = []
        let array = pageRangeString.components(separatedBy: ",")
        for string in array {
            if string.isEmpty {
                return []
            } else {
                let pages = string .components(separatedBy: "-")
                if pages.count > 2 {
                    return []
                } else if pages.count == 1 {
                    let page = pages[0]
                    if page.isEmpty || Int(page)! > self.documentModel!.pageCount || Int(page)! == 0 {
                        return []
                    } else {
                        var hasSame: Bool = false
                        for i in result {
                            if i == Int(page)! {
                                hasSame = true
                                return []
                            }
                        }
                        if !hasSame {
                            result.append(Int(page)!)
                        }
                    }
                } else if pages.count == 2 {
                    let page1 = pages[0]
                    let page2 = pages[1]
                    if page1.isEmpty || page2.isEmpty || Int(page1)! >= Int(page2)! || Int(page2)! > self.documentModel!.pageCount || Int(page1)! == 0 {
                        return []
                    } else {
                        var hasSame: Bool = false
                        for i in Int(page1)! ... Int(page2)! {
                            for j in result {
                                if j == i {
                                    hasSame = true
                                    return []
                                }
                            }
                        }
                        if !hasSame {
                            for i in Int(page1)! ... Int(page2)! {
                                result.append(i)
                            }
                        }
                     }
                }
            }
        }
        
        return result
    }
    
    // MARK: -
    // MARK: Private Methods
    
    private func updateBackAndNextButtonState() {
        var nextEnabled = false
        if let result = self.prePDFView?.canGoToNextPage() {
            nextEnabled = result
        }
        var backEnabled = false
        if let result = self.prePDFView?.canGoToPreviousPage() {
            backEnabled = result
        }
        
        if (Thread.isMainThread) {
            self.backButtonVC?.state = backEnabled ? .Norm : .Disabled
            self.nextButtonVC?.state = nextEnabled ? .Norm : .Disabled
        } else {
            DispatchQueue.main.async {
                self.backButtonVC?.state = backEnabled ? .Norm : .Disabled
                self.nextButtonVC?.state = nextEnabled ? .Norm : .Disabled
            }
        }
    }
    
    internal func updatePreView(pageRange: KMPageRange, pageString: String = "") {
        let pages = self.getPages(pageRange, pageString: pageString)
        if (pages == nil || pages!.isEmpty) {
            let alert = NSAlert()
            alert.alertStyle = .warning
            alert.messageText = NSLocalizedString("Invalid page range or the page number is out of range. Please try again.", comment: "")
            alert.runModal()
            return
        }
        var indexs = IndexSet()
        for i in 0 ..< self.prePDFView!.document.pageCount  {
            indexs.insert(IndexSet.Element(i))
        }
        self.prePDFView?.document.removePage(at: indexs)
        
        #if DEBUG
        let pageIndexs = self.getPageIndexs(pageRange, pageString: pageString)
        if (pageIndexs != nil) {
            for i in pageIndexs! {
                
                KMPrint(i)
            }
        }
        #endif
//        self.prePDFView.document?.importPages(pageIndexs!, from: self.documentModel.document, at: 0)
        for page in pages! {
            self.prePDFView?.document.insertPageObject(page, at: self.prePDFView!.document.pageCount)
        }
        DispatchQueue.main.async {
            self.prePDFView?.layoutDocumentView()
            self.prePDFView?.setNeedsDisplayForVisiblePages()
            self.prePDFView?.goToFirstPage(nil)
            
            let number: Int = Int(self.prePDFView!.document!.pageCount)
            self.totalNumberLabel.stringValue = "\(number)"
            self.currentPageIndex = 1
            self.numberTextField.stringValue = "1"
            
            self.updateBackAndNextButtonState()
        }
    }
    
    private func getPageIndexs(_ pageRange: KMPageRange, pageString: String = "") -> IndexSet? {
        guard let pageCount = self.documentModel?.pageCount, pageCount > 0 else {
            return nil
        }
        
        var indexs = IndexSet()
        if (pageRange == .all) {
            for i in 0 ..< pageCount {
                indexs.insert(i)
            }
        } else if (pageRange == .odd) {
            for i in 0 ..< pageCount {
                if ((i % 2) == 1) {
                    continue
                }
                indexs.insert(i)
            }
        } else if (pageRange == .even) {
            for i in 0 ..< pageCount {
                if ((i % 2) == 0) {
                    continue
                }
                indexs.insert(i)
            }
        } else if (pageRange == .current) {
            if (self.currentPageIndex >= 1 && self.currentPageIndex <= pageCount) {
                indexs.insert(self.currentPageIndex-1)
            }
        } else if (pageRange == .custom) {
            let array = self.findSelectPage(pageRangeString: pageString)
            if array.count == 0 {

            } else {
                for i in 0 ..< array.count {
                    let index = array[i]
                    if (index > pageCount || index < 1) {
                        continue
                    }
                    indexs.insert(index-1)
                }
            }
        }
        return indexs
    }
    
    private func getPages(_ pageRange: KMPageRange, pageString: String = "") -> [CPDFPage]? {
        guard let pageCount = self.documentModel?.pageCount, pageCount > 0 else {
            return nil
        }
        
        var pages: [CPDFPage] = []
        if (pageRange == .all) {
            for i in 0 ..< pageCount {
                let page = self.documentModel!.document?.page(at: UInt(i))
                if (page == nil) {
                    continue
                }
                
                pages.append(page!)
            }
        } else if (pageRange == .odd) {
            for i in 0 ..< pageCount {
                if ((i % 2) == 1) {
                    continue
                }
                let page = self.documentModel!.document?.page(at: UInt(i))
                if (page == nil) {
                    continue
                }
                
                pages.append(page!)
            }
        } else if (pageRange == .even) {
            for i in 0 ..< pageCount {
                if ((i % 2) == 0) {
                    continue
                }
                let page = self.documentModel!.document?.page(at: UInt(i))
                if (page == nil) {
                    continue
                }
                
                pages.append(page!)
            }
        } else if (pageRange == .current) {
            let page = self.prePDFView?.currentPage()
            if (page != nil) {
                pages.append(page!)
            }
        } else if (pageRange == .custom) {
            let array = self.findSelectPage(pageRangeString: pageString)
            if array.count == 0 {

            } else {
                for i in 0 ..< array.count {
                    let index = array[i]
                    if (index > pageCount || index < 1) {
                        continue
                    }
                    let page = self.documentModel?.document?.page(at: UInt(index-1))
                    if (page == nil) {
                        continue
                    }
                    
                    pages.append(page!)
                }
            }
        }
        return pages
    }
    
    private func _convertButtonAction(limit: Bool = false) {
        var pages: [Int] = []
        let filePath = self.getConvertFileSavePath()
        if (FileManager.default.fileExists(atPath: filePath)) {
            try?FileManager.default.removeItem(atPath: filePath)
        }
        if (limit) {
            if let _ = KMTools.saveWatermarkDocument(document: self.prePDFView!.document, to: URL(fileURLWithPath: filePath), removePWD: true) {
                for i in 0 ..< self.prePDFView!.document.pageCount {
                    if (i >= 10) {
                        break
                    }
                    pages.append(Int(i)+1)
                }
            }
        } else {
            if ((self.prePDFView?.document?.writeDecrypt(to: URL(fileURLWithPath: filePath)))!) {
                for i in 0 ..< self.prePDFView!.document.pageCount {
                    pages.append(Int(i)+1)
                }
            }
        }
        
        if (pages.count <= 0) {
            let alert = NSAlert()
            alert.alertStyle = .warning
            alert.messageText = NSLocalizedString("Invalid page range or the page number is out of range. Please try again.", comment: "")
            alert.runModal()
            return
        }
        
        DispatchQueue.main.async {
            NSPanel.savePanel(self.window!) { panel in
                var url: URL = self.prePDFView!.document.documentURL
                if (self.oriDocumentUrl != nil) {
                    url = self.oriDocumentUrl!
                }
                let name = url.deletingPathExtension().lastPathComponent
                panel.nameFieldStringValue = name
                panel.allowedFileTypes = [self.fileExtension]
            } completion: { response, url in
                if (response == .cancel) {
                    return
                }
                let outputFolderPath = url!.deletingLastPathComponent().path
                let convert = self.initConvert()
                self.convert = convert
                convert.password = self.documentModel!.password
                convert.outputFolderPath = outputFolderPath
                convert.filePath = filePath
                convert.pages = pages
                var fileName = url!.deletingPathExtension().lastPathComponent
                if (self.fileExtension.isEmpty) {
                    fileName = url!.lastPathComponent
                }
                //            if (fileName.isEmpty) {
                //                fileName = NSLocalizedString("Untitled", comment: "")
                //            }
                convert.outputFileName = fileName
                self.convertModelAppendParams(convert: convert)
                
                DispatchQueue.main.async {
                    self.showProgressWindow()
                    self.progressController?.maxValue = Double(convert.pages.count)
                }
#if VERSION_DMG
                if self.settingView?.ocrItemView?.checkVC?.state == .Checked {
                    let bundlePath = kResourcePath?.stringByAppendingPathComponent("DocumentAI.bundle")
                    CPDFConvertKit.setOCRModelPath(bundlePath)
                }
#else
                let bundlePath = Bundle.main.path(forResource: "DocumentAI", ofType: "bundle")
                CPDFConvertKit.setOCRModelPath(bundlePath)
#endif
                DispatchQueue.global().async {
                    KMPDFConvertManager.defaultManager.convert(convert: convert, progress: { index in
                        DispatchQueue.main.async {
                            self.progressController?.increment(by: 1.0)
                        }
                    }) { [unowned self] finished, error in
                        self.hiddenProgressWindow()
                        
                        // 清除临时文件
                        if (FileManager.default.fileExists(atPath: filePath)) {
                            try?FileManager.default.removeItem(atPath: filePath)
                        }
                        if finished {
                            self._clearData()
                            self.recordConvertCount()
                            cancelButtonAction()
                            if FileManager.default.fileExists(atPath: convert.outputFilePath) {
                                NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: convert.outputFilePath)])
                            }
                        } else {
                            var errorString = ""
                            let myError: NSError? = error as? NSError
                            if myError?.code == 1 {
                                errorString = NSLocalizedString("Password required or incorrect password. Please re-enter your password and try again", comment: "")
                            } else if myError?.code == 2 {
                                errorString = NSLocalizedString("The license doesn't allow the permission", comment: "")
                            } else if myError?.code == 3 {
                                errorString = NSLocalizedString("Malloc failure", comment: "")
                            } else if myError?.code == 4 {
                                errorString = NSLocalizedString("Unknown error in processing conversion. Please try again later", comment: "")
                            } else if myError?.code == 5 {
                                errorString = NSLocalizedString("Unknown error in processing PDF. Please try again later", comment: "")
                            } else if myError?.code == 6 {
                                errorString = NSLocalizedString("File not found or could not be opened. Check if your file exists or choose another file to convert", comment: "")
                            } else if myError?.code == 7 {
                                errorString = NSLocalizedString("File not in PDF format or corruptead. Change a PDF file and try again", comment: "")
                            } else if myError?.code == 8 {
                                errorString = NSLocalizedString("Unsupported security scheme", comment: "")
                            } else if myError?.code == 9 {
                                errorString = NSLocalizedString("Page not found or content error", comment: "")
                            } else {
                                errorString = NSLocalizedString("Table not found", comment: "")
                            }
                            
                            let alert = NSAlert()
                            alert.alertStyle = .critical
                            alert.messageText = NSLocalizedString("Conversion Failed", comment: "")
                            alert.informativeText = errorString
                            alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
                            alert.runModal()
                        }
                    }
                }
            }
        }
    }
    
    // MARK: - Notifation Methods
    
    @objc private func km_windowWillCloseNotifation() {
        Task { @MainActor in
            if await (KMLightMemberManager.manager.canUseAdvanced() == false) {
                self.limitCount = true
            } else {
                self.limitCount = false
            }
            
            if await (KMLightMemberManager.manager.canPayFunction() == false) {
                #if VERSION_DMG
                if (self.limitCount) { // 未登录
                    self.settingView?.tipView?.isHidden = true
                } else {
                    self.settingView?.tipView?.isHidden = false
                }
                #else
                self.settingView?.tipView?.isHidden = false
                #endif
            } else {
                self.limit = false
            }
        }
    }
    
    // MARK: Progress
    func showProgressWindow() {
        self.hiddenProgressWindow()
        
        let progress = SKProgressController()
        progress.window?.backgroundColor = NSColor.km_init(hex: "#36383B")
        progress.window?.contentView?.wantsLayer = true
        progress.window?.contentView?.layer?.backgroundColor = NSColor.km_init(hex: "#36383B").cgColor
        progress.progressField.textColor = NSColor.white
        progress.message = NSLocalizedString("Converting...", comment: "")

        progress.closeBlock = { [weak self] in
            if let convert = self?.convert {
                KMPDFConvertManager.defaultManager.cancel(convert: convert)
            }
        }
        
        self.progressController = progress
        self.window?.beginSheet(progress.window!)
    }
    
    func hiddenProgressWindow() {
        if (self.progressController != nil) {
            self.window?.endSheet((self.progressController?.window)!)
            self.progressController = nil
        }
    }
    
    func getCurrentLanguage() -> String {
//        return Bundle.main.preferredLocalizations.first!
        let array: [String] = UserDefaults.standard.object(forKey: "AppleLanguages") as! [String]
        return array.first!
    }
    
    /// 存储用户的选择的语言
    func saveLanugageSelectedIndex(index: Int) {
        UserDefaults.standard.setValue("\(index)", forKey: kKMConvertLanugageSelectedIndex)
        UserDefaults.standard.synchronize()
    }
    
    private func _clearData() {
        if let _ = self.oriDocumentUrl {
            if let data = self.prePDFView?.document.documentURL.path, FileManager.default.fileExists(atPath: data) {
                try?FileManager.default.removeItem(atPath: data)
            }
        }
    }
}

extension KMConvertBaseWindowController: NSTextFieldDelegate {
    func controlTextDidChange(_ obj: Notification) {
        if numberTextField.isEqual(to: obj.object) {
            let textField: NSTextField = obj.object as! NSTextField
            var value: String = ""
            for ch in textField.stringValue {
                if ch != "0" && ch != "1" && ch != "2" && ch != "3" && ch != "4" && ch != "5" && ch != "6" && ch != "7" && ch != "8" && ch != "9" {

                } else {
                    if value.isEmpty && ch == "0" {
                        
                    } else {
                        value.append(ch)
                    }
                }
            }
            
            if value.isEmpty {
                value.append("1")
            } else {
                if Int(value)! <= 0 {
                    value = "1"
                } else if Int(value)! > self.prePDFView!.document!.pageCount {
                    let number: Int = Int(self.prePDFView!.document!.pageCount)
                    value = "\(number)"
                }
            }
            
            numberTextField.stringValue = value
        }
    }
    
    func controlTextDidEndEditing(_ obj: Notification) {
        if numberTextField.isEqual(to: obj.object) {
            if (numberTextField.stringValue.isEmpty) {
                numberTextField.stringValue = "1"
                self.prePDFView?.go(toPageIndex: 0, animated: false)
                self.currentPageIndex = 1
                
                self.updateBackAndNextButtonState()
                return
            }
            let number: Int = Int(numberTextField.stringValue)!
            if number > 0 && number <= self.prePDFView!.document!.pageCount {
                guard let page = self.prePDFView?.document?.page(at: UInt(number-1)) else {
                    return
                }
                self.prePDFView?.go(to: page)
                currentPageIndex = number
                
                self.updateBackAndNextButtonState()
            }
        }
    }
}

extension KMConvertBaseWindowController: CPDFViewDelegate {
    func pdfViewCurrentPageDidChanged(_ pdfView: CPDFView!) {
        let currentIndex = pdfView.currentPageIndex
        currentPageIndex = currentIndex + 1
        numberTextField.stringValue = "\(currentIndex+1)"
        
        self.updateBackAndNextButtonState()
    }
}

let kKMConvertCountKey = "KMConvertCountKey"
let kKMConvertCountMax = 2
extension KMConvertBaseWindowController {
    func convertCountIsReach() -> Bool {
        #if VERSION_DMG
        return false
        #else
        let cnt = self.getConvertCount()
        if (cnt >= kKMConvertCountMax) {
            return true
        }
        return false
        #endif
    }
    
    func recordConvertCount() {
        let cnt = self.getConvertCount()
        UserDefaults.standard.setValue(cnt+1, forKey: kKMConvertCountKey)
        UserDefaults.standard.synchronize()
    }
    
    func clearConvertRecordCount() {
        UserDefaults.standard.setValue(0, forKey: kKMConvertCountKey)
        UserDefaults.standard.synchronize()
    }
    
    private func getConvertCount() -> Int {
        return UserDefaults.standard.integer(forKey: kKMConvertCountKey)
    }
}