//
//  KMCompressWindowController.swift
//  PDF Master
//
//  Created by tangchao on 2022/11/25.
//

import Cocoa

protocol KMLoadingProtocol: NSObjectProtocol {
    
    func beginLoading()
    func endLoading()
}

extension NSView: KMLoadingProtocol {
    var markViewTag: Int {
        get {
            return 123456
        }
    }
    
    func beginLoading() {
        self .endLoading()
        
        if (Thread.isMainThread) {
            self.beginLoadingInMainThread()
        } else {
            DispatchQueue.main.async {
                self.beginLoadingInMainThread()
            }
        }
    }
    
    func endLoading() {
        if (Thread.isMainThread) {
            self.endLoadingInMainThread()
        } else {
            DispatchQueue.main.async {
                self.endLoadingInMainThread()
            }
        }
    }
    
    
    // MARK: exe in main thread
    
    private func beginLoadingInMainThread() {
        let maskView = self.createLoadingMaskView()
        self.addSubview(maskView)
        maskView.frame = self.bounds
        maskView.autoresizingMask = [.minXMargin, .maxXMargin, .minYMargin, .maxYMargin]
        
        let loadingIndicator = self.createLoadingIndicator()
        maskView.addSubview(loadingIndicator)
        let size = NSMakeSize(32, 32)
        let left: CGFloat = (NSWidth(self.bounds)-size.width) * 0.5
        let top: CGFloat = (NSHeight(self.bounds)-size.height) * 0.5
        loadingIndicator.frame = NSMakeRect(left, top, size.width, size.height)
        loadingIndicator.autoresizingMask = [.minXMargin, .maxXMargin, .minYMargin, .maxYMargin]
        
        loadingIndicator.startAnimation(nil)
    }
    
    private func endLoadingInMainThread() {
        let maskView = self.viewWithTag(self.markViewTag)
        if (maskView == nil) {
            return
        }
        
        let loadingIndicator = maskView?.subviews.first
        if (loadingIndicator is NSProgressIndicator == false) {
            return
        }
        
        (loadingIndicator as! NSProgressIndicator).stopAnimation(nil)
        loadingIndicator?.removeFromSuperview()
        maskView?.removeFromSuperview()
    }
    
    // MARK: Init View
    
    private func createLoadingMaskView() -> NSButton {
        let mask = NSButton()
        mask.tag = self.markViewTag
        mask.isBordered = false
        mask.title = ""
        mask.target = self
        mask.action = #selector(loadingMask_Click)
        
        return mask
    }
    
    private func createLoadingIndicator() -> NSProgressIndicator {
        let loading = NSProgressIndicator()
        loading.style = .spinning
        loading.controlSize = .regular
        loading.isIndeterminate = true
        
        return loading
    }
    
    @objc private func loadingMask_Click() {}
}

typealias KMCompressWindowControllerItemClick = (Int)->()
typealias KMCompressWindowControllerResultCallback = (_ result: Bool,_ openDocuemt: Bool, _ fileURL: URL, _ error: String)->()
class KMCompressWindowController: NSWindowController {

    @IBOutlet weak var titleLabel: NSTextField!
    
    @IBOutlet weak var largeBox: NSBox!
    @IBOutlet weak var standardBox: NSBox!
    @IBOutlet weak var smallBox: NSBox!
    @IBOutlet weak var minimumBox: NSBox!
    
    @IBOutlet weak var batchButton: NSButton!
    @IBOutlet weak var cancelBox: NSBox!
    @IBOutlet weak var compressBox: NSBox!
    
    var documentURL: URL!
    var password: String!
    private var datas: [String] = []
    var selectIndex = 2
    
    var itemClick       : KMCompressWindowControllerItemClick!
    var resultCallback  : KMCompressWindowControllerResultCallback!
    var largeVC         : KMDesignButton!
    var standardVC      : KMDesignButton!
    var smallVC         : KMDesignButton!
    var minimumVC       : KMDesignButton!
    var cancelVC        : KMDesignButton!
    var compressVC      : KMDesignButton!

    deinit {
        KMPrint("KMCompressWindowController 已释放")
    }
    
    override func windowDidLoad() {
        super.windowDidLoad()
        self.window?.appearance = NSAppearance(named: .aqua)
        largeVC = KMDesignButton.init(withType: .RadioButton)
        standardVC = KMDesignButton.init(withType: .RadioButton)
        smallVC = KMDesignButton.init(withType: .RadioButton)
        minimumVC = KMDesignButton.init(withType: .RadioButton)
        cancelVC = KMDesignButton.init(withType: .Text)
        compressVC = KMDesignButton.init(withType: .Text)
        largeBox.fillColor = .clear
        largeBox.contentView = largeVC.view
        standardBox.fillColor = .clear
        standardBox.contentView = standardVC.view
        smallBox.fillColor = .clear
        smallBox.contentView = smallVC.view
        minimumBox.fillColor = .clear
        minimumBox.contentView = minimumVC.view
        cancelBox.fillColor = .clear
        cancelBox.contentView = cancelVC.view
        compressBox.fillColor = .clear
        compressBox.contentView = compressVC.view
        
        titleLabel.stringValue = NSLocalizedString("Compress", comment: "")
        
        batchButton.isBordered = false
        batchButton.title = NSLocalizedString("Batch", comment: "")
        batchButton.wantsLayer = true
        batchButton.layer?.borderWidth = 1
        batchButton.layer?.borderColor = NSColor.black.cgColor
        batchButton.layer?.cornerRadius = 4
        batchButton.target = self
        batchButton.action = #selector(batchButtonAction)
        batchButton.isHidden = true
        
        cancelVC.target = self
        cancelVC.action = #selector(cancelButtonAction)
        cancelVC.stringValue = NSLocalizedString("Cancel", comment: "")
        cancelVC.button(type: .Sec, size: .m)
        cancelVC.button.keyEquivalent = KMKeyEquivalent.esc.string()
        
        compressVC.target = self
        compressVC.action = #selector(compressButtonAction)
        compressVC.stringValue = NSLocalizedString("Compress", comment: "")
        compressVC.button(type: .Cta, size: .m)
        compressVC.button.keyEquivalent = KMKeyEquivalent.enter
        
        largeVC.target = self
        largeVC.action = #selector(self.radioButtonAction(_:))
        largeVC.stringValue = NSLocalizedString("Large File Size", comment: "")
        largeVC.checkbox_radio()
        
        standardVC.target = self
        standardVC.action = #selector(self.radioButtonAction(_:))
        standardVC.stringValue = NSLocalizedString("Standard File Size", comment: "")
        standardVC.checkbox_radio()

        smallVC.target = self
        smallVC.action = #selector(self.radioButtonAction(_:))
        smallVC.stringValue = NSLocalizedString("Small File Size", comment: "")
        smallVC.checkbox_radio()

        minimumVC.target = self
        minimumVC.action = #selector(self.radioButtonAction(_:))
        minimumVC.stringValue = NSLocalizedString("Minimum File Size", comment: "")
        minimumVC.checkbox_radio()
        
        self.initUIProperty()
        
        smallVC.state = .Checked
    }
    
