//
//  KMPDFCropWindowController.swift
//  PDF Reader Pro
//
//  Created by liujiajie on 2024/1/9.
//

import Foundation

@objc enum KMPDFCropType: Int {
    case CropBox = 0
    case ArtBox
    case TrimBox
    case BleedBox
}

typealias cropWindowCloseBlock = (_ doc: CPDFDocument) ->Void

class KMPDFCropWindowController: NSWindowController, CPDFViewDelegate, NSWindowDelegate, NSTextFieldDelegate, NSComboBoxDelegate{
    var previewDocument: CPDFDocument?
    var originalDocument: CPDFDocument?
    var password: String = ""
    var pagesString: String = ""
    var pageType: KMPDFSelectPageStringType = .AllPages
    var currentPage: Int = 0
    var cropRect: CGRect = CGRectZero
    var defaultCropRect: CGRect = CGRectZero
    var selectPages = NSMutableArray()
    var cropEdgeInsets: NSEdgeInsets = .init(top: 0, left: 0, bottom: 0, right: 0)
    var drawPageRect: CGRect = CGRectZero
    
    @IBOutlet var unitLabel: NSTextField!
    @IBOutlet var unitPopUpButton: NSPopUpButton!
    
    @IBOutlet var marginBox: NSBox!
    @IBOutlet var marginLabel: NSTextField!
    @IBOutlet var applyLabel: NSTextField!
    @IBOutlet var applyPopUpButton: NSPopUpButton!
    @IBOutlet var topLabel: NSTextField!
    @IBOutlet var bottomLabel: NSTextField!
    @IBOutlet var leftLabel: NSTextField!
    @IBOutlet var rightLabel: NSTextField!
    @IBOutlet var topDistanceText: NSTextField!
    @IBOutlet var bottomDistanceText: NSTextField!
    @IBOutlet var leftDistanceText: NSTextField!
    @IBOutlet var rightDistanceText: NSTextField!
    @IBOutlet var topStepper: NSStepper!
    @IBOutlet var bottomStepper: NSStepper!
    @IBOutlet var leftStepper: NSStepper!
    @IBOutlet var rightStepper: NSStepper!
    @IBOutlet var proportButton: NSButton!
    @IBOutlet var marginsButton: NSButton!
    @IBOutlet var zeroButton: NSButton!
    @IBOutlet var revertButton: NSButton!
    
    @IBOutlet var pageSizeBox: NSBox!
    @IBOutlet var pageSizeLabel: NSTextField!
    @IBOutlet var pageSizePopUpButton: NSPopUpButton!
    @IBOutlet var fixedSizeButton: NSButton!
    @IBOutlet var customButton: NSButton!
    @IBOutlet var centerButton: NSButton!
    @IBOutlet var widthLabel: NSTextField!
    @IBOutlet var heightLabel: NSTextField!
    @IBOutlet var xLabel: NSTextField!
    @IBOutlet var yLabel: NSTextField!
    @IBOutlet var widthText: NSTextField!
    @IBOutlet var heightText: NSTextField!
    @IBOutlet var xText: NSTextField!
    @IBOutlet var yText: NSTextField!
    
    @IBOutlet var pageRangeLabel: NSTextField!
    @IBOutlet var pageRangeComboBox: NSComboBox!
    
    @IBOutlet var cancelButton: NSButton!
    @IBOutlet var saveButton: NSButton!
    @IBOutlet var printButton: NSButton!
    
    @IBOutlet var previewPageButton: NSButton!
    @IBOutlet var nextPageButton: NSButton!
    @IBOutlet var currentPageIndexTextF: NSTextField!
    @IBOutlet var totalPageCountLabel: NSTextField!
    @IBOutlet var pdfView: KMCropPDFView!
    @IBOutlet var cropLabel: NSTextField!
    
    var fileAttribute: KMFileAttribute!
    
    var isChangePageSize = false
    var cropWindowCloseBlock: cropWindowCloseBlock?
    
    
    convenience init(document:CPDFDocument, pwd:String, currentPage:Int, cropSize:CGRect, selectPageString:String) {
        self.init(windowNibName: "KMPDFCropWindowController")
        self.currentPage = currentPage
        self.defaultCropRect = cropRect
        if selectPageString.count > 0 {
            self.pagesString = String(format: "%ld", (Int(selectPageString) ?? 0) + 1)
            self.pageType = .PagesString
            let nu: NSNumber = Int(selectPageString)! as NSNumber
            self.selectPages.add(nu)
        }else {
            self.pageType = .AllPages
        }
        self.password = pwd
        self.originalDocument = document
    }
    
    convenience init(documentPath: URL, selectPages: String){
        self.init(windowNibName: "KMPDFCropWindowController")
        if selectPages.count > 0 {
            self.pagesString = String(format: "%ld", (Int(selectPages) ?? 0) + 1)
            self.pageType = .PagesString
            let nu: NSNumber = Int(selectPages)! as NSNumber
            self.selectPages.add(nu)
        }else {
            self.pageType = .AllPages
        }
        self.originalDocument = CPDFDocument(url: documentPath)
    }
    
    override func windowDidLoad() {
        super.windowDidLoad()
        self.cropRect = self.defaultCropRect
        fileAttribute = KMFileAttribute()
        fileAttribute.filePath = self.originalDocument?.documentURL.path ?? ""
        self.pdfView.wantsLayer = true
        self.pdfView.layer?.borderColor = NSColor.black.cgColor
        self.pdfView.layer?.borderWidth = 2
        self.pdfView.backgroundColor = NSColor.white
        self.pdfView.autoScales = true
        self.pdfView.delegate = self
        
        self.localizedString()
        
        self.fixedSizeButton.state = .on
        self.customButton.state = .off
        self.centerButton.isEnabled = false
        self.xText.isEnabled = false
        self.yText.isEnabled = false
        self.widthText.isEnabled = false
        self.heightText.isEnabled = false
        self.centerButton.state = .on
        
        let numberFormatter = self.currentPageIndexTextF.formatter as! NumberFormatter
        numberFormatter.maximum = NSNumber(value: self.originalDocument?.pageCount ?? 0)
        self.totalPageCountLabel.stringValue = String(format: "%ld", self.originalDocument?.pageCount ?? 0)
        let currentPageIndex = self.pdfView.currentPageIndex//self.pdfView.document!.index(for: self.pdfView.currentPage()!)
        self.currentPageIndexTextF.stringValue = "\(currentPageIndex + 1)"
        self.updateSizeView()
        self.topStepper.minValue = 0
        self.leftStepper.minValue = 0
        self.rightStepper.minValue = 0
        self.bottomStepper.minValue = 0
        self.changePrePDFView()
        self.reloadPDFWithIndex()
        self.updateCropViewLabel()
        
        let tPage = self.previewDocument?.page(at: UInt(self.currentPage))
        self.pdfView.go(to: tPage)
    }
    
