//
//  SplitWindowController.swift
//  PDF Reader Pro
//
//  Created by tangchao on 2023/11/14.
//

import Cocoa

class SplitWindowController: KMBaseWindowController {
    /*
     @protocol SplitDelegate <NSObject>
     @optional
     - (void)didFinshedSplitWithURL:(NSURL*)url;
     @end

     @property (nonatomic,assign) id<SplitDelegate> splitDelegate;
     */
    
    var fileAttribute: KMFileAttribute?
     
    //转圈提示
    @IBOutlet var progress: NSProgressIndicator!
    //分割后文档存储所在文件夹名称TextField容器View
    @IBOutlet var nameView: NSView!
    //分割后文档存储所在文件夹名称 TextField
    @IBOutlet var partFileNameLabel: NSTextField!
    @IBOutlet var originalFileButton: NSButton!
    //分割提示 Label
    @IBOutlet var splitLabel: NSTextField!
    @IBOutlet var splitMethodBox: NSBox!
    @IBOutlet var fileNameBox: NSBox!
    @IBOutlet var exampleLabel: NSTextField!
    //平均页数分割单位Pages Label
    @IBOutlet var pagesLabel: NSTextField!
    //平均分割为多少个PDF文件单位 Label
    @IBOutlet var filesLabel: NSTextField!
    //导出目录提示 Label
    @IBOutlet var labelingLabel: NSTextField!
    //按页分割页数输入 TextField
    @IBOutlet var byPageText: NSTextField!
    //按文档数量均分文档个数输入 TextField
    @IBOutlet var byFileText: NSTextField!
    //文档名称分割符输入 TextField
    @IBOutlet var separatorText: NSTextField!
    //新增文档命名拼接字段输入 TextField
    @IBOutlet var renameText: NSTextField!
    //按页分割 Button
    @IBOutlet var byPageButton: NSButton!
    //按分割文档个数分割 Button
    @IBOutlet var byFileButton: NSButton!
    //手动输入页分割 Button
    @IBOutlet var pageFromButton: NSButton!
    //取消 Button
    @IBOutlet var cancelButton: NSButton!
    //分割 Button
    @IBOutlet var splitButton: NSButton!
    //按文档个数分割,文档个数步进器
    @IBOutlet var byFileStepper: NSStepper!
    //按页均分分割,单个文档页数步进器
    @IBOutlet var byPageStepper: NSStepper!
    //新增文件夹名称拼接输入选择 Button
    @IBOutlet var renameButton: NSButton!
    //新增文件夹名字拼接 Button
    @IBOutlet var separatorButton: NSButton!
    //页面选择 ComboBox
    @IBOutlet var pageRangeComboBox: NSComboBox!
    @IBOutlet var splitMethodLabel: NSTextField!
    @IBOutlet var fileNameLabel: NSTextField!
    
    private var _fileURL: URL?
    private var _PDFDocument: CPDFDocument?
    
    private var _isSuccessfully = false

    //密码
    var password: String?
    //分割样式
    private var _splitType: Int = 0
    
    convenience init(document: CPDFDocument) {
        self.init(windowNibName: "SplitWindowController")
        
        self.fileAttribute = KMFileAttribute()
        self._fileURL = document.documentURL
        self._PDFDocument = document
        self.fileAttribute?.pdfDocument = document
        if IAPProductsManager.default().isAvailableAllFunction() {
            self._splitType = 3
        }
    }
    
    convenience init(fileURL documentPath: URL) {
        self.init(windowNibName: "SplitWindowController")
        
        self.fileAttribute = KMFileAttribute()
        self._fileURL = documentPath
        self._PDFDocument = CPDFDocument(url: documentPath)
    }
    
    override func windowDidLoad() {
        super.windowDidLoad()
    
        self._localizedLanguage()
        self._setInputRange()
        self._configuViews()
    }
    
    override func interfaceThemeDidChanged(_ appearance: NSAppearance.Name) {
//        KMPrint("appearance")
    }
    
    @IBAction func byPageStepperAction(_ sender: AnyObject) {
        self.byPageText.stringValue = String(format: "%ld", self.byPageStepper.integerValue)
    }
    