    private func initUIProperty() {
        self.titleLabel.textColor = NSColor.titleColor()
        self.titleLabel.font = .SFProTextSemibold(16)
        
        self.batchButton.setTitleColor(NSColor.buttonTitleColor())
        self.batchButton.layer?.borderColor = NSColor.buttonBorderColor().cgColor
        self.batchButton.font = .SFProTextRegular(14)
    }
    
    @objc func radioButtonAction(_ sender: NSButton) {
        largeVC.state = .Norm
        standardVC.state = .Norm
        smallVC.state = .Norm
        minimumVC.state = .Norm
        if (largeVC.button == sender) {
            largeVC.state = .Checked
            self.selectIndex = 0
        } else if (standardVC.button == sender) {
            standardVC.state = .Checked
            self.selectIndex = 1
        } else if (smallVC.button == sender) {
            smallVC.state = .Checked
            self.selectIndex = 2
        } else if (minimumVC.button == sender) {
            minimumVC.state = .Checked
            self.selectIndex = 3
        }
    }
    
    @objc func batchButtonAction() {
        guard let callback = itemClick else {
            return
        }
        
        callback(1)
    }
    
    @objc func cancelButtonAction() {
        guard let callback = itemClick else {
            return
        }
        
        callback(2)
    }
    
    @objc func compressButtonAction() {        
        if documentURL == nil {
            return
        }
        
        NSPanel.savePanel(self.window!, true) { panel in
            panel.nameFieldStringValue = ""+self.documentURL.deletingPathExtension().lastPathComponent+"_Compressed"
            panel.allowedFileTypes = ["pdf"]
        } completion: { response, url, isOpen in
            if (response == .cancel) {
                return
            }
            
            self.beginLoading()
            DispatchQueue.main.async {
                let docuemt = CPDFDocument.init(url: self.documentURL)
                if (docuemt?.isLocked)! && self.password != nil {
                    docuemt?.unlock(withPassword: self.password)
                }
                
                var option = 60
                if self.selectIndex == 0 {
                    option = 120
                } else if self.selectIndex == 1 {
                    option = 90
                } else if self.selectIndex == 2 {
                    option = 60
                } else if self.selectIndex == 3 {
                    option = 30
                }
                
                let result = docuemt?.writeOptimize(to: url, withOptions: [.imageQualityOption : option])
                
                self.endLoading()
                guard let callback = self.resultCallback else {
                    if result! {
                        if isOpen { /// 开启文档
                            if !url!.path.isPDFValid() {
                                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
                            }
                            NSDocumentController.shared.openDocument(withContentsOf: url!, display: true) { document, alreadyOpen, error in
                                
                            }
                        } else {
                            NSWorkspace.shared.activateFileViewerSelecting([url!])
                        }
                    }
                    return
                }
                
                callback(result!, isOpen, url!, "")
            }
        }
    }
    
    func getUniqueFilePath(filePath: String) -> String {
        var i: Int = 0
        var isDirectory: ObjCBool = false
        var uniqueFilePath = filePath
        let fileManager = FileManager.default
        fileManager.fileExists(atPath: uniqueFilePath, isDirectory: &isDirectory)
        if isDirectory.boolValue {
            var path: String = ""
            while fileManager.fileExists(atPath: uniqueFilePath) {
                i += 1
                
                path = filePath
                path.append("(\(i))")
                uniqueFilePath = path
            }
        } else {
            let fileURL = URL(fileURLWithPath: filePath)
            var path: String = ""
            while fileManager.fileExists(atPath: uniqueFilePath) {
                i += 1
                
                path = fileURL.deletingPathExtension().path
                path.append("(\(i))")
                path.append(".")
                path.append(fileURL.pathExtension)
                uniqueFilePath = path
            }
        }
        return uniqueFilePath
    }
    
}

extension KMCompressWindowController: NSTableViewDataSource {
    func numberOfRows(in tableView: NSTableView) -> Int {
         datas.count
    }
    
}

extension KMCompressWindowController: KMLoadingProtocol {
    func beginLoading() {
        self.window?.contentView?.beginLoading()
    }
    
    func endLoading() {
        self.window?.contentView?.endLoading()
    }
}