    func windowShouldClose(_ sender: NSWindow) -> Bool {
        close()
        return true
    }
    
    override func close() {
        if (self.cropWindowCloseBlock != nil) {
            cropWindowCloseBlock!(originalDocument!)
        }
        if ((self.window?.isSheet) != nil) {
//            self.window?.sheetParent?.endSheet(self.window!)
        } else {
            super.close()
        }
    }
    
    
    
    func updateCropViewLabel() {
        let unitScanl: CGFloat = self.unitConversion()
        var mat: String = NSLocalizedString("Cropped page size:", comment: "")
        if (0 == self.applyPopUpButton.indexOfSelectedItem) {
            mat = NSLocalizedString("Cropped page size:", comment: "")
        } else if (1 == self.applyPopUpButton.indexOfSelectedItem) {
            mat = NSLocalizedString("ArtBox size:", comment: "")
        } else if (2 == self.applyPopUpButton.indexOfSelectedItem) {
            mat = NSLocalizedString("TrimBox size:", comment: "")
        } else {
            mat = NSLocalizedString("BleedBox size:", comment: "")
        }
        if (0 == self.pageSizePopUpButton.indexOfSelectedItem && self.fixedSizeButton.state == .on) {
            if (.on == self.marginsButton.state) {
                let orgPage: CPDFPage = (self.originalDocument?.page(at: UInt(self.currentPage)))!
                let rect: NSRect = KMCropTools.getPageForegroundBox(orgPage)
                self.cropLabel.stringValue = String(format: "%@%@ * %@%@", mat, self.formatFloat(Float(rect.size.width/unitScanl)), self.formatFloat(Float(rect.size.height/unitScanl)), self.unitPopUpButton.title)
            } else {
                self.cropLabel.stringValue =  String(format: "%@%@ * %@%@", mat, self.formatFloat(Float(self.cropRect.size.width/unitScanl)), self.formatFloat(Float(self.cropRect.size.height/unitScanl)), self.unitPopUpButton.title)
            }
        } else {
            self.cropLabel.stringValue = String(format: "%@%@ * %@%@", KMLocalizedString("Expanded page size:", nil), self.formatFloat(Float(self.drawPageRect.size.width/unitScanl)), self.formatFloat(Float(self.drawPageRect.size.height/unitScanl)), self.unitPopUpButton.title)
        }
    }
    
    func formatFloat(_ f: Float) -> String {
        if f.truncatingRemainder(dividingBy: 1) == 0 { // If there is one decimal place
            return String(format: "%.0f", f)
        } else if (f * 10).truncatingRemainder(dividingBy: 1) == 0 { // If there are two decimal places
            return String(format: "%.1f", f)
        } else {
            return String(format: "%.2f", f)
        }
    }
    
    func handlerReDraw() {
        if drawPageRect.size.width < 0 || drawPageRect.size.height < 0 {
            NSSound.beep()
            return
        } else {
            for i in 0..<(originalDocument?.pageCount ?? 0) {
                if selectPages.contains(i) {
                    let page = KMCropPDFPage() 
                    page.setBounds(NSRect(x: 0, y: 0, width: drawPageRect.size.width, height: drawPageRect.size.height), for: .mediaBox)
                    let cropPage = originalDocument?.page(at: i)
                    page.cropDrawingPage = cropPage
                    originalDocument?.insertPageObject(page, at: i)
                    originalDocument?.removePage(at: i)
                }
            }
        }
    }
    
    func updateView() {
        let page = originalDocument?.page(at: UInt(currentPage))
        let pageBounds = page?.bounds(for: .mediaBox)
        let tCropRect = CGRect(x: cropEdgeInsets.left, y: cropEdgeInsets.bottom, width: (pageBounds?.width ?? 0) - cropEdgeInsets.left - cropEdgeInsets.right, height: (pageBounds?.height ?? 0) - cropEdgeInsets.top - cropEdgeInsets.bottom)
        cropRect = tCropRect
        changePrePDFView()
    }
    
    func unitConversion() -> CGFloat {
        var unitScanl: CGFloat = 1.0
        if (0 == self.unitPopUpButton.indexOfSelectedItem) {
            unitScanl = 595.0/21.0
        } else if (1 == self.unitPopUpButton.indexOfSelectedItem) {
            unitScanl = 595.0/210.0
        } else {
            unitScanl = (595.0/21.0) * 2.54
        }
        return unitScanl
    }
    
    func getDrawPages() {
        let pages = NSMutableArray()
        if 0 == self.pageRangeComboBox.indexOfSelectedItem {
            for i in 0..<(self.originalDocument?.pageCount ?? 0) {
                pages.add(i)
            }
        } else if 1 == self.pageRangeComboBox.indexOfSelectedItem {
            for i in 0..<(self.originalDocument?.pageCount ?? 0) {
                if i % 2 == 0 {
                    pages.add(i)
                }
            }
        } else if 2 == self.pageRangeComboBox.indexOfSelectedItem {
            for i in 0..<(self.originalDocument?.pageCount ?? 0) {
                if i % 2 != 0 {
                    pages.add(i)
                }
            }
        } else {
            fileAttribute.bAllPage = false
            fileAttribute.pagesType = .custom
            fileAttribute.pagesString = self.pageRangeComboBox.stringValue
            
            for num in fileAttribute.fetchSelectPages() {
                pages.add(num - 1)
            }
        }
        
        if pages.count < 1 {
            let alert = NSAlert()
            alert.alertStyle = .critical
            alert.messageText = String(format: "%@%@", self.originalDocument?.documentURL.lastPathComponent ?? "", KMLocalizedString("Invalid page range or the page number is out of range. Please try again.", nil))
            alert.runModal()
        } else {
            self.selectPages = pages
        }
    }
    
