//
//  KMBatchOperateImageToPDFViewController.swift
//  PDF Reader Pro
//
//  Created by liujiajie on 2023/12/5.
//

import Cocoa

class KMBatchOperateImageToPDFViewController: KMBatchOperateBaseViewController, KMImageToPDFMethodDelegate, NSPopoverDelegate{
    
    @IBOutlet var outputTypeLabel: NSTextField!
    @IBOutlet var createNewPDFBtn: NSButton!
    @IBOutlet var btnMerge: NSButton!
    @IBOutlet var appendPDFBtn: NSButton!
    @IBOutlet var appendTextField: NSTextField!
    @IBOutlet var appendOtherPDFBtn: NSButton!
    @IBOutlet var appendBackView: NSView!
    
    @IBOutlet var ocrLabel: NSTextField!
    @IBOutlet var ocrSelectBtn: NSButton!
    @IBOutlet var languaeBox: NSBox!
    @IBOutlet var languageButton: NSButton!
    @IBOutlet var saveAsButton: NSButton!
    @IBOutlet var planButton: NSButton!
    @IBOutlet var selectLanguageLabel: NSTextField!
    @IBOutlet var planBox: NSBox!
    
    @IBOutlet var actionButton: NSButton!
    
    var password: String = ""
    
    lazy var method: KMImageToPDFMethod = {
        let method = KMImageToPDFMethod()
        method.imageTopdfDelegate = self
        return method
    }()
    
    override var interfaceStatus: KMBatchOperateInterfaceStatus?{
        set{
            super.interfaceStatus = newValue
            if newValue == .PrepareProcess {
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
                    var files = NSMutableArray()
                    for url in self.successFilePathURLArray! {
                        if FileManager.default.fileExists(atPath: url.path) {
                            files.add(url)
                        }
                    }
                    if files.count > 0 {
                        let workspace = NSWorkspace.shared
                        workspace.activateFileViewerSelecting(files as! [URL])
                    }
                }
                self.actionButton.tag = 1
                self.actionButton.title = NSLocalizedString("Save as PDF", comment: "")
                self.actionButton.setTitleColor(KMAppearance.Layout.w0Color())
                self.actionButton.isEnabled = true
                self.actionButton.layer?.backgroundColor = KMAppearance.Interactive.m0Color().cgColor
            } else {
                self.actionButton.tag = 0
                self.actionButton.layer?.backgroundColor = KMAppearance.Interactive.m0Color().cgColor
                self.actionButton.setTitleColor(KMAppearance.Layout.w0Color())
                self.actionButton.isEnabled = false
            }
        }
        get{
            return super.interfaceStatus
        }
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.localizedLanguage()
        self.configuUI()
        