    @IBAction func byFileStepperAction(_ sender: AnyObject) {
        self.byFileText.stringValue = String(format: "%ld", self.byFileStepper.integerValue)
    }
    
    @IBAction func buttonItemClicked_Cancel(_ sender: AnyObject) {
        self.km_quick_endSheet()
    }
     
    @IBAction func buttonItemClicked_ByPage(_ sender: AnyObject) {
        self.byFileButton.state = .off
        self.pageFromButton.state = .off
        self.byPageText.isEditable = true

        self.pageRangeComboBox.isEditable = false
        self.pageRangeComboBox.isEditable = false
        
        self.window?.makeFirstResponder(self)
        
        self.pageRangeComboBox.isEnabled = false
        
        self.byFileText.isEditable = false
        self.byFileStepper.isEnabled = false
        self.byPageStepper.isEnabled = true
        self.fileAttribute?.bAllPage = true
    }
    
    @IBAction func buttonItemClicked_ByFile(_ sender: AnyObject) {
        self.byPageButton.state = .off
        self.pageFromButton.state = .off
        self.byPageText.isEditable = false
        
        self.pageRangeComboBox.isEditable = false
        self.pageRangeComboBox.isSelectable = false
        self.window?.makeFirstResponder(self)
        self.pageRangeComboBox.isEnabled = false
        
        self.byFileText.isEditable = true
        self.byFileStepper.isEnabled = true
        self.byPageStepper.isEnabled = false
        self.fileAttribute?.bAllPage = true
    }
    
    @IBAction func buttonItemClicked_ByRange(_ sender: AnyObject) {
        if !IAPProductsManager.default().isAvailableAllFunction() {
            pageFromButton.state = .off
            KMPurchaseCompareWindowController.sharedInstance().showWindow(nil)
            return;
        }

        self.byFileButton.state = .off
        self.byPageButton.state = .off
        self.byPageText.isEditable = false
        self.pageRangeComboBox.isEnabled = true
        
        if (self.pageRangeComboBox.indexOfSelectedItem == 2) {
            self.pageRangeComboBox.isSelectable = true
            self.pageRangeComboBox.isEditable = true
            self.pageRangeComboBox.stringValue = ""
            self.window?.makeFirstResponder(self.pageRangeComboBox)
        }
        self.byFileText.isEditable = false
        self.byFileStepper.isEnabled = false
        self.byPageStepper.isEnabled = false
        self.fileAttribute?.bAllPage = false
    }
    