    func reloadPDFWithIndex() {
        self.pdfView.documentView().enclosingScrollView?.hasVerticalScroller = false
        self.pdfView.documentView().enclosingScrollView?.hasHorizontalScroller = false
        let pageCount = self.previewDocument?.pageCount
        
        let currentPageIndex = self.previewDocument?.index(for: self.pdfView.currentPage())
        
        self.currentPageIndexTextF.stringValue = "\((currentPageIndex ?? 0)+1)"
        
        self.totalPageCountLabel.stringValue = String(format:NSLocalizedString(" / %ld", comment: ""), pageCount ?? 0)
    }
    
    func updateLocationXY() {
        guard centerButton.state == .on else { return }
        let unitScanl = unitConversion()
        let page = originalDocument?.page(at: UInt(currentPage))
        let pageBounds = page?.bounds(for: .mediaBox)
        
        let x = (drawPageRect.size.width - (pageBounds?.size.width ?? 0)) / (2 * unitScanl)
        let y = (drawPageRect.size.height - (pageBounds?.size.height ?? 0)) / (2 * unitScanl)
        
        xText.stringValue = formatFloat(Float(x))
        yText.stringValue = formatFloat(Float(y))
    }
    
    func handerReDraw() {
        if drawPageRect.size.width < 0 || drawPageRect.size.height < 0 {
            NSSound.beep()
            return
        } else {
            for i in 0..<(originalDocument?.pageCount ?? 0) {
                if selectPages.contains(i) {
                    let newPage = KMCropPDFPage()
                    newPage.setBounds(NSMakeRect(0, 0, drawPageRect.size.width, drawPageRect.size.height), for: .mediaBox)
                    let cropPage = self.originalDocument?.page(at: i)
                    newPage.cropDrawingPage = cropPage
                    self.originalDocument?.insertPageObject(newPage, at: i)
                    self.originalDocument?.removePage(at: i)
                }
            }
        }
    }
    
    @IBAction func buttonItemClick_Proport(_ sender: NSButton) {
        var mint = min(cropEdgeInsets.bottom, cropEdgeInsets.top) 
        mint = min(mint, cropEdgeInsets.left)
        mint = min(mint, cropEdgeInsets.right)
        cropEdgeInsets = NSEdgeInsets(top: mint, left: mint, bottom: mint, right: mint)
        let unitScanl = unitConversion()
        rightStepper.stringValue = formatFloat(Float(cropEdgeInsets.right/unitScanl))
        topDistanceText.stringValue = "\(formatFloat(Float(cropEdgeInsets.top/unitScanl)))"
        leftDistanceText.stringValue = "\(formatFloat(Float(cropEdgeInsets.left/unitScanl)))"
        bottomDistanceText.stringValue = "\(formatFloat(Float(cropEdgeInsets.bottom/unitScanl)))"
        rightDistanceText.stringValue = "\(formatFloat(Float(cropEdgeInsets.right/unitScanl)))"
        if proportButton.state == .on {
            marginsButton.state = .off
        }

        updateView()
        updateCropViewLabel()
    }
    
    @IBAction func buttonClicked_Margin(_ sender: NSButton) {
        if marginsButton.state == .on {
            proportButton.state = .off
            topDistanceText.isEnabled = false
            bottomDistanceText.isEnabled = false
            leftDistanceText.isEnabled = false
            rightDistanceText.isEnabled = false
            
            topStepper.isEnabled = false
            bottomStepper.isEnabled = false
            leftStepper.isEnabled = false
            rightStepper.isEnabled = false
            
            previewDocument = CPDFDocument()
            
            for i in 0..<(originalDocument?.pageCount ?? 0) {
                var page: CPDFPage? = nil
                if selectPages.contains(i) {
                    page = CPDFPage()
                    let orgPage = originalDocument?.page(at: i)
                    let rect = KMCropTools.getPageForegroundBox(orgPage ?? CPDFPage())
                    let pageBounds = orgPage?.bounds(for: .mediaBox) ?? NSRect.zero
                    page?.setBounds(pageBounds, for: .mediaBox)
                    page?.cropDrawingPage = orgPage
                    page?.cropRect = rect
                } else {
                    page = originalDocument?.page(at: i)
                }
                previewDocument?.insertPageObject(page, at: previewDocument?.pageCount ?? 0)
            }
            
            pdfView.document = previewDocument
            pdfView.needsDisplay = true
        } else {
            topDistanceText.isEnabled = true
            bottomDistanceText.isEnabled = true
            leftDistanceText.isEnabled = true
            rightDistanceText.isEnabled = true
            
            topStepper.isEnabled = true
            bottomStepper.isEnabled = true
            leftStepper.isEnabled = true
            rightStepper.isEnabled = true
            
            cropEdgeInsets = NSEdgeInsets(top: CGFloat(topDistanceText.floatValue), left: CGFloat(leftDistanceText.floatValue), bottom: CGFloat(bottomDistanceText.floatValue), right: CGFloat(rightDistanceText.floatValue))
            let unitScanl = unitConversion()
            rightStepper.stringValue = formatFloat(Float(cropEdgeInsets.right/unitScanl))
            topDistanceText.stringValue = "\(formatFloat(Float(cropEdgeInsets.top/unitScanl)))"
            leftDistanceText.stringValue = "\(formatFloat(Float(cropEdgeInsets.left/unitScanl)))"
            bottomDistanceText.stringValue = "\(formatFloat(Float(cropEdgeInsets.bottom/unitScanl)))"
            rightDistanceText.stringValue = "\(formatFloat(Float(cropEdgeInsets.right/unitScanl)))"
            
            updateView()
        }
        updateCropViewLabel()
    }
    
    @IBAction func buttonItemClick_Zero(_ sender: NSButton) {
        cropEdgeInsets = NSEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        let unitScanl = unitConversion()
        rightStepper.stringValue = formatFloat(Float(cropEdgeInsets.right/unitScanl))
        topDistanceText.stringValue = "\(formatFloat(Float(cropEdgeInsets.top/unitScanl)))"
        leftDistanceText.stringValue = "\(formatFloat(Float(cropEdgeInsets.left/unitScanl)))"
        bottomDistanceText.stringValue = "\(formatFloat(Float(cropEdgeInsets.bottom/unitScanl)))"
        rightDistanceText.stringValue = "\(formatFloat(Float(cropEdgeInsets.right/unitScanl)))"

        marginsButton.state = .off
        proportButton.state = .off

        updateView()
        updateCropViewLabel()
    }
    