        NotificationCenter.default.addObserver(self, selector: #selector(OCRSelectedLanguagesChangeNotification(notification:)), name: NSNotification.Name("KMOCRSelectedLanguagesChangeNotification"), object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(OCRSelectedPlanChangeNotification(notification:)), name: NSNotification.Name("KMOCRSelectedPlanChangeNotification"), object: nil)
        
        NotificationCenter.default.addObserver(self, selector: #selector(themeChanged(notification:)), name: NSNotification.Name("AppleInterfaceThemeChangedNotification"), object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(batchFilesCountNotification(notification:)), name: NSNotification.Name("KMBatchFilesCountNotification"), object: nil)
    }
    func localizedLanguage() {
        self.outputTypeLabel.stringValue = KMLocalizedString("Output",nil)
        self.btnMerge.title = KMLocalizedString("Merge All", nil)
        self.createNewPDFBtn.title = KMLocalizedString("New PDF Document", nil)
        self.appendPDFBtn.title = KMLocalizedString("Append To Existing File", nil)
        self.appendTextField.placeholderString = KMLocalizedString("Select a File", nil)
        self.selectLanguageLabel.stringValue = KMLocalizedString("Select OCR Language:",nil)
        self.ocrSelectBtn.title = KMLocalizedString("OCR Plan",nil)
        self.updateLanguageButton((KMGOCRManager.default().selectedLanguages?.value(forKeyPath: KMGOCRLanguageStringKey) as? [String]))
        
        self.actionButton.title = KMLocalizedString("Save as PDF", nil)
        self.saveAsButton.title = KMLocalizedString("Save as TXT", nil)
        self.OCRSelectedPlanChangeAction()
    }
    func configuUI() {
        self.view.wantsLayer = true
        
        appendOtherPDFBtn.wantsLayer = true
        appendBackView.wantsLayer = true
        appendBackView.layer?.borderWidth = 0.5
        
        self.actionButton.wantsLayer = true
        self.actionButton.layer?.backgroundColor = KMAppearance.Interactive.m0Color().cgColor
        self.appendOtherPDFBtn.layer?.backgroundColor = KMAppearance.Interactive.s0Color().withAlphaComponent(0.4).cgColor
        self.actionButton.setTitleColor(KMAppearance.Layout.w0Color())
        self.actionButton.layer?.cornerRadius = 1.0
        
        self.createNewPDFBtn.setTitleColor(KMAppearance.Layout.h0Color())
        self.btnMerge.setTitleColor(KMAppearance.Layout.h0Color())
        self.appendPDFBtn.setTitleColor(KMAppearance.Layout.h0Color())
        
        self.ocrSelectBtn.setTitleColor(KMAppearance.Layout.h0Color())
        self.saveAsButton.setTitleColor(KMAppearance.Layout.h0Color())
        self.selectLanguageLabel.textColor = KMAppearance.Layout.h0Color()
        self.languageButton.isEnabled = false
        self.planButton.isEnabled = false
        self.saveAsButton.isEnabled = false
        
        appendTextField.backgroundColor = KMAppearance.Layout.l1Color()
        planButton.wantsLayer = true
        appendTextField.wantsLayer = true
        planButton.wantsLayer = true
        appendTextField.layer?.cornerRadius = 1.0
        languageButton.layer?.backgroundColor = NSColor.clear.cgColor
        languaeBox.borderColor = KMAppearance.Interactive.s0Color()
        planBox.borderColor = KMAppearance.Interactive.s0Color()
        languaeBox.fillColor = KMAppearance.Layout.l1Color()
        planBox.fillColor = KMAppearance.Layout.l1Color()
        
        self.updateViewColor()
    }
    func updateViewColor() {
        if KMAppearance.isDarkMode() {
            self.view.layer?.backgroundColor = NSColor(red: 0.055, green: 0.067, blue: 0.078, alpha: 1).cgColor
            appendBackView.layer?.borderColor = NSColor(red: 86/255.0, green: 88/255.0, blue: 90/255.0, alpha: 1).cgColor
            appendBackView.layer?.backgroundColor = NSColor(red: 57/255.0, green: 60/255.0, blue: 62/255.0, alpha: 1).cgColor
        } else {
            self.view.layer?.backgroundColor = NSColor(red: 0.922, green: 0.925, blue: 0.941, alpha: 1).cgColor
            appendBackView.layer?.borderColor = NSColor(red: 218/255.0, green: 219/255.0, blue: 222/255.0, alpha: 1).cgColor
            appendBackView.layer?.backgroundColor = NSColor.white.cgColor;
        }
    }
    func updateLanguageButton(_ languages: [String]?) {
        if languages?.count ?? 0 < 1 {
            self.languageButton.title = " " + KMLocalizedString("Auto Detection", nil)
            return
        }
        var languageName: String = ""
        if languages?.count ?? 0 > 0 {
            for i in 0..<(languages?.count ?? 0) {
                let language = languages?[i]
                if i == 0 {
                    languageName = language ?? ""
                } else {
                    languageName = languageName.appendingFormat(",%@", language ?? "")
                }
            }
        } else {
            languageName = ""
        }
        
        self.languageButton.title = " " + languageName
    }
    func converArrType(arr: Array<KMBatchOperateFile>, keyString: String) -> [String] {
        let newArr = NSMutableArray()
        for item in arr {
            newArr.add(item.filePath)
        }
        return newArr as! [String]
    }
    func isConnectionAvailable() -> Bool {
        //        var isExistenceNetwork = true
        //        let reach = Reachability(hostname: "www.apple.com")
        //        let status: NetworkStatus = NetworkStatus(rawValue: (reach?.currentReachabilityStatus())!.rawValue)
        //        switch status.rawValue {
        //        case 0:
        //            isExistenceNetwork = false
        //        case 1:
        //            isExistenceNetwork = true
        //        case 2:
        //            isExistenceNetwork = true
        //        default:
        //            break
        //        }
        if Reachability.forInternetConnection().currentReachabilityStatus().rawValue == 0 {
            return false
        }
        return true
    }
    func beginImageToPDF() {
        if self.files?.count ?? 0 < 1 {
            return
        }
        let photoArray = converArrType(arr: self.files!, keyString: "")
        var path: String = ""
        var isMerge = false
        var isCreatNewPDF = false
        var isOCR = false
        if self.ocrSelectBtn.state == .on {
            isOCR = true
        }
        
        var isSaveAs = false
        if self.saveAsButton.state == .on {
            isSaveAs = true
        }
        
        let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
        if isOCR && !self.isConnectionAvailable() && plan == 0 {
            let alert = NSAlert()
            alert.alertStyle = .critical
            alert.messageText = NSLocalizedString("Connection Error", comment: "")
            alert.informativeText = NSLocalizedString("Please make sure your internet connection is available.", comment: "")
            alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
            if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) {
                alert.beginSheetModal(for: self.view.window!, completionHandler: nil)
            } else {
                alert.runModal()
            }
            return
        }
        
        if self.createNewPDFBtn.state == .on {
            if (self.choosePath.count < 1) {
                let alert = NSAlert()
                alert.alertStyle = .critical
                alert.messageText = String(format: NSLocalizedString("Output Folder cannot be empty.", comment: ""))
                alert.runModal()
                return
            }
            
            path = self.choosePath
            
            if self.btnMerge.state == .on {
                isMerge = true
            }
            isCreatNewPDF = true
            
        } else {
            let appenString = self.appendTextField.stringValue
            if appenString.isEmpty {
                let alert = NSAlert()
                alert.alertStyle = .critical
                alert.messageText = String(format: NSLocalizedString("Select a File", comment: ""))
                alert.runModal()
                return
            }
            
            path = self.appendTextField.stringValue
            isMerge = true
            isCreatNewPDF = false
        }
        
        self.languageButton.isEnabled = false
        self.planButton.isEnabled = false
        self.method.password = self.password
        self.interfaceStatus = .Processing
        
        self.method.exportPDFFile(fileArray: photoArray, savePath: path, isOCR: isOCR, isCreatPDF: isCreatNewPDF, isMerge: isMerge, isSaveAsText: isSaveAs) { [weak self] savePath, errorArr, errorOCRArray in
            
            self?.languageButton.isEnabled = true
            self?.planButton.isEnabled = true
            self?.interfaceStatus = .PrepareProcess
            if errorArr.count > 0 {
                let dict: [String: Any] = ["isMerge": false, "isSuccess": false]
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: "KMBatchOperateImageToPDFSuccessNotification"), object: self, userInfo: dict)
                
                let alert = NSAlert()
                alert.messageText = NSLocalizedString("Conversion Failed", comment: "")
                alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
                alert.informativeText = "\(errorArr)"
                alert.alertStyle = .informational
                alert.runModal()
            } else {
                if errorOCRArray.count > 0 {
                    var contextString = NSLocalizedString("Some problems occurred during the last operation:", comment: "")
                    for filePath in errorOCRArray {
                        contextString += "\n" + (filePath as AnyObject).lastPathComponent
                    }
                    
                    let alert = NSAlert()
                    alert.messageText = NSLocalizedString("Converted Successfully", comment: "")
                    alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
                    alert.informativeText = contextString
                    alert.alertStyle = .informational
                    let response = alert.runModal()
                    if response == .OK {
                        self?.viewFileAtFinder(fileName: savePath)
                    }
                } else {
                    self?.viewFileAtFinder(fileName: savePath)
                }
            }
        }
    }
    
    func viewFileAtFinder(fileName: String) {
        let dict = ["isMerge": true, "isSuccess": true]
        NotificationCenter.default.post(name: Notification.Name("KMBatchOperateImageToPDFSuccessNotification"), object: self, userInfo: dict)
        let workspace = NSWorkspace.shared
        let url = URL(fileURLWithPath: fileName)
        workspace.activateFileViewerSelecting([url])
    }
    
    
    //MARK: Notification
    @objc func OCRSelectedLanguagesChangeNotification(notification: Notification) {
        let selectedLanguages = notification.object/* as? [KMBatchOperateFile]*/
        self.updateLanguageButton(selectedLanguages as? [String])
    }
    @objc func OCRSelectedPlanChangeNotification(notification: Notification) {
        self.OCRSelectedPlanChangeAction()
    }
    @objc func themeChanged(notification: Notification) {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
            self.updateViewColor()
        }
    }
    func OCRSelectedPlanChangeAction() {
        let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
        if plan == 0 {
            self.planButton.title = " " + KMLocalizedString("Plan 1 (Online)", nil)
        } else {
            self.planButton.title = " " + KMLocalizedString("Plan 2 (Offline)", nil)
        }
        KMGOCRManager.default().selectedLanguages = NSMutableArray()
        self.updateLanguageButton(KMGOCRManager.default().selectedLanguages?.value(forKeyPath: KMGOCRLanguageStringKey) as? [String])
    }
    @objc func batchFilesCountNotification(notification: Notification)  {
        let files: Array? = notification.object as? [KMBatchOperateFile]
        self.files? = files ?? []
//        if files?.count ?? 0 > 0 {
//            haveFiles = true
//        } else {
//            haveFiles = false
//        }
    }
    
    @IBAction func buttonClicked_CreateNewPDF(_ sender: NSButton) {
        if (sender.state == .on) {
            self.btnMerge.isEnabled = true
            self.appendPDFBtn.state = .off
            self.appendOtherPDFBtn.isEnabled = false
        }
    }
    
    @IBAction func buttonClicked_AppendOtherPDF(_ sender: NSButton) {
        if (sender.state == .on) {
            self.createNewPDFBtn.state = .off
            self.btnMerge.isEnabled = false
            self.appendOtherPDFBtn.isEnabled = true
        }
    }
    
    @IBAction func buttonClicked_OCRSelect(_ sender: NSButton) {
        //MARK: 判断是否付费用户
        
        if (sender.state == .on) {
            self.languageButton.isEnabled = true
            self.planButton.isEnabled = true
            self.saveAsButton.isEnabled = true
        } else {
            self.languageButton.isEnabled = false
            self.planButton.isEnabled = false
            self.saveAsButton.isEnabled = false
        }
    }
    
    @IBAction func buttonClicked_ChooseLanguage(_ sender: NSButton) {
        let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
        if plan == 0 {
            KMGOCRManager.default().ocrType = .google
        } else {
            KMGOCRManager.default().ocrType = .apple
        }
        let popover = NSPopover()
        popover.delegate = self
        popover.contentViewController = KMLanguageViewController(nibName: "KMLanguageViewController", bundle: Bundle.main)
        popover.animates = true
        popover.behavior = .transient
        popover.show(relativeTo: sender.bounds, of: sender as NSView, preferredEdge: .minX)
    }
    
    @IBAction func buttonClicked_ChoosePlan(_ sender: NSButton) {
        let popover = NSPopover()
        popover.delegate = self
        popover.contentViewController = KMPlanViewController(nibName: "KMPlanViewController", bundle: Bundle.main)
        popover.animates = true
        popover.behavior = .transient
        popover.show(relativeTo: sender.bounds, of: sender as NSView, preferredEdge: .minX)
    }
    
    @IBAction func buttonClicked_ImageToPDF(_ sender: NSButton) {
        //MARK: 判断是否付费用户,展示iap界面
        if self.files?.count ?? 0 < 1 {
            return
        }
        if sender.tag == 1 {
            self.choosePath = ""
            var hasTask = false
            for i in 0..<(self.files?.count ?? 0) {
                let file = self.files?[i]
                file?.currentOperateInfo?.resetState()
                if file?.fileType == .Image {
                    hasTask = true
                }
            }
            if !hasTask {
                NSSound.beep()
                return
            }
            
            var isOCR = false
            if self.ocrSelectBtn.state == .on {
                isOCR = true
            }
            
            var isSaveAs = false
            if self.saveAsButton.state == .on {
                isSaveAs = true
            }
            
            let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
            if isOCR && !isConnectionAvailable() && plan == 0 {
                let alert = NSAlert()
                alert.alertStyle = .critical
                alert.messageText = NSLocalizedString("Connection Error", comment: "")
                alert.informativeText = NSLocalizedString("Please make sure your internet connection is available.", comment: "")
                alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
                if let window = self.view.window {
                    alert.beginSheetModal(for: window, completionHandler: nil)
                } else {
                    alert.runModal()
                }
                return
            }
            
            if self.createNewPDFBtn.state == .off {
                let appenString = self.appendTextField.stringValue
                if appenString.isEmpty {
                    let alert = NSAlert()
                    alert.alertStyle = .critical
                    alert.messageText = NSLocalizedString("Select a File", comment: "")
                    alert.runModal()
                    return
                }
            }
            
            let openPanel = NSOpenPanel()
            openPanel.canChooseFiles = false
            openPanel.canChooseDirectories = true
            openPanel.canCreateDirectories = true
            openPanel.beginSheetModal(for: self.view.window!) { (result) in
                if result == .OK {
                    for fileURL in openPanel.urls {
                        self.choosePath = fileURL.path
                        self.beginImageToPDF()
                    }
                }
            }
        } else { // Do something else }
            
            
        }
    }
    
    @IBAction func buttonItemClicked_AppendOtherPDF(_ sender: NSButton) {
        let openPanel = NSOpenPanel()
        openPanel.allowedFileTypes = ["pdf"]
        openPanel.canChooseDirectories = false
        openPanel.allowsMultipleSelection = false
        openPanel.beginSheetModal(for: self.view.window!) { (result) in
            if result == .OK {
                guard let url = openPanel.url else { return }
                guard let document = PDFDocument(url: url) else {
                    let alert = NSAlert()
                    alert.alertStyle = .critical
                    alert.messageText = NSLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.", comment: "")
                    alert.runModal()
                    return
                }
                if !document.allowsCopying || !document.allowsPrinting {
                    let alert = NSAlert()
                    alert.alertStyle = .critical
                    alert.messageText = NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "")
                    alert.runModal()
                    return
                }
                
                if document.isLocked {
                    let com = PasswordWindowController(windowNibName: "PasswordWindowController")
                    com.fileURL = url
                    com.beginSheetModal(for: self.view.window!) { (password) in
                        if password.count > 0 {
                            self.password = password
                            self.appendTextField.stringValue = url.path
                        }
                    }
                } else {
                    self.appendTextField.stringValue = url.path
                }
            }
        }
    }
    
    @IBAction func buttonClicked_Help(_ sender: NSButton) {
        let helpController = NSViewController()
        let textView = NSTextView(frame: NSRect(x: 0, y: 0, width: 300.0, height: 100.0))
        textView.backgroundColor = NSColor.clear
        textView.isEditable = false
        textView.layer?.cornerRadius = 6
        let tStrAuto = NSLocalizedString("Choose automatic language detection for better OCR results.", comment: "")
        let tStrVPN = NSLocalizedString("The OCR service works via an internet connection. We would suggest you to perform OCR using a VPN connection while the service is limited.", comment: "")
        let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
        if plan == 0 {
            textView.string = "\(tStrAuto)\n\n\(tStrVPN)"
        } else {
            textView.frame = NSRect(x: 0, y: 0, width: 300.0, height: 40.0)
            textView.string = tStrAuto
        }
        helpController.view = textView
        let popover = NSPopover()
        popover.delegate = self
        popover.contentViewController = helpController
        popover.animates = true
        popover.behavior = .transient
        popover.show(relativeTo: sender.bounds, of: sender as NSView, preferredEdge: .minY)
    }
    
    
    
    
    //MARK: KMImageToPDFMethodDelegate
    func imageToPDFMethod(_ method: KMImageToPDFMethod, progress: Float) {
        
    }
}