//
//  KMBatchOperateAddHeaderFooterViewController.swift
//  PDF Reader Pro
//
//  Created by liujiajie on 2023/11/7.
//

import Cocoa

class KMBatchOperateAddHeaderFooterViewController: KMBatchOperateBaseViewController, NSTableViewDelegate,NSTableViewDataSource{
    var isBates = false
    var onlyManagerTemplate = false
    var isBatchOperation = false
    var pdfView: CPDFView?
    
    @IBOutlet var topBaseView: NSView!
    @IBOutlet var bottomBaseView: NSView!
    @IBOutlet var tableView: NSTableView!
    @IBOutlet var titleLabel: NSTextField!
    @IBOutlet var actionButton: NSButton!
    @IBOutlet var managerTemplateTitleLabel: NSTextField!
    @IBOutlet var addButton: NSButton!
    @IBOutlet var blankView: KMBlankView!
    
    @IBOutlet var managerTemplateTopConstraint: NSLayoutConstraint!
    
    @IBOutlet var managerTemplateButtonHeightConstraint: NSButton!
    @IBOutlet var topHeightConstraint: NSLayoutConstraint!
    
    @IBOutlet var lineView: NSView!
    var haveFiles = false
    var currentObject: KMHeaderFooterObject?
    
    override var interfaceStatus: KMBatchOperateInterfaceStatus?{
        set{
            super.interfaceStatus = newValue
            if newValue == .PrepareProcess {
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
                    let 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 = KMLocalizedString("Apply", nil)
                self.actionButton.setTitleColor(KMAppearance.Layout.w0Color())
            } else {
                self.actionButton.tag = 0
                self.actionButton.title = KMLocalizedString("Cancel", nil)
                self.actionButton.setTitleColor(KMAppearance.Layout.w0Color())
            }
        }
        get{
            return super.interfaceStatus
        }
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        localizedLanguage()
        configuInterface()
        NotificationCenter.default.addObserver(self, selector: #selector(headerFootersNotification(notification:)), name: Notification.Name(rawValue: "KMBatchOperateHeaderFootersNotification"), object: nil)
//        NotificationCenter.default.addObserver(self, selector: #selector(themeChanged(notification:)), name: Notification.Name(rawValue: "AppleInterfaceThemeChangedNotification"), object: nil)
        DistributedNotificationCenter.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.addButton.title = "  " + KMLocalizedString("Add Template", nil)
        self.actionButton.title = KMLocalizedString("Apply", nil)
        self.titleLabel.stringValue = KMLocalizedString("Apply", nil)
    }
    func configuInterface() {
        self.titleLabel.font = NSFont.systemFont(ofSize: 14)
        self.titleLabel.textColor = KMAppearance.Layout.h0Color()
        self.tableView.enclosingScrollView?.borderType = .noBorder
        self.actionButton.wantsLayer = true
        self.addButton.wantsLayer = true
        
        self.topHeightConstraint.constant = 0
        var color = NSColor(red: 227.0/255.0, green: 228.0/255.0, blue: 230.0/255.0, alpha: 1)
        if KMAppearance.isSupportNewColor() {
            if KMAppearance.isDarkMode() {
                color = NSColor(red: 59.0/255.0, green: 61/255.0, blue: 64.0/255.0, alpha: 1)
            }
        }
        self.lineView.wantsLayer = true
        self.lineView.layer?.backgroundColor = color.cgColor
        self.addButton.imagePosition = .imageLeft
        self.addButton.image = NSImage(named: "KMImageNameHeaderFooterAddBtn")
        self.addButton.layer?.backgroundColor = KMAppearance.Interactive.s0Color().cgColor
        self.addButton.setTitleColor(KMAppearance.Layout.h0Color())
        if (onlyManagerTemplate){
            managerTemplateTitleLabel.isHidden = false
            titleLabel.isHidden = true
            self.topBaseView.isHidden = false
            topHeightConstraint.constant = 40
        }else{
            managerTemplateTitleLabel.isHidden = true
            titleLabel.isHidden = true
            self.topBaseView.isHidden = true
            topHeightConstraint.constant = 0
        }
        
        self.actionButton.layer?.backgroundColor = KMAppearance.Interactive.m0Color().cgColor
        self.actionButton.setTitleColor(KMAppearance.Layout.w0Color())
        self.actionButton.imagePosition = .noImage
        if !self.onlyManagerTemplate {
            if self.files?.count ?? 0 > 0 {
                self.haveFiles = true
            } else {
                self.haveFiles = false
            }
        } else {
            self.haveFiles = true
        }
        updateViewColor()
        updateActionButtonbackgroundColor()
        
        self.addButton.layer?.cornerRadius = 1.0
        self.actionButton.layer?.cornerRadius = 1.0
        
        self.topBaseView.wantsLayer = true
        self.topBaseView.layer?.backgroundColor = KMAppearance.Layout.l0Color().cgColor
        self.bottomBaseView.wantsLayer = true
        self.bottomBaseView.layer?.backgroundColor = KMAppearance.Layout.l0Color().cgColor
        self.managerTemplateTitleLabel.font = NSFont.systemFont(ofSize: 14)
        self.managerTemplateTitleLabel.textColor = KMAppearance.Layout.h0Color()
        
        self.addButton.isHidden = false
        
        self.managerTemplateTitleLabel.stringValue = NSLocalizedString("Manage Templates", comment: "")
        
        self.view.addSubview(self.blankView)
        self.blankView.mas_makeConstraints { make in
            make?.top.equalTo()(self.topBaseView.mas_bottom)
            make?.left.equalTo()(self.view)
            make?.right.equalTo()(self.view)
            make?.bottom.equalTo()(self.bottomBaseView.mas_top)
            make?.height.greaterThanOrEqualTo()(200)
        }
        
        self.blankView.titleLabel.stringValue = KMLocalizedString("No Templates", nil)
        
        self.tableView.backgroundColor = KMAppearance.Layout.l0Color()
        
        let menu = NSMenu(title: "")
        if !self.isBatchOperation && !self.isBates {
            menu.addItem(withTitle: NSLocalizedString("Batch Add Header & Footer", comment: ""), action: #selector(buttonItemClick_addBatch(_:)), keyEquivalent: "")
        } else if !self.isBatchOperation && self.isBates {
            menu.addItem(withTitle: NSLocalizedString("Batch Add Bates Numbers", comment: ""), action: #selector(buttonItemClick_addBatch(_:)), keyEquivalent: "")
        }
        if !self.isBates {
            menu.addItem(withTitle: NSLocalizedString("Remove All Header & Footer Templates", comment: ""), action: #selector(buttonItemClick_CleanAll(_:)), keyEquivalent: "")
        } else {
            menu.addItem(withTitle: NSLocalizedString("Remove All Bates Numbers Templates", comment: ""), action: #selector(buttonItemClick_CleanAll(_:)), keyEquivalent: "")
        }
        self.view.menu = menu
        
    }
    func updateActionButtonbackgroundColor() {
        let row = self.tableView.selectedRow 
        if (self.files?.count ?? 0 > 0 || self.pdfView != nil) && row > -1 {
            self.actionButton.layer?.backgroundColor = KMAppearance.Interactive.m0Color().cgColor
            self.actionButton.setTitleColor(KMAppearance.Layout.w0Color())
        } else {
            self.actionButton.setTitleColor(KMAppearance.Layout.w0Color().withAlphaComponent(0.6))
            self.actionButton.layer?.backgroundColor = KMAppearance.Interactive.m0Color().withAlphaComponent(0.6).cgColor
        }
    }
    @objc func buttonItemClick_addBatch(_ sender: Any) {
        let baseWindowController = KMBatchOperateBaseWindowController(windowNibName: "KMBatchOperateBaseWindowController")
        if #available(macOS 10.13, *) {
            baseWindowController.window?.makeKeyAndOrderFront(nil)
        } else {
            baseWindowController.showWindow(nil)
        }
        let arr = NSMutableArray()
        let file = KMBatchOperateFile(filePath: self.pdfView!.document!.documentURL!.path, type: self.isBates ? .AddBates : .AddHeaderFooter)
        arr.add(file)
        baseWindowController.checkNeedPasswordSwitchToOperateType(operateType: self.isBates ? .AddBates : .AddHeaderFooter, files: arr as! [KMBatchOperateFile])
    }
    @objc func buttonItemClick_CleanAll(_ sender: Any) {
        let alert = NSAlert()
        alert.alertStyle = .warning
        alert.messageText = ""
        alert.informativeText = NSLocalizedString("Are you sure to delete all templates?", comment: "")
        alert.addButton(withTitle: NSLocalizedString("Delete", comment: ""))
        alert.addButton(withTitle: NSLocalizedString("Cancel", comment: ""))
        alert.beginSheetModal(for: NSApp.mainWindow!) { (response) in
            if response == .alertFirstButtonReturn {
                self.deleteAll()
            }
        }
    }
    @objc func headerFootersNotification(notification: Notification) {
        if let addHeaderFooter = notification.object as? KMBatchOperateAddHeaderFooterViewController {
            if self != addHeaderFooter {
                loadData()
            }
        }
    }
    @objc func themeChanged(notification: Notification) {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
            self.updateViewColor()
        }
    }
    @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
        }
        updateActionButtonbackgroundColor()
    }
    func loadData() {
        self.tableView.reloadData()
    }
    func updateViewColor() {
        if KMAppearance.isDarkMode() {
            self.bottomBaseView.layer?.backgroundColor = NSColor(red: 0.149, green: 0.157, blue: 0.169, alpha: 1).cgColor
            self.addButton.layer?.backgroundColor = NSColor(red: 0.337, green: 0.345, blue: 0.353, alpha: 1).cgColor
            self.addButton.setTitleColor(NSColor.white)
            self.actionButton.layer?.backgroundColor = NSColor(red: 0.306, green: 0.498, blue: 0.859, alpha: 1).cgColor
            self.actionButton.setTitleColor(KMAppearance.Layout.w0Color())
        } else {
            self.bottomBaseView.layer?.backgroundColor = NSColor(red: 0.988, green: 0.992, blue: 1.000, alpha: 1).cgColor
            self.addButton.layer?.backgroundColor = NSColor(red: 0.855, green: 0.859, blue: 0.871, alpha: 1).cgColor
            self.addButton.setTitleColor(NSColor(red: 0.055, green: 0.067, blue: 0.078, alpha: 1))
            self.actionButton.layer?.backgroundColor = NSColor(red: 0.153, green: 0.235, blue: 0.384, alpha: 1).cgColor
            self.actionButton.setTitleColor(KMAppearance.Layout.w0Color())
        }
    }
    func deleteAll() {
        if self.isBates {
            for waterMark in KMHeaderFooterManager.defaultManager.onlyBatesObjects {
                KMHeaderFooterManager.defaultManager.removeHeaderFooter(waterMark)
            }
        } else {
            for waterMark in KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects {
                KMHeaderFooterManager.defaultManager.removeHeaderFooter(waterMark)
            }
        }
        reloadTable()
        loadData()
        postNotification()
    }
    func reloadTable() {
        self.tableView.noteNumberOfRowsChanged()
        var count = 0
        var array: [KMHeaderFooterObject] = []
        if self.isBates {
            count = KMHeaderFooterManager.defaultManager.onlyBatesObjects.count
            array = KMHeaderFooterManager.defaultManager.onlyBatesObjects
        } else {
            count = KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects.count
            array = KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects
        }
        if array.contains(self.currentObject ?? KMHeaderFooterObject()) {
            let row = array.firstIndex(of: self.currentObject!)!
            let indexSet = IndexSet(integer: row)
            self.tableView.selectRowIndexes(indexSet, byExtendingSelection: false)
        }
        updateActionButtonbackgroundColor()
    }
    func postNotification() {
        NotificationCenter.default.post(name: NSNotification.Name("KMBatchOperateHeaderFootersNotification"), object: self)
    }
    
    @IBAction func buttonClicked_AddHeaderFooter(_ sender: Any) {
//        guard let windowController = self.view.window?.windowController else { return }
//        var filePath: String?
//        var password: String?
//        if let mainWC = windowController as? MainWindowController {
//            //            filePath = mainWC.pdfView?.document?.documentURL?.path
//            //            password = (mainWC.pdfView?.document as? CPDFDocument)?.password
//        }
//        let wc = KMHeaderFooterManagerWindowController(baseFile: filePath, headerFooter: nil, password: password, type: .KMBatchModifyTemplateType_Add)
//        wc.isBates = self.isBates
//        wc.operateCallBack = { [weak self] obj in
//            self?.currentObject = obj
//            self?.loadData()
//            self?.postNotification()
//            DispatchQueue.main.async {
//                guard let strongSelf = self else {
//                    return
//                }
//                strongSelf.tableView.selectRowIndexes(IndexSet(integer: 0), byExtendingSelection: false)
//            }
//        }
//        wc.beginSheetModal(for: NSApp.keyWindow!, completionHandler: nil)
        let filePath: String = Bundle.main.path(forResource: "Quick Start Guide", ofType: "pdf") ?? ""
        var cdocument = self.pdfView?.document
        if isBatchOperation {
            cdocument = CPDFDocument(url: URL(fileURLWithPath: filePath))
        }
        let windowController = KMHeaderFooterWindowController(windowNibName: "KMHeaderFooterWindowController")
        windowController.isBatch = isBatchOperation
        windowController.type = .Add
        windowController.isBates = isBates
        windowController.pdfDocument = cdocument
        
        windowController.cancelAction = { [weak self] controller in
            self?.km_endSheet()
        }
        windowController.operateCallBack = { [weak self] wController, model in
            self?.currentObject = model
            self?.loadData()
            self?.postNotification()
            let set = NSIndexSet(index: 0)
            self?.tableView.selectRowIndexes(set as IndexSet, byExtendingSelection: false)
        }
        self.km_beginSheet(windowC: windowController)
        
    }
    
    @IBAction func buttonClicked_Action(_ sender: NSButton) {
        if (!self.onlyManagerTemplate) {
            if (!self.haveFiles) {
                return
            }
        }
        if (self.onlyManagerTemplate) {
            if (sender.tag == 1) {
                var headFooter: KMHeaderFooterObject?
                let row = self.tableView.selectedRow
                if (row == -1) {
                    NSSound.beep()
                    return
                } else {
                    if (self.isBates) {
                        headFooter = KMHeaderFooterManager.defaultManager.onlyBatesObjects[row]
                    } else {
                        headFooter = KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects[row]
                    }
                }

                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.hiddenWindowCloseButtonIfNeeded()
                            self.successFilePathURLArray?.removeAll()
                            if (self.isBates) {
                                let file = KMBatchOperateFile(filePath: self.pdfView?.document.documentURL.path ?? "", type: .AddBates)
                                if file.fileType == .PDF {
                                    file.addBatesInfo.pageChoice = KMBatchOperatePageChoice(rawValue: headFooter?.pageRangeType.rawValue ?? 0) ?? .All
                                    file.addBatesInfo.pageRangeString = headFooter?.pageRangeString
                                    file.addBatesInfo.savePath = fileURL.path
                                    if file.status == .Waiting {
                                        let op = KMBatchAddHeaderFooterOperation(file: file, headerFooter: headFooter!)
                                        op.delegate = self
                                        self.queue?.addOperation(op)
                                    }
                                }
                            } else {
                                self.successFilePathURLArray?.removeAll()
                                let file = KMBatchOperateFile(filePath: self.pdfView?.document.documentURL.path ?? "", type: .AddHeaderFooter)
                                if file.fileType == .PDF {
                                    file.addHeaderFooterInfo.pageChoice = KMBatchOperatePageChoice(rawValue: headFooter?.pageRangeType.rawValue ?? 0) ?? .All
                                    file.addHeaderFooterInfo.pageRangeString = headFooter?.pageRangeString
                                    file.addHeaderFooterInfo.savePath = fileURL.path
                                    if file.status == .Waiting {
                                        let op = KMBatchAddHeaderFooterOperation(file: file, headerFooter: headFooter!)
                                        op.delegate = self
                                        self.queue?.addOperation(op)
                                    }
                                }
                            }
                            if self.queue?.operations.count ?? 0 > 0 {
                                self.interfaceStatus = .Processing
                            }
                        }
                    }
                }
            } else if (sender.tag == 0) {
                if let cnt = self.queue?.operations.count, cnt > 0 {
                    self.queue?.cancelAllOperations()
                }
                self.interfaceStatus = .PrepareProcess
            }
        } else {
            //点击开始
            if (sender.tag == 1) {
                if (!self.checkAndResetTask()) {
                    NSSound.beep()
                    return;
                }
                var headFooter: KMHeaderFooterObject?
                let row = self.tableView.selectedRow
                if (row == -1 || self.files?.count ?? 0 < 1) {
                    NSSound.beep()
                    return;
                } else {
                    if (self.isBates) {
                        headFooter = KMHeaderFooterManager.defaultManager.onlyBatesObjects[row]
                    } else {
                        headFooter = KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects[row]
                    }
                }
                
                self.choosePathAndBeginOperation(headFooter!)
            } else if (sender.tag == 0) {
                if let cnt = self.queue?.operations.count, cnt > 0 {
                    self.queue?.cancelAllOperations()
                }
                self.interfaceStatus = .PrepareProcess
            }
        }
        
    }
    func checkAndResetTask() -> Bool {
        if files?.count ?? 0 < 1 {
            return false
        }
        for i in 0..<(files?.count ?? 0) {
            if let file = files?[i] as? KMBatchOperateFile {
                if isBates {
                    file.addBatesInfo.resetState()
                } else {
                    file.addHeaderFooterInfo.resetState()
                }
            }
        }
        return true
    }
    func choosePathAndBeginOperation(_ obj: Any) {
        let openPanel = NSOpenPanel()
        openPanel.canChooseFiles = false
        openPanel.canChooseDirectories = true
        openPanel.canCreateDirectories = true
        openPanel.beginSheetModal(for: self.view.window!) { (result) in
            if result == NSApplication.ModalResponse.OK {
                for fileURL in openPanel.urls {
                    self.choosePath = fileURL.path
                    if self.isBates {
                        self.beginAddBates(obj as! KMHeaderFooterObject)
                    } else {
                        self.beginAddHeaderFooter(obj as! KMHeaderFooterObject)
                    }
                }
            }
        }
    }
    func beginAddBates(_ bates: KMHeaderFooterObject) {
        hiddenWindowCloseButtonIfNeeded()
        successFilePathURLArray?.removeAll()
        for i in 0..<(files?.count ?? 0) {
            if let file = files?[i] as? KMBatchOperateFile {
                if file.fileType == .PDF {
                    file.addBatesInfo.savePath = choosePath
                    if file.status == .Waiting {
                        let operation = KMBatchAddHeaderFooterOperation(file: file, headerFooter: bates)
                        operation.delegate = self
                        queue?.addOperation(operation)
                    }
                }
            }
        }
        if queue?.operationCount ?? 0 > 0 {
            interfaceStatus = .Processing
        }
    }
    func beginAddHeaderFooter(_ headerFooter: KMHeaderFooterObject) {
        hiddenWindowCloseButtonIfNeeded()
        successFilePathURLArray?.removeAll()
        for i in 0..<(files?.count ?? 0) {
            if let file = files?[i] as? KMBatchOperateFile {
                if file.fileType == .PDF {
                    file.addHeaderFooterInfo.savePath = choosePath
                    if file.status == .Waiting {
                        let operation = KMBatchAddHeaderFooterOperation(file: file, headerFooter: headerFooter)
                        operation.delegate = self
                        queue?.addOperation(operation)
                    }
                }
            }
        }
        if queue?.operationCount ?? 0 > 0 {
            interfaceStatus = .Processing
        }
    }
    func modify(obj: KMHeaderFooterObject) {
//        let windowController = self.view.window?.windowController
//        var filePath: String? = nil
//        var password: String? = nil
//        if let mainWindowController = windowController as? MainWindowController {
//            filePath = mainWindowController.mainViewController.listView?.document?.documentURL?.path
//            let document = mainWindowController.mainViewController.listView?.document as? CPDFDocument
//            password = document?.password
//        }
//        let wc = KMHeaderFooterManagerWindowController(baseFile: filePath, headerFooter: obj, password: password, type: .KMBatchModifyTemplateType_Edit)
//        wc?.isBates = self.isBates
//        let blockSelf = self
//        wc?.operateCallBack = { obj in
//            blockSelf.currentObject = obj
//            blockSelf.loadData()
//            blockSelf.reloadTable()
//            blockSelf.postNotification()
//        }
//        wc?.beginSheetModalForWindow(NSApp.keyWindow, completionHandler: nil)
        
        var filePath: String = Bundle.main.path(forResource: "Quick Start Guide", ofType: "pdf") ?? ""
        if self.pdfView?.document.documentURL.path.count ?? 0 > 0 {
            filePath = self.pdfView?.document.documentURL.path ?? ""
        }

        let cdocument = CPDFDocument(url: URL(fileURLWithPath: filePath))
        
        let windowController = KMHeaderFooterWindowController(windowNibName: "KMHeaderFooterWindowController")
        windowController.headerFooterObj = obj
        windowController.isBatch = isBatchOperation
        windowController.type = .Edit
        windowController.isBates = isBates
        windowController.pdfDocument = cdocument
        
        windowController.cancelAction = { [weak self] controller in
            self?.km_endSheet()
        }
        windowController.operateCallBack = { wController, model in
            self.currentObject = model
            self.loadData()
            self.postNotification()
            let set = NSIndexSet(index: 0)
            self.tableView.selectRowIndexes(set as IndexSet, byExtendingSelection: false)
        }
        self.km_beginSheet(windowC: windowController)
        
    }
    func delete(obj: KMHeaderFooterObject) {
        KMHeaderFooterManager.defaultManager.removeHeaderFooter(obj)
        loadData()
        reloadTable()
        postNotification()
    }
   
    func headerFooterInterfaceSelectHeaderFooter(headerFooter: KMHeaderFooterObject) {
        self.tableView.reloadData()
        if let index = KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects.firstIndex(of: headerFooter) {
            let indexSet = IndexSet(integer: index)
            self.tableView.selectRowIndexes(indexSet, byExtendingSelection: false)
        }
    }
    func batesInterfaceSelectBates(headerFooter: KMHeaderFooterObject) {
        self.tableView.reloadData()
        if let index = KMHeaderFooterManager.defaultManager.onlyBatesObjects.firstIndex(of: headerFooter) {
            let indexSet = IndexSet(integer: index)
            self.tableView.selectRowIndexes(indexSet, byExtendingSelection: false)
        }
    }
   
    func numberOfRows(in tableView: NSTableView) -> Int {
        var count = 0
        if self.isBates {
            count = KMHeaderFooterManager.defaultManager.onlyBatesObjects.count
        } else {
            count = KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects.count
        }
        self.blankView.isHidden = count != 0
        return count
    }
    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
        var obj: KMHeaderFooterObject? = nil
        if self.isBates {
            obj = KMHeaderFooterManager.defaultManager.onlyBatesObjects[row]
        } else {
            obj = KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects[row]
        }
        guard let cellView = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "mainCell"), owner: self) as? KMHeaderFooterTableCellView else {
            return nil
        }
        
        cellView.updateInterface(obj!)
        cellView.headerFooterTableCellViewCallback = { type in
            if type == .Edit {
                let indexSet = IndexSet(integer: row)
                self.tableView.selectRowIndexes(indexSet, byExtendingSelection: false)
                self.currentObject = obj
                self.modify(obj: obj!)
            } else {
                self.delete(obj: obj!)
            }
        }
        return cellView
    }
    func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
        let rowView = KMTableRowView() 
        return rowView
    }
    func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat { 
        if self.isBates {
            return KMHeaderFooterManager.defaultManager.onlyBatesObjects[row].cellHeight
        } else {
            return KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects[row].cellHeight
        }
    }
    func tableView(_ tableView: NSTableView, shouldSelect tableColumn: NSTableColumn?) -> Bool {
        return true
    }
    func tableView(_ tableView: NSTableView, shouldSelectRow row: Int) -> Bool {
        return true
    }
    func tableViewSelectionDidChange(_ notification: Notification) {
        let row = self.tableView.selectedRow
        updateActionButtonbackgroundColor()
        if row == -1 { return }
        if self.isBates {
            let bates = KMHeaderFooterManager.defaultManager.onlyBatesObjects[row]
            self.currentObject = bates
            for i in 0..<(self.files?.count ?? 0) {
                let file = self.files?[i]
                file?.addBatesInfo.pageChoice = KMBatchOperatePageChoice(rawValue: bates.pageRangeType.rawValue) ?? .All
                if file?.addBatesInfo.pageChoice == .Input {
                    let arr = allPageNumbers(bates.pageRangeString)
                    let sortedArray: NSArray = file!.pagesArrayIntersect(with: arr) as NSArray
                    if sortedArray.count < 1 {
                        file?.addBatesInfo.pageChoice = .All
                    } else {
                        file!.addBatesInfo.pageRangeString = sortedArray.componentsJoined(by: ",")
                    }
                }
            }
        } else {
            let headerFooter = KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects[row]
            self.currentObject = headerFooter
            for i in 0..<(self.files?.count ?? 0) {
                let file = self.files?[i]
                file?.addHeaderFooterInfo.pageChoice =  KMBatchOperatePageChoice(rawValue: headerFooter.pageRangeType.rawValue) ?? .All
                if file?.addHeaderFooterInfo.pageChoice == .Input {
                    let arr = allPageNumbers(headerFooter.pageRangeString)
                    let sortedArray: NSArray = file!.pagesArrayIntersect(with: arr) as NSArray
                    if sortedArray.count < 1 {
                        file?.addHeaderFooterInfo.pageChoice = .All
                    } else {
                        file!.addHeaderFooterInfo.pageRangeString = sortedArray.componentsJoined(by: ",")
                    }
                }
            }
        }
        reloadTable()
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: kNeedChangePageRangeNotification), object: nil)
    }
}

extension KMBatchOperateAddHeaderFooterViewController: NSMenuDelegate, NSMenuItemValidation{
    func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
        let action = menuItem.action
        if action == #selector(buttonItemClick_CleanAll(_:)) {
            if (self.isBates && KMHeaderFooterManager.defaultManager.onlyBatesObjects.count < 1) || (!self.isBates && KMHeaderFooterManager.defaultManager.onlyHeaderFooterObjects.count < 1){
                return false
            }
            return true
        }
        return true
    }
}