    @IBAction func buttonItemClick_Revert(_ sender: NSButton) {
        cropRect = defaultCropRect
        marginsButton.state = .off
        proportButton.state = .off

        changePrePDFView()
        updateCropViewLabel()
    }
    
    @IBAction func buttonItemClick_Cancel(_ sender: NSButton) {
        self.km_quick_endSheet()
        
        super.close()
    }
    
    @IBAction func buttonItemClick_Save(_ sender: NSButton) {
        self.window?.makeFirstResponder(nil)
        self.getDrawPages()

        if self.selectPages.count < 1 {
            let alert = NSAlert()
            alert.alertStyle = .critical
            alert.messageText = "\(self.originalDocument?.documentURL.path.lastPathComponent ?? "") \(NSLocalizedString("Invalid page range or the page number is out of range. Please try again.", comment: ""))"
            alert.runModal()
            return
        }

        if self.pageSizePopUpButton.indexOfSelectedItem == 0 && self.fixedSizeButton.state == .on {
            var box = CPDFDisplayBox.mediaBox
            if self.applyPopUpButton.indexOfSelectedItem == 0 {
                box = .cropBox
            } else if self.applyPopUpButton.indexOfSelectedItem == 1 {
                box = .artBox
            } else if self.applyPopUpButton.indexOfSelectedItem == 2 {
                box = .trimBox
            } else {
                box = .bleedBox
            }

            let page = self.originalDocument?.page(at: UInt(currentPage))
            let pageBounds = page?.bounds(for: .mediaBox)
            
            if self.marginsButton.state == .on {
                for i in 0..<(selectPages.count) {
                    let num: NSNumber = selectPages[i] as! NSNumber
                    let page = self.originalDocument?.page(at: UInt((num.intValue)))
                    let rect = KMCropTools.getPageForegroundBox(page ?? CPDFPage())
                    page?.setBounds(rect, for: .cropBox)
                }
            } else {
                let tCropRect = NSMakeRect(
                    self.cropEdgeInsets.left,
                    self.cropEdgeInsets.bottom,
                    pageBounds!.size.width - self.cropEdgeInsets.left - self.cropEdgeInsets.right,
                    pageBounds!.size.height - self.cropEdgeInsets.top - self.cropEdgeInsets.bottom
                )
                
                self.selectPages.forEach { num in
                    let page = self.originalDocument?.page(at: UInt((num as! NSNumber).intValue))
                    page?.setBounds(tCropRect, for: box)
                    if self.applyPopUpButton.indexOfSelectedItem != 0 {
                        page?.setBounds(tCropRect, for: .cropBox)
                    }
                }
            }
        } else {
            var isAllow = true
            for num in self.selectPages {
                let page = self.originalDocument?.page(at: UInt((num as! NSNumber).intValue))
                let pageBounds = page?.bounds(for: .mediaBox)
                if self.drawPageRect.size.width < pageBounds!.size.width || self.drawPageRect.size.height < pageBounds!.size.height {
                    isAllow = false
                    break
                }
            }
            
            if !isAllow {
                NSSound.beep()
                return
            }
            
            self.handerReDraw()
        }

        self.close()
    }
    
    @IBAction func buttonItemClick_Print(_ sender: NSButton) {
        self.window?.makeFirstResponder(nil)
        self.getDrawPages()
        if self.selectPages.count < 1 {
            let alert = NSAlert()
            alert.alertStyle = .critical
            alert.messageText = "\(String(describing: self.originalDocument?.documentURL.path.lastPathComponent)) \(NSLocalizedString("Invalid page range or the page number is out of range. Please try again.", comment: ""))"
            alert.runModal()
            return
        }

        var fileName: String = ""
       
        if FileManager.default.fileExists(atPath: kCropPrintFolderPath()) == false {
            let success: ()? = try?FileManager.default.createDirectory(atPath: kCropPrintFolderPath(), withIntermediateDirectories: false)
            if success == nil {
                return
            }
        }
        fileName = "cropPDF.pdf"
        fileName = kCropPrintFolderPath().stringByAppendingPathComponent(fileName)

        let tDocuemnt = CPDFDocument()
        for i in 0..<(self.originalDocument?.pageCount ?? 0) {
            if let page = self.originalDocument?.page(at: i) {
                tDocuemnt?.insertPageObject(page as? CPDFPage, at: tDocuemnt?.pageCount ?? 0)
            }
        }

        if 0 == self.pageSizePopUpButton.indexOfSelectedItem && self.fixedSizeButton.state == .on {
            var box: CPDFDisplayBox = .mediaBox
            if 0 == self.applyPopUpButton.indexOfSelectedItem {
                box = .cropBox
            } else if 1 == self.applyPopUpButton.indexOfSelectedItem {
                box = .artBox
            } else if 2 == self.applyPopUpButton.indexOfSelectedItem {
                box = .trimBox
            } else {
                box = .bleedBox
            }
            
            if let page = self.originalDocument?.page(at: UInt(self.currentPage)) {
                let pageBounds = page.bounds(for: .mediaBox)
                if self.marginsButton.state == .on {
                    for i in 0..<self.selectPages.count {
                        let num: NSNumber = self.selectPages[i] as! NSNumber
                        if let page = tDocuemnt?.page(at: UInt(num.intValue)) {
                            let rect = KMCropTools.getPageForegroundBox(page)
                            page.setBounds(rect, for: .cropBox)
                        }
                    }
                } else {
                    let tCropRect = CGRect(x: self.cropEdgeInsets.left, y: self.cropEdgeInsets.bottom, width: pageBounds.size.width - self.cropEdgeInsets.left - self.cropEdgeInsets.right , height: pageBounds.size.height - self.cropEdgeInsets.top - self.cropEdgeInsets.bottom)
                    
                    for i in 0..<self.selectPages.count {
                        let num: NSNumber = self.selectPages[i] as! NSNumber
                        if let page = tDocuemnt?.page(at: UInt(num.intValue)) {
                            page.setBounds(tCropRect, for: box)
                            if 0 != self.applyPopUpButton.indexOfSelectedItem {
                                page.setBounds(tCropRect, for: .cropBox)
                            }
                        }
                    }
                }
            }
        } else {
            var isAllow = true
            for num in self.selectPages {
                if let page = self.originalDocument?.page(at: UInt((num as! NSNumber).intValue)) {
                    let pageBounds = page.bounds(for: .mediaBox)
                    if self.drawPageRect.size.width < pageBounds.size.width || self.drawPageRect.size.height < pageBounds.size.height {
                        isAllow = false
                        break
                    }
                }
            }
            if !isAllow {
                NSSound.beep()
                return
            }
            if self.drawPageRect.size.width < 0 || self.drawPageRect.size.height < 0 {
                NSSound.beep()
                return
            } else {
                for i in 0..<(tDocuemnt?.pageCount ?? 0) {
                    let page: KMCropPDFPage?
                    if self.selectPages.contains(NSNumber(value: i)) {
                        page = KMCropPDFPage()
                        page?.setBounds(NSRect(x: 0, y: 0, width: self.drawPageRect.size.width, height: self.drawPageRect.size.height), for: .mediaBox)
                        if let cropPage = tDocuemnt?.page(at: i) {
                            page?.cropDrawingPage = cropPage
                        }
                        if let thePage = page {
                            tDocuemnt?.insertPageObject(thePage, at: i)
                            tDocuemnt?.removePage(at: i+1)
                        }
                    }
                }
            }
        }

        guard let isSuc = tDocuemnt?.write(to: URL(fileURLWithPath: fileName )) else { return }

        if isSuc {
            let pdf = PDFDocument(url: URL(fileURLWithPath: fileName ))
            let printInfo = NSPrintInfo.shared
            
            var printOperation: NSPrintOperation?
            printOperation = pdf?.printOperation(for: printInfo, scalingMode: .pageScaleNone, autoRotate: true)
            
            printOperation?.runModal(for: self.window!, delegate: self, didRun: nil, contextInfo: nil)
        }
    }
    