    @IBAction func buttonItemClicked_Split(_ sender: AnyObject) {
        var fileAttribute: KMFileAttribute?
        if (self.pageFromButton.state == .on) {
            //选择page
            fileAttribute = self.fileAttribute
            fileAttribute?.filePath = self._fileURL?.path ?? ""
            fileAttribute?.bAllPage = false
            
            let pageCnt = self._PDFDocument?.pageCount ?? 0
            if self.pageRangeComboBox.stringValue == KMLocalizedString("Odd Pages Only", nil) {
                var tPagesString = ""
                for i in 0 ..< pageCnt {
                    if (i%2 == 0) {
                        if (tPagesString.isEmpty) {
                            tPagesString.append("\(i+1)")
                        }else{
                            tPagesString.append(",\(i+1)")
                        }
                    }
                }
                fileAttribute?.pagesString = tPagesString
                fileAttribute?.pagesType = .odd
            } else if self.pageRangeComboBox.stringValue == KMLocalizedString("Even Pages Only", nil) {
                var tPagesString = ""
                for i in 0 ..< pageCnt {
                    if (i%2 == 1) {
                        if (tPagesString.isEmpty) {
                            tPagesString.append("\(i+1)")
                        }else{
                            tPagesString.append(",\(i+1)")
                        }
                    }
                }
                fileAttribute?.pagesString = tPagesString
                fileAttribute?.pagesType = .even
            } else {
                fileAttribute?.pagesString = self.pageRangeComboBox.stringValue
                fileAttribute?.pagesType = .custom
            }
            if let data = fileAttribute?.fetchSelectPages().isEmpty, data {
                KMAlertTool.runModelForMainThread(message: KMLocalizedString("Invalid page range or the page number is out of range. Please try again.", nil))
                return
            }
        }
        
        let panel = NSOpenPanel()
        panel.canChooseFiles = false
        panel.canChooseDirectories = true
        panel.canCreateDirectories = true
        panel.beginSheetModal(for: self.window!) { result in
            if (result == .OK) {
                let outputURL = panel.urls.first
                var tFolderPath = outputURL!.path
                
                var index = 0
                let folderName = self.partFileNameLabel.stringValue.deletingPathExtension.lastPathComponent
                var folderPath = "\(tFolderPath)" + "/" + "\(folderName)"
                //创建目录
                while FileManager.default.fileExists(atPath: folderPath) {
                    index += 1
                    folderPath = "\(tFolderPath)" + "/" + "\(folderName)_\(index)"
                }
                tFolderPath = folderPath
                try?FileManager.default.createDirectory(atPath: tFolderPath, withIntermediateDirectories: true)
                
                self.progress.isHidden = false
                self.cancelButton.isEnabled = false
                self.splitButton.isEnabled = false
                self.progress.startAnimation(nil)
                
                if (self.byPageButton.state == .on) {
                    let index = self.byPageStepper.integerValue;
                    DispatchQueue.global().async {
                        let successArray = self._PDFDocument?.splitByPagesWith(index, folerPath: tFolderPath, fileName: folderName) ?? []
                        DispatchQueue.main.async {
                            self.progress.isHidden = true
                            self.cancelButton.isEnabled = true
                            self.splitButton.isEnabled = true
                            
                            if (successArray.isEmpty == false) {
                                let response = KMAlertTool.runModelForMainThread_r(message: KMLocalizedString("Splitting completed. Tap 'OK' to open the output folder.", nil), buttons: [KMLocalizedString("OK",nil)])
                                if (response == .alertFirstButtonReturn ) {
                                    self.km_quick_endSheet()
                                    DispatchQueue.main.asyncAfter(deadline: .now()+0.5) {
                                        let filePath = successArray.first ?? ""
                                        self._viewFileAtFinder(filePath)
                                    }
                                }
                            } else {
                                let response = KMAlertTool.runModelForMainThread_r(message: KMLocalizedString("Failed to split!", nil))
                                if (response == .alertFirstButtonReturn) {
                                    self.km_quick_endSheet()
                                }
                            }
                        }
                    }
                } else if (self.byFileButton.state == .on) {
                    let dex = self.byFileStepper.integerValue
                    DispatchQueue.global().async {
//                        let successArray = self._PDFDocument?.splitByPagesWith(dex, folerPath: tFolderPath, fileName: folderName)
                        let successArray = self._PDFDocument?.splitByFileWith(dex, folerPath: tFolderPath, fileName: folderName) ?? []
                        DispatchQueue.main.async {
                            self.progress.isHidden = true
                            self.cancelButton.isEnabled = true
                            self.splitButton.isEnabled = true
                            
                            if (successArray.isEmpty == false) {
                                let response = KMAlertTool.runModelForMainThread_r(message: KMLocalizedString("Splitting completed. Tap 'OK' to open the output folder.", nil), buttons: [KMLocalizedString("OK",nil)])
                                if (response == .alertFirstButtonReturn) {
                                    self.km_quick_endSheet()
                                    DispatchQueue.main.asyncAfter(deadline: .now()+0.5) {
                                        let filePath = successArray.first ?? ""
                                        self._viewFileAtFinder(filePath)
                                    }
                                }
                            }else{
                                let response = KMAlertTool.runModelForMainThread_r(message: KMLocalizedString("Failed to split!", nil))
                                if (response == .alertFirstButtonReturn) {
                                    self.km_quick_endSheet()
                                }
                            }
                        }
                    }
                } else {
                    DispatchQueue.global().async { [self] in
                        var pdfDocument1 = CPDFDocument()
                        var pdfDocument2 = CPDFDocument()
                        let pageCnt = self._PDFDocument?.pageCount ?? 0
                        let pages = fileAttribute?.fetchSelectPages() ?? []
                        for i in 0 ..< pageCnt {
                            var isSelected = false
                            for number in pages {
                                if number == i+1 {
                                    isSelected = true
//                                    let page = self._PDFDocument?.page(at: i).copy()
                                    if let page = self._PDFDocument?.page(at: i) as? CPDFPage {
                                        pdfDocument1?.insertPageObject(page, at: pdfDocument1!.pageCount)
                                    }
                                }
                            }
                            if (!isSelected) {
//                                let page = self._PDFDocument?.page(at: i).copy()
                                if let page = self._PDFDocument?.page(at: i) as? CPDFPage {
                                    pdfDocument2?.insertPageObject(page, at: pdfDocument2!.pageCount)
                                }
                            }
                        }
                        if (pdfDocument1!.pageCount > 0) {
                            let tpath = "\(tFolderPath)/\(folderName) 1.pdf"
                            _isSuccessfully = pdfDocument1?.write(toFile:tpath) ?? false
                        }
                        if (pdfDocument2!.pageCount > 0) {
                            let tPath = "\(tFolderPath)/\(folderName) 2.pdf"
                            pdfDocument2?.write(toFile: tPath)
                        }
                        DispatchQueue.main.async {
                            self.progress.isHidden = true
                            self.cancelButton.isEnabled = true
                            self.splitButton.isEnabled = true
                            
                            if (_isSuccessfully) {
//                                if ([_splitDelegate respondsToSelector:@selector(didFinshedSplitWithURL:)]) {
//                                    [_splitDelegate didFinshedSplitWithURL:_fileURL];
//                                }
                                let response = KMAlertTool.runModelForMainThread_r(message: KMLocalizedString("Splitting completed. Tap 'OK' to open the output folder.", nil), buttons: [KMLocalizedString("OK",nil)])
                                if (response == .alertFirstButtonReturn) {
                                    self.km_quick_endSheet()
                                    DispatchQueue.main.asyncAfter(deadline: .now()+0.5) {
                                        let filePath = "\(tFolderPath)/\(folderName) 1.pdf"
                                        self._viewFileAtFinder(filePath)
                                    }
                                }
                            }else{
                                let response = KMAlertTool.runModelForMainThread_r(message: KMLocalizedString("Failed to split!", nil))
                                if (response == .alertFirstButtonReturn) {
                                    self.km_quick_endSheet()
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    @IBAction func buttonItemClicked_OriginalName(_ sender: AnyObject) {
        self._updateSplitFileName()
    }
    
    @IBAction func buttonItemClicked_Rename(_ sender: AnyObject) {
        self._updateSplitFileName()
    }
    
    @IBAction func comboBoxClicked_PageRange(_ sender: NSComboBox) {
        if (sender.indexOfSelectedItem == 0) {
            //奇数页
            sender.isEditable = false
            sender.isSelectable = false
            self.window?.makeFirstResponder(self)
        } else if (sender.indexOfSelectedItem == 1){
            //偶数页
            sender.isEditable = false
            sender.isSelectable = false
            self.window?.makeFirstResponder(self)
        } else {
            //手动输入页数
            sender.isEditable = true
            sender.isSelectable = true
            self.pageRangeComboBox.stringValue = self.pageRangeComboBox.stringValue
            (sender.cell as? NSComboBoxCell)?.placeholderString = KMLocalizedString("e.g. 1,3-5,10", nil)
            self.window?.makeFirstResponder(sender)
        }
    }
}

// MARK: - Private Methods

extension SplitWindowController {
    private func _localizedLanguage() {
        self.splitMethodLabel.stringValue = KMLocalizedString("Split Methods", nil)
//        self.splitLabel.stringValue = KMLocalizedString("Split Methods", nil)
        self.pagesLabel.stringValue = KMLocalizedString("page(s)", nil)
        self.filesLabel.stringValue = KMLocalizedString("PDF file(s)", nil)
//        self.labelingLabel.stringValue = KMLocalizedString("File Naming", nil)
        self.fileNameLabel.stringValue = KMLocalizedString("File Naming", nil)
        self.exampleLabel.stringValue = KMLocalizedString("example", nil)
        
        self.byPageButton.title = KMLocalizedString("Split by every", nil)
        self.byFileButton.title = KMLocalizedString("Split averagely to", nil)
        self.pageFromButton.title = KMLocalizedString("Split by page range", nil)
        self.cancelButton.title = KMLocalizedString("Cancel", nil)
        self.splitButton.title = KMLocalizedString("Split", nil)
        self.originalFileButton.title = KMLocalizedString("Keep the current file name in front of labels", nil)
        self.renameButton.title = KMLocalizedString("Label", nil)
        self.separatorButton.title = KMLocalizedString("Separator", nil)
        
        self.byPageButton.toolTip = KMLocalizedString("Split by every", nil)
        self.byFileButton.toolTip = KMLocalizedString("Split averagely to", nil)
        self.pageFromButton.toolTip = KMLocalizedString("Split by page range", nil)
        self.originalFileButton.toolTip = KMLocalizedString("Keep the current file name in front of labels", nil)
    }
    
    private func _setInputRange() {
        if let data = self._PDFDocument?.isLocked, data {
            if let url = self._fileURL {
                Self.checkPassword(url: url, type: .owner) { [weak self] success, pwd in
                    if success {
                        self?.password = pwd
                        self?._PDFDocument?.unlock(withPassword: pwd)
                        let pageNumber = self?._PDFDocument?.pageCount ?? 0
                        let pdfName = self?._PDFDocument?.documentURL.deletingPathExtension().lastPathComponent ?? ""
                        self?.byFileStepper.maxValue = Double(pageNumber)
                        self?.byPageStepper.maxValue = Double(pageNumber)
                        
                        self?.partFileNameLabel.stringValue = String(format: "%@%@%@.pdf", pdfName, self?.separatorText.stringValue ?? "", self?.renameText.stringValue ?? "")
                    }
                }
            }
        } else {
            let pageNumber = self._PDFDocument?.pageCount ?? 0
            let pdfName = self._PDFDocument?.documentURL.deletingPathExtension().path.lastPathComponent ?? ""
            self.byFileStepper.maxValue = Double(pageNumber)
            self.byPageStepper.maxValue = Double(pageNumber)
            
            if let data = self._PDFDocument?.documentURL.path.isEmpty, data == false {
                self.partFileNameLabel.stringValue = String(format: "%@%@%@", pdfName, self.separatorText.stringValue, "\(self.renameText.stringValue).pdf")
            } else {
                self.partFileNameLabel.stringValue = String(format: "%@%@%@", "Untitled", self.separatorText.stringValue, "\(self.renameText.stringValue).pdf")
            }
        }
    }
    
    private func _configuViews() {
        self.nameView.wantsLayer = true
    //    _nameView.layer.backgroundColor = [KMAppearance KMColor_Layout_L1].CGColor;

        //初始化ComboBox
        self.pageRangeComboBox.removeAllItems()
        
        let pageRangeArray = [KMLocalizedString("Odd Pages Only", nil),
                                    KMLocalizedString("Even Pages Only", nil),
                                    KMLocalizedString("e.g. 1,3-5,10", nil)]
        (self.pageRangeComboBox.cell as? NSComboBoxCell)?.placeholderString = KMLocalizedString("e.g. 1,3-5,10", nil)
        self.pageRangeComboBox.addItems(withObjectValues: pageRangeArray)
        self.pageRangeComboBox.selectItem(at: 0)
        self.pageRangeComboBox.isSelectable = false
        self.pageRangeComboBox.isEditable = false
        
        self.byFileText.isEditable = false
        self.byFileStepper.isEnabled = false
        self.byPageText.isEditable = false
        self.byPageStepper.isEnabled = true
        
        if (self._splitType == 3) {
            self.pageRangeComboBox.selectItem(at: 2)
            let isEmpty = self.fileAttribute?.pagesString.isEmpty ?? false
            if (isEmpty == false) {
                self.pageRangeComboBox.stringValue = self.fileAttribute?.pagesString ?? ""
                
                self.byPageButton.state = .off
                self.pageFromButton.state = .on
                self.pageRangeComboBox.isEnabled = true
            } else {
                self.pageRangeComboBox.stringValue = ""
                
                self.byPageButton.state = .on
                self.byPageText.isEditable = true
                self.pageFromButton.state = .off
                self.pageRangeComboBox.isEnabled = false
            }
            self.pageRangeComboBox.isEditable = true
            self.pageRangeComboBox.isSelectable = true
        } else {
            self.pageRangeComboBox.stringValue = ""
            self.pageRangeComboBox.isEnabled = false
            self.byPageText.isEditable = true
        }
        
        self.byPageStepper.minValue = 1.0
        self.byFileStepper.minValue = 1.0
        
        self.byPageStepper.integerValue = 1
        self.byFileStepper.integerValue = 1
        
        self.renameText.stringValue = "part"
        self.separatorText.stringValue = "-"
        self.byPageText.stringValue = "1"
        self.byFileText.stringValue = "1"
        
        self.byPageText.formatter = TextFieldFormatter()
        self.byFileText.formatter = TextFieldFormatter()
        
        self.byPageText.delegate = self
        self.byFileText.delegate = self
        self.renameText.delegate = self
        self.separatorText.delegate = self
        
        self.progress.isHidden = true
    }
    
    private func _viewFileAtFinder(_ filePath: String) {
        let workspace = NSWorkspace.shared
        let url = URL(fileURLWithPath: filePath)
        workspace.activateFileViewerSelecting([url])
    }
    
    private func _updateSplitFileName() {
        let pdfName = self._PDFDocument?.documentURL.deletingPathExtension().path.lastPathComponent ?? ""
        var splitPartString = ""
        var separatorString = ""
        
        if (self.renameButton.state == .on) {
            splitPartString = self.renameText.stringValue
        }
        if (self.separatorButton.state == .on) {
            separatorString =  self.separatorText.stringValue
        }
        var partName = ""
        if (self.originalFileButton.state == .on) {
            if (separatorString.isEmpty == false) {
                if (partName.isEmpty == false) {
                    partName.append(separatorString)
                } else {
                    partName = separatorString
                }
            }
            if (splitPartString.isEmpty == false) {
                if (partName.isEmpty == false) {
                    partName.append(splitPartString)
                } else {
                    partName = splitPartString
                }
            }
            self.partFileNameLabel.stringValue = String(format: "%@%@.pdf", pdfName, partName)
        } else {
            if (splitPartString.isEmpty == false) {
                if (partName.isEmpty == false) {
                    partName.append(splitPartString)
                } else {
                    partName = splitPartString
                }
            }
            if (separatorString.isEmpty == false) {
                if (partName.isEmpty == false) {
                    partName.append(separatorString)
                } else {
                    partName = separatorString
                }
            }
            self.partFileNameLabel.stringValue = String(format: "%@%@.pdf", partName, pdfName)
        }
    }
}

extension SplitWindowController: NSTextFieldDelegate {
    func controlTextDidChange(_ obj: Notification) {
        let textField = obj.object as? NSTextField
        if (self.byPageText.isEqual(to: textField)) {
            if let data = textField?.stringValue.isEmpty, data {
                self.byPageText.stringValue = "1"
                self.byPageStepper.integerValue = 1
            }else if let data = Int(textField!.stringValue), data <= 0 {
                self.byPageText.stringValue = "1"
                self.byPageStepper.integerValue = 1
            } else if (textField!.stringValue.stringToCGFloat() > self.byPageStepper.maxValue){
                self.byPageText.stringValue = String(format: "%.0f", self.byPageStepper.maxValue)
                self.byPageStepper.integerValue = Int(self.byPageStepper.maxValue)
            } else {
                self.byPageStepper.integerValue = Int(self.byPageText.stringValue) ?? 0
            }
        } else if (self.byFileText.isEqual(to: textField)){
            if let data = textField?.stringValue.isEmpty, data {
                self.byFileText.stringValue = "1"
                self.byFileStepper.integerValue = 1
            } else if let data = Int(textField!.stringValue), data <= 0 {
                self.byFileText.stringValue = "1"
                self.byFileStepper.integerValue = 1
            }else if (textField!.stringValue.stringToCGFloat() > self.byFileStepper.maxValue){
                self.byFileText.stringValue = String(format: "%.0f", self.byFileStepper.maxValue)
                self.byFileStepper.integerValue = Int(self.byFileStepper.maxValue)
            }else{
                self.byFileStepper.integerValue = Int(self.byFileText.stringValue) ?? 0
            }
        } else if (self.renameText.isEqual(to: textField) || self.separatorText.isEqual(to: textField )) {
            self._updateSplitFileName()
        }
    }
}