    @IBAction func buttonItemClick_FixedSize(_ sender: NSButton) {
        self.fixedSizeButton.state = .on
        self.customButton.state = .off
        self.pageSizePopUpButton.isEnabled = true
        self.widthText.isEnabled = false
        self.heightText.isEnabled = false
        if self.pageSizePopUpButton.indexOfSelectedItem != 0 {
            self.centerButton.isEnabled = true
            self.xText.isEnabled = true
            self.yText.isEnabled = true
            self.xText.stringValue = "0"
            self.yText.stringValue = "0"
            self.isChangePageSize = false
            
            self.topDistanceText.isEnabled = false
            self.bottomDistanceText.isEnabled = false
            self.leftDistanceText.isEnabled = false
            self.rightDistanceText.isEnabled = false
            self.topStepper.isEnabled = false
            self.bottomStepper.isEnabled = false
            self.leftStepper.isEnabled = false
            self.rightStepper.isEnabled = false
            self.marginsButton.isEnabled = false
            self.zeroButton.isEnabled = false
            self.revertButton.isEnabled = false
            self.proportButton.isEnabled = false
            self.applyPopUpButton.isEnabled = false
        } else {
            self.isChangePageSize = true
            self.centerButton.isEnabled = false
            self.xText.isEnabled = false
            self.yText.isEnabled = false
            let tSize = KMPageSizeTool.getPaperSize(paperName: self.pageSizePopUpButton.stringValue)
            self.drawPageRect = CGRect(x: 0, y: 0, width: tSize.width * 595.0/210, height: tSize.height * 842.0/297.0)
            
            self.topDistanceText.isEnabled = true
            self.bottomDistanceText.isEnabled = true
            self.leftDistanceText.isEnabled = true
            self.rightDistanceText.isEnabled = true
            self.topStepper.isEnabled = true
            self.bottomStepper.isEnabled = true
            self.leftStepper.isEnabled = true
            self.rightStepper.isEnabled = true
            self.marginsButton.isEnabled = true
            self.zeroButton.isEnabled = true
            self.revertButton.isEnabled = true
            self.proportButton.isEnabled = true
            self.applyPopUpButton.isEnabled = true
        }
        updateCropViewLabel()
    }
    
    @IBAction func buttonClicked_PageSize(_ sender: NSPopUpButton) {
        if (0 == sender.indexOfSelectedItem) {
            self.isChangePageSize = false
            self.centerButton.isEnabled = false
            self.xText.isEnabled = false
            self.yText.isEnabled = false
            self.xText.floatValue = 0
            self.yText.floatValue = 0
            self.marginsButton.state = NSControl.StateValue.off
            if (NSControl.StateValue.on != self.marginsButton.state) {
                self.topDistanceText.isEnabled = true
                self.bottomDistanceText.isEnabled = true
                self.leftDistanceText.isEnabled = true
                self.rightDistanceText.isEnabled = true
                self.topStepper.isEnabled = true
                self.bottomStepper.isEnabled = true
                self.leftStepper.isEnabled = true
                self.rightStepper.isEnabled = true
            } else {
                self.topDistanceText.isEnabled = false
                self.bottomDistanceText.isEnabled = false
                self.leftDistanceText.isEnabled = false
                self.rightDistanceText.isEnabled = false
                
                self.topStepper.isEnabled = false
                self.bottomStepper.isEnabled = false
                self.leftStepper.isEnabled = false
                self.rightStepper.isEnabled = false
            }
            self.marginsButton.isEnabled = true
            self.zeroButton.isEnabled = true
            self.revertButton.isEnabled = true
            self.proportButton.isEnabled = true
            self.applyPopUpButton.isEnabled = true
        } else {
            self.topDistanceText.isEnabled = false
            self.bottomDistanceText.isEnabled = false
            self.leftDistanceText.isEnabled = false
            self.rightDistanceText.isEnabled = false
            
            self.topStepper.isEnabled = false
            self.bottomStepper.isEnabled = false
            self.leftStepper.isEnabled = false
            self.rightStepper.isEnabled = false
            self.marginsButton.isEnabled = false
            self.zeroButton.isEnabled = false
            self.revertButton.isEnabled = false
            self.proportButton.isEnabled = false
            self.applyPopUpButton.isEnabled = false
            
            self.isChangePageSize = true
            let menuItem = self.pageSizePopUpButton.itemTitle(at: self.pageSizePopUpButton.indexOfSelectedItem)
            let tSize = KMPageSizeTool.getPaperSize(paperName: menuItem)
            self.drawPageRect = CGRect(x: 0, y: 0, width: tSize.width * 595.0/210, height: tSize.height * 842.0/297.0)
            self.centerButton.isEnabled = true
            self.xText.isEnabled = true
            self.yText.isEnabled = true
        }
        updateLocationXY()
        changePrePDFView()
        updateCropViewLabel()
    }
    
    @IBAction func buttonItemClick_CustomSize(_ sender: NSButton) {
        self.fixedSizeButton.state = NSControl.StateValue.off
        self.customButton.state = NSControl.StateValue.on
       self.widthText.isEnabled = true
       self.heightText.isEnabled = true
       self.centerButton.isEnabled = true
       self.xText.isEnabled = true
       self.yText.isEnabled = true

       self.topDistanceText.isEnabled = false
       self.bottomDistanceText.isEnabled = false
       self.leftDistanceText.isEnabled = false
       self.rightDistanceText.isEnabled = false
       self.topStepper.isEnabled = false
       self.bottomStepper.isEnabled = false
       self.leftStepper.isEnabled = false
       self.rightStepper.isEnabled = false
       self.marginsButton.isEnabled = false
       self.zeroButton.isEnabled = false
       self.revertButton.isEnabled = false
       self.proportButton.isEnabled = false
       self.applyPopUpButton.isEnabled = false

       self.pageSizePopUpButton.isEnabled = false
       self.isChangePageSize = true
        self.drawPageRect = CGRect(x: 0, y: 0, width: Int(self.widthText.floatValue), height: Int(self.heightText.floatValue))
       updateLocationXY()
       changePrePDFView()
       updateCropViewLabel()
    }
    
    @IBAction func buttonItemClick_Center(_ sender: NSButton) {
        if (NSControl.StateValue.on == sender.state) {
            updateLocationXY()
        } else {
            self.xText.stringValue = "0 \(self.unitPopUpButton.title)"
            self.yText.stringValue = "0 \(self.unitPopUpButton.title)"
        }
    }
    
    @IBAction func comboBoxItemClick_PageRange(_ sender: NSButton) {
        if (0 == self.pageRangeComboBox.indexOfSelectedItem || 1 == self.pageRangeComboBox.indexOfSelectedItem || 2 == self.pageRangeComboBox.indexOfSelectedItem) {
            self.pageRangeComboBox.delegate = nil
            self.window?.makeFirstResponder(self)
            self.pageRangeComboBox.isEditable = false
            self.getDrawPages()
            self.changePrePDFView()
        } else if (3 == self.pageRangeComboBox.indexOfSelectedItem) {
            self.pageRangeComboBox.delegate = self
            self.pageRangeComboBox.stringValue = ""
            self.pageRangeComboBox.isEditable = true
            self.window?.makeFirstResponder(self.pageRangeComboBox)
        }
    }
    
    @IBAction func buttonClicked_Unit(_ sender: NSPopUpButton) {
        if self.unitPopUpButton.indexOfSelectedItem == 1 {
            self.cropLabel.stringValue = "(\(NSLocalizedString("mm", comment: "")))"
        } else if self.unitPopUpButton.indexOfSelectedItem == 0 {
            self.cropLabel.stringValue = "(\(NSLocalizedString("cm", comment: "")))"
        } else {
            self.cropLabel.stringValue = "(\(NSLocalizedString("in", comment: "")))"
        }
        updateSizeView()
        updateCropViewLabel()
    }
    
    @IBAction func buttonClicked_AppleType(_ sender: NSPopUpButton) {
        if (0 == sender.indexOfSelectedItem) {
            self.marginsButton.isEnabled = true
        } else {
            self.marginsButton.isEnabled = false
        }
        updateCropViewLabel()
    }
    
    @IBAction func stepperItemClick_Distance(_ sender: NSButton) {
        let unitScanl: CGFloat = unitConversion()
        if sender == topStepper {
            self.topDistanceText.stringValue = String(format: "%.2f", self.topStepper.floatValue)
            let formatter = self.topStepper.floatValue * Float(unitScanl)
            self.cropEdgeInsets = NSEdgeInsetsMake(CGFloat(formatter), self.cropEdgeInsets.left, self.cropEdgeInsets.bottom, self.cropEdgeInsets.right)
        } else if sender == bottomStepper {
            self.bottomDistanceText.stringValue = String(format: "%.2f", self.bottomStepper.floatValue)
            let formatter = self.bottomStepper.floatValue * Float(unitScanl)
            self.cropEdgeInsets = NSEdgeInsetsMake(self.cropEdgeInsets.top, self.cropEdgeInsets.left, CGFloat(formatter), self.cropEdgeInsets.right)
        } else if sender == leftStepper {
            self.leftDistanceText.stringValue = String(format: "%.2f", self.leftStepper.floatValue)
            let formatter = self.leftStepper.floatValue * Float(unitScanl)
            self.cropEdgeInsets = NSEdgeInsetsMake(self.cropEdgeInsets.top, CGFloat(formatter), self.cropEdgeInsets.bottom, self.cropEdgeInsets.right)
        } else if sender == rightStepper {
            self.rightDistanceText.stringValue = String(format: "%.2f", self.rightStepper.floatValue)
            let formatter = self.rightStepper.floatValue * Float(unitScanl)
            self.cropEdgeInsets = NSEdgeInsetsMake(self.cropEdgeInsets.top, self.cropEdgeInsets.left, self.cropEdgeInsets.bottom, CGFloat(formatter))
        }
        updateView()
        updateCropViewLabel()
    }
    
    @IBAction func goPrevious(_ sender: NSButton) {
        if self.pdfView.canGoToPreviousPage() {
            self.pdfView.goToPreviousPage(nil)
        }
        self.reloadPDFWithIndex()
    }
    
    @IBAction func goNext(_ sender: NSButton) {
        if self.pdfView.canGoToNextPage() {
            self.pdfView.goToNextPage(nil)
        }
        self.reloadPDFWithIndex()
    }
    
//MARK: NSTextFieldDelegate
    func controlTextDidEndEditing(_ obj: Notification) {
        guard let textField = obj.object as? NSTextField else { return }
        guard let page = originalDocument?.page(at: UInt(currentPage)) else {
            return
        }

        let pageBounds = page.bounds(for: .mediaBox)

        if textField == topDistanceText {
            let unitScale = unitConversion()
            var unitMax = CGFloat(textField.floatValue) * CGFloat(unitScale)
            
            if unitMax > pageBounds.size.height {
                unitMax = pageBounds.size.width
                textField.stringValue = "\(Float(pageBounds.size.height/unitScale))"
            } else if unitMax <= 0 {
                unitMax = 0
                textField.stringValue = "0"
            }
            
            topStepper.stringValue = textField.stringValue
            
            cropEdgeInsets = NSEdgeInsetsMake(unitMax, cropEdgeInsets.left, cropEdgeInsets.bottom, cropEdgeInsets.right)
            updateView()
        } else if textField == bottomDistanceText {
            let unitScale = unitConversion()
            var unitMax = CGFloat(textField.floatValue) * CGFloat(unitScale)
            
            if unitMax > pageBounds.size.height {
                unitMax = pageBounds.size.height
                textField.stringValue = "\(formatFloat(Float(pageBounds.size.height/unitScale)))"
            } else if unitMax <= 0 {
                unitMax = 0
                textField.stringValue = "0"
            }
            
            bottomStepper.stringValue = textField.stringValue
            
            cropEdgeInsets = NSEdgeInsetsMake(cropEdgeInsets.top, cropEdgeInsets.left, unitMax, cropEdgeInsets.right)
            updateView()
        } else if textField == leftDistanceText {
            let unitScale = unitConversion()
            var unitMax = CGFloat(textField.floatValue) * CGFloat(unitScale)
            
            if unitMax > pageBounds.size.width {
                unitMax = pageBounds.size.width
                textField.stringValue = "\(formatFloat(Float(pageBounds.size.width/unitScale)))"
            } else if unitMax <= 0 {
                unitMax = 0
                textField.stringValue = "0"
            }
            
            leftStepper.stringValue = textField.stringValue
            
            cropEdgeInsets = NSEdgeInsetsMake(cropEdgeInsets.top, unitMax, cropEdgeInsets.bottom, cropEdgeInsets.right)
            updateView()
        } else if textField == rightDistanceText {
            let unitScale = unitConversion()
            var unitMax = CGFloat(textField.floatValue) * CGFloat(unitScale)
            
            if unitMax > pageBounds.size.height {
                unitMax = pageBounds.size.width
                textField.stringValue = "\(formatFloat(Float(pageBounds.size.width/unitScale)))"
            } else if unitMax <= 0 {
                unitMax = 0
                textField.stringValue = "0"
            }
            
            rightStepper.stringValue = textField.stringValue
            
            cropEdgeInsets = NSEdgeInsetsMake(cropEdgeInsets.top, cropEdgeInsets.left, cropEdgeInsets.bottom, unitMax)
            updateView()
        } else if textField == widthText {
            let unitScale = unitConversion()
            let unitMax = CGFloat(textField.floatValue) * CGFloat(unitScale)
            
            drawPageRect = CGRect(x: 0, y: 0, width: unitMax, height: drawPageRect.size.height)
            
            updateLocationXY()
            changePrePDFView()
        } else if textField == heightText {
            let unitScale = unitConversion()
            let unitMax = CGFloat(textField.floatValue) * CGFloat(unitScale)
            
            drawPageRect = CGRect(x: 0, y: 0, width: drawPageRect.size.width, height: unitMax)
            
            updateLocationXY()
            changePrePDFView()
        } else if textField == currentPageIndexTextF {
            pdfView.go(to: originalDocument?.page(at: UInt(Int(currentPageIndexTextF.stringValue)! - 1))!)
        } else if textField == pageRangeComboBox {
            getDrawPages()
            changePrePDFView()
        }

        updateCropViewLabel()
    }
    
    func changePrePDFView() {
        previewDocument = CPDFDocument()
        for i in 0..<(self.originalDocument?.pageCount ?? 0) {
            var page: CPDFPage!
            if self.selectPages.contains(i) {
                let doc = CPDFDocument()
                if self.marginsButton.state == .on {
                    page = CPDFPage()
                    let orgPage: CPDFPage = (self.originalDocument?.page(at: i))!
                    let rect = KMCropTools.getPageForegroundBox(orgPage)
                    let pageBounds = orgPage.bounds(for: .mediaBox)
                    page?.setBounds(pageBounds, for: .mediaBox)
                    page?.cropDrawingPage = orgPage
                    page?.cropRect = rect
                } else {
                    page = self.originalDocument?.page(at: i)!
                    let orgPage = self.originalDocument?.page(at: i)!
                    if self.isChangePageSize {
                        page?.setBounds(self.drawPageRect, for: .mediaBox)
                        page?.isChangePageSize = true
                    } else {
                        let pageBounds = orgPage?.bounds(for: .mediaBox)
                        page.setBounds(pageBounds ?? .zero, for: .mediaBox)
                    }
                    page?.cropRect = self.cropRect
                    page?.cropDrawingPage = orgPage
                    page?.cropOffsetX = CGFloat(self.xText.floatValue)
                    page?.cropOffsetY = CGFloat(self.yText.floatValue)
//                    
//                    let info = KMCropInfo()
//                    info.drawPage = page
//                    self.pdfView.drawInfo.append(info)
                }
            } else {
                page = self.originalDocument?.page(at: i)!
            }
            self.previewDocument?.insertPageObject(page, at: self.previewDocument?.pageCount ?? 0)
        }
        self.pdfView.document = self.previewDocument
        self.pdfView.layoutDocumentView()
        self.pdfView.needsDisplay = true
        let tPage = self.previewDocument?.page(at: 0)!
        self.pdfView.go(to: tPage)
        self.currentPageIndexTextF.stringValue = "\(1)"
    }
    
    func updateSizeView() {
        let page = self.originalDocument?.page(at: UInt(self.currentPage))!
        let pageBounds = page?.bounds(for: .mediaBox)
        self.cropEdgeInsets = NSEdgeInsets(top: (pageBounds?.size.height ?? 0) - self.cropRect.maxY,
                                           left: self.cropRect.origin.x,
                                           bottom: self.cropRect.origin.y,
                                           right: (pageBounds?.size.width ?? 0) - self.cropRect.maxX)
        
        let unitScale = self.unitConversion()
        self.topStepper.stringValue = self.formatFloat(Float(self.cropEdgeInsets.top / unitScale))
        self.leftStepper.stringValue = self.formatFloat(Float(self.cropEdgeInsets.left / unitScale))
        self.bottomStepper.stringValue = self.formatFloat(Float(self.cropEdgeInsets.bottom / unitScale))
        self.rightStepper.stringValue = self.formatFloat(Float(self.cropEdgeInsets.right / unitScale))
        self.topDistanceText.stringValue = "\(self.formatFloat(Float(self.cropEdgeInsets.top / unitScale)))"
        self.leftDistanceText.stringValue = "\(self.formatFloat(Float(self.cropEdgeInsets.left / unitScale)))"
        self.bottomDistanceText.stringValue = "\(self.formatFloat(Float(self.cropEdgeInsets.bottom / unitScale)))"
        self.rightDistanceText.stringValue = "\(self.formatFloat(Float(self.cropEdgeInsets.right / unitScale)))"
        
        self.leftStepper.maxValue = (pageBounds?.size.width ?? 0) / unitScale
        self.rightStepper.maxValue = (pageBounds?.size.width ?? 0) / unitScale
        self.topStepper.maxValue = (pageBounds?.size.height ?? 0) / unitScale
        self.bottomStepper.maxValue = (pageBounds?.size.height ?? 0) / unitScale
    }
    
    func localizedString() {
        self.unitLabel.stringValue = NSLocalizedString("Unit:", comment: "")
        self.marginLabel.stringValue = NSLocalizedString("Margin Controls", comment: "")
        self.applyLabel.stringValue = NSLocalizedString("Apply to:", comment: "")
        self.pageSizeLabel.stringValue = NSLocalizedString("Change Page Size", comment: "")
        self.pageRangeLabel.stringValue = NSLocalizedString("Page Range:", comment: "")
        self.widthLabel.stringValue = NSLocalizedString("Width:", comment: "")
        self.heightLabel.stringValue = NSLocalizedString("Height:", comment: "")
        self.xLabel.stringValue = NSLocalizedString("XOffset:", comment: "")
        self.yLabel.stringValue = NSLocalizedString("YOffset:", comment: "")
        self.topLabel.stringValue = NSLocalizedString("Top:", comment: "")
        self.bottomLabel.stringValue = NSLocalizedString("Bottom:", comment: "")
        self.leftLabel.stringValue = NSLocalizedString("Left:", comment: "")
        self.rightLabel.stringValue = NSLocalizedString("Right:", comment: "")
        self.zeroButton.title = NSLocalizedString("Set To Zero", comment: "")
        self.marginsButton.title = NSLocalizedString("Remove White Margins", comment: "")
        self.proportButton.title = NSLocalizedString("Constrain Proport", comment: "")
        self.revertButton.title = NSLocalizedString("Revert To Selection", comment: "")
        self.fixedSizeButton.title = NSLocalizedString("Fixed Sizes", comment: "")
        self.customButton.title = NSLocalizedString("Custom", comment: "")
        self.centerButton.title = NSLocalizedString("Center", comment: "")
        self.cancelButton.title = NSLocalizedString("Cancel", comment: "")
        self.saveButton.title = NSLocalizedString("Done", comment: "")
        self.printButton.title = NSLocalizedString("Print", comment: "")
        
        self.pageRangeComboBox.addItems(withObjectValues: [NSLocalizedString("All Pages", comment: ""),
                                                           NSLocalizedString("Odd Pages Only", comment: ""),
                                                           NSLocalizedString("Even Pages Only", comment: ""),
                                                           NSLocalizedString("e.g. 1,3-5,10", comment: "")])
        self.pageRangeComboBox.placeholderString = NSLocalizedString("e.g. 1,3-5,10", comment: "")
        
        if (.AllPages == self.pageType) {
            self.pageRangeComboBox.selectItem(at: 0)
            self.pageRangeComboBox.isEditable = false
        } else if(.OnlyOdd == self.pageType){
            self.pageRangeComboBox.selectItem(at: 1)
            self.pageRangeComboBox.isEditable = false
        } else if(.AllPages == self.pageType){
            self.pageRangeComboBox.selectItem(at: 2)
            self.pageRangeComboBox.isEditable = false
        } else {
            self.pageRangeComboBox.selectItem(at: 3)
            self.pageRangeComboBox.isEditable = true
            self.pageRangeComboBox.stringValue = self.pagesString
        }
        
        self.unitPopUpButton.removeAllItems()
        let items = [NSLocalizedString("cm", comment: ""),
                     NSLocalizedString("mm", comment: ""),
                     NSLocalizedString("in", comment: "")]
        self.unitPopUpButton.addItems(withTitles: items)
        self.unitPopUpButton.selectItem(at: 0)
        
        self.xText.stringValue = "0" + self.unitPopUpButton.title
        self.yText.stringValue = "0" + self.unitPopUpButton.title
        self.widthText.stringValue = "0" + self.unitPopUpButton.title
        self.heightText.stringValue = "0" + self.unitPopUpButton.title
        
        self.applyPopUpButton.removeAllItems()
        let applyItems = [NSLocalizedString("CropBox", comment: ""),
                          NSLocalizedString("ArtBox", comment: ""),
                          NSLocalizedString("TrimBox", comment: ""),
                          NSLocalizedString("BleedBox", comment: "")]
        self.applyPopUpButton.addItems(withTitles: applyItems)
        self.applyPopUpButton.selectItem(at: 0)
        
        let paperArray = KMPageSizeTool.paperSize()
        var pageSizeItems = [Any]()
        pageSizeItems.append(contentsOf: paperArray)
        self.pageSizePopUpButton.removeAllItems()
        self.pageSizePopUpButton.addItems(withTitles: pageSizeItems as! [String])
        self.pageSizePopUpButton.insertItem(withTitle: NSLocalizedString("None", comment: ""), at: 0)
        self.pageSizePopUpButton.selectItem(at: 0)
    }
    
    
    
    
    
    func kCropPrintFolderPath() -> String {
        let rootPath = KMDataManager.fetchAppSupportOfBundleIdentifierDirectory().path
        return rootPath.stringByAppendingPathComponent("Crop")
    }
}