//
//  KMPDFRedactViewController.swift
//  PDF Reader Pro
//
//  Created by tangchao on 2023/12/18.
//

import Cocoa

class KMPDFRedactViewController: NSViewController {
    
    var scaleFactor: CGFloat = 0 {
        didSet {
            self.redactPdfView.scaleFactor = scaleFactor
        }
    }
    
    var callback: ((Bool, Int, Bool, URL?)->Void)?
    var titleBack: ((String)->Void)?
    
    @IBOutlet var redactPdfView: KMRedactPDFView!
    
    @IBOutlet weak var redactTipLabel: NSTextField!
    @IBOutlet weak var propertiesLabel: NSTextField!
    @IBOutlet weak var redactTextLabel: NSTextField!
    @IBOutlet weak var exitBox: KMBox!
    @IBOutlet weak var applyBox: KMBox!
    @IBOutlet weak var exitButton: NSButton!
    @IBOutlet weak var applyButton: NSButton!
    @IBOutlet weak var toolView: NSView!
    @IBOutlet weak var redactTextBox: NSBox!
    @IBOutlet weak var propertiesBox: NSBox!
    
    @IBOutlet weak var redactTextButton: KMCustomButton!
    @IBOutlet weak var propertiesButton: KMCustomButton!
    
    @IBOutlet weak var whiteOutBox: NSBox!
    @IBOutlet weak var whiteOutLabel: NSTextField!
    @IBOutlet weak var whiteOutButton: KMCustomButton!
    
    private var _url: URL?
    private var url: URL? {
        get {
            return self._url
        }
    }
    private var _password: String?
    private var _indicator: NSProgressIndicator?
    
    private var isWhiteOut_ = false

    deinit {
        KMPrint("KMPDFRedactViewController deinit.")
        
        NotificationCenter.default.removeObserver(self)
        self.redactPdfView.delegate = nil
    }
    
    convenience init(url: URL, password: String?) {
        self.init()
        
        self._url = url
        self._password = password
    }
    
    override func loadView() {
        super.loadView()
        self.isWhiteOut_ = false
        
        self.propertiesBox.wantsLayer = true
        self.redactTextBox.wantsLayer = true
        self.redactTextBox.fillColor = KMAppearance.Layout.w30Color()
        self.redactTextBox.layer?.cornerRadius = 6
        self.redactTextLabel.textColor = KMAppearance.Layout.w0Color()
        self.propertiesLabel.textColor = KMAppearance.Layout.w0Color()
        self.redactTextLabel.stringValue = KMLocalizedString("Redact Text", nil)
        self.propertiesLabel.stringValue = KMLocalizedString("Properties", nil)
        
        self.propertiesButton.mouseMoveCallback = { [weak self] mouseEntered in
            self?.propertiesBox.layer?.cornerRadius = 6
            if mouseEntered {
                self?.propertiesBox.fillColor = KMAppearance.Layout.w30Color()
            } else {
                self?.propertiesBox.fillColor = .clear
            }
        }
        
        self.whiteOutBox.wantsLayer = true
//        self.whiteOutBox.fillColor = KMAppearance.Layout.w30Color()
        self.whiteOutBox.layer?.cornerRadius = 6
        self.whiteOutLabel.textColor = KMAppearance.Layout.w0Color()
        self.whiteOutLabel.stringValue = NSLocalizedString("White Out PDF", comment: "")
        
        self.redactTextButton.target = self
        self.redactTextButton.action = #selector(redactButtonAction)
        self.whiteOutButton.target = self
        self.whiteOutButton.action = #selector(whiteOutButtonAction)
        
        // Do view setup here.
        self.redactTipLabel.stringValue = KMLocalizedString("You are under redact mode", nil)
        self.applyButton.title = KMLocalizedString("Apply", nil)
        self.exitButton.toolTip = KMLocalizedString("Exit", nil)

        self.exitBox.fillColor = .clear
        self.exitBox.borderColor = KMAppearance.Layout.w70Color()
        self.exitBox.borderWidth = 1.0
        self.exitButton.title = KMLocalizedString("Exit", nil)
        self.exitButton.setTitleColor(KMAppearance.Layout.w0Color())
    
        self.applyButton.setTitleColor(KMAppearance.Interactive.a0Color())
        self.applyButton.wantsLayer = true
        
        self.applyBox.downCallback = { [weak self] downEntered, mouseBox, event in
            if downEntered {
                self?.apply_button(nil)
            }
        }
        
        self.exitBox.downCallback = { [weak self] downEntered, mouseBox, event in
            if downEntered {
                self?.exit_button(nil)
            }
        }

        self.toolView.wantsLayer = true
        self.toolView.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor
        
        let document = CPDFDocument(url: self.url!)
        if let pwd = self._password, pwd.isEmpty == false {
            document?.unlock(withPassword: pwd)
        }
        self.redactPdfView.document = document
    //    self.redactPdfView.scaleFactor = self.scaleFactor;
        self.redactPdfView.autoScales = true
        self.redactPdfView.delegate = self
//        self.redactPdfView.toolMode = .redactToolMode
        self.redactPdfView.operationType = .redact
        
    //    [self.redactPdfView layoutDocumentView];

        let frame = NSMakeRect((self.redactPdfView.frame.size.width-32)/2.0, (self.redactPdfView.frame.size.height-32)/2.0, 32, 32)
        self._indicator = NSProgressIndicator(frame: frame)
        self._indicator?.autoresizingMask = [.minXMargin, .maxXMargin, .minYMargin, .maxYMargin]
        self._indicator?.style = .spinning
        self._indicator?.controlSize = .regular
        self._indicator?.isIndeterminate = true
        self._indicator?.startAnimation(nil)
        self.redactPdfView.addSubview(self._indicator!)
        self._indicator?.isHidden = true
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        NotificationCenter.default.addObserver(self, selector: #selector(showCurrentRedactAnnotationProperties), name: KMRedactPDFView.showCurrentRedactAnnotationNotificationName, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(apply), name: KMRedactPDFView.redactAnnotationApplyNotificationName, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(across), name: KMRedactPDFView.redactAnnotationAcrossNotificationName, object: nil)
    }
    
    func setCurrentPageIndex(_ currentPageIndex: Int) {
        self.redactPdfView.go(toPageIndex: currentPageIndex, animated: false)
    }
    
    // MARK: - Button Actions

    @IBAction func showProperties_button(_ sender: AnyObject?) {
        FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_RedactText", withProperties: ["SubTbr_Btn": "Btn_SubTbr_RedactText_Properties"])
        
        let properties = KMRedactPropertiesWindowController()
        self.km_beginSheet(windowC: properties)
        properties.callback = { annotation in
            
        }
    }

    @IBAction func apply_button(_ sender: AnyObject?) {
        var isApply = false
        for i in 0 ..< self.redactPdfView.document.pageCount {
            let page = self.redactPdfView.document.page(at: i)
            for anno in page?.annotations ?? [] {
                if anno.isKind(of: CPDFRedactAnnotation.self) {
                     isApply = true
                 }
             }
         }
        if(self.redactPdfView.newAddAnnotation.count == 0 && !isApply) {
            return
        }

        let returnCode = KMAlertTool.runModelForMainThread_r(message: "", informative: KMLocalizedString("This will permanently remove the redacted information from this document. Once you save this document, you won’t be able to retrieve the redacted information.", nil), buttons: [KMLocalizedString("Apply", nil), KMLocalizedString("Cancel", nil)])
        if returnCode == .alertFirstButtonReturn {
            DispatchQueue.main.async {
                self.saveAsPath()
            }
        }
     }
    
    @IBAction func exit_button(_ sender: AnyObject?) {
        guard let block = self.callback else {
            return
        }
        block(false, self.redactPdfView.currentPageIndex, false, nil)
     }

    func saveAsPath() {
        let saveAccessCtr = KMSavePanelAccessoryController()
        var fileName = self.redactPdfView.document.documentURL.deletingPathExtension().lastPathComponent
        fileName = String(format: "%@_%@.pdf", fileName, "Redact")
        let outputSavePanel = NSSavePanel()
        outputSavePanel.allowedFileTypes = ["pdf"]
        outputSavePanel.nameFieldStringValue = fileName
        outputSavePanel.accessoryView = saveAccessCtr.view
        outputSavePanel.beginSheetModal(for: NSApp.mainWindow!) { result in
            if result == .OK {
                self.redactPdfView.document.applyRedactions()
                self._indicator?.isHidden = false
                self._indicator?.startAnimation(nil)
                let savePDFPath = outputSavePanel.url!.path

                let isSuccess = self.redactPdfView.document.write(toFile: savePDFPath)
                 if (isSuccess) {
//                     [self.redactPdfView.newAddAnnotation removeAllObjects];
                     if (saveAccessCtr.openAutomaticButton.state == .on) {
                         NSDocumentController.shared.km_safe_openDocument(withContentsOf: outputSavePanel.url!, display: true) { _, _, _ in
                             
                         }
                     } else {
                         KMTools.viewFile(at: savePDFPath)
                     }
                 }
                self._indicator?.stopAnimation(nil)
                self._indicator?.isHidden = true

                guard let block = self.callback else {
                    return
                }
                block(true, self.redactPdfView.currentPageIndex, false, outputSavePanel.url)
             }
         }
     }

    // MARK: - Button notice
    
    @objc func showCurrentRedactAnnotationProperties(_ notice: NSNotification) {
        guard let pdfview = notice.object as? KMRedactPDFView else {
            return
        }
        if(pdfview == self.redactPdfView) {
            let properties = KMRedactPropertiesWindowController()
            properties.readactAnnotation = self.redactPdfView.currentAnnotation
//            __block KMPDFRedactViewController *weak_self = self;
            self.km_beginSheet(windowC: properties)
            properties.callback = { [weak self] annotation in
                if let page = self?.redactPdfView.currentAnnotation?.page {
                    if let anno = annotation {
                        self?.redactPdfView.newAddAnnotation.append(anno)
                    }
                    self?.redactPdfView.setNeedsDisplayAnnotationViewFor(page)
                }
            }
        }
    }
    
    @objc func apply(_ notice: NSNotification) {
        guard let pdfview = notice.object as? KMRedactPDFView else {
            return
        }
        if(pdfview == self.redactPdfView) {
            self.apply_button(nil)
        }
    }
    
    @objc func across(_ notice: NSNotification) {
        guard let pdfview = notice.object as? KMRedactPDFView else {
            return
        }
        
        if(pdfview == self.redactPdfView) {
            let pagesWindowController = KMRedactSelectPagesWindowController(document: self.redactPdfView.document)
            self.km_beginSheet(windowC: pagesWindowController)
            pagesWindowController.callback = { [unowned self] pages in
                if pages.count > 0 {
                    self.redactPdfView.acrossAddAnnotations(pages)
                }
            }
        }
    }
    
    @objc func redactButtonAction(sender : NSButton) {
        FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_RedactText", withProperties: ["SubTbr_Btn": "Btn_SubTbr_RedactText_RedactPDF"])
        
        self.isWhiteOut_ = false
        self.redactPdfView.isWhiteOut = false
        self.updateButtonsState()
    }
    
    @objc func whiteOutButtonAction(sender: NSButton) {
        FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_RedactText", withProperties: ["SubTbr_Btn": "Btn_SubTbr_RedactText_WhiteOutPDF"])
        
        self.isWhiteOut_ = true
        self.redactPdfView.isWhiteOut = true
        self.updateButtonsState()
    }
    
    // MARK: - Private Methods
    
    private func updateButtonsState() {
        if self.isWhiteOut_ {
            self.whiteOutBox.fillColor = KMAppearance.Layout.w30Color()
            self.redactTextBox.fillColor = .clear
        } else {
            self.redactTextBox.fillColor = KMAppearance.Layout.w30Color()
            self.whiteOutBox.fillColor = .clear
        }
    }
    
}

extension KMPDFRedactViewController: CPDFViewDelegate {
    func pdfViewCurrentPageDidChanged(_ pdfView: CPDFView!) {
        let fileName = pdfView.document.documentURL.deletingLastPathComponent().lastPathComponent
        let title = String(format: KMLocalizedString("%@ (page %ld / %ld)", "Window title format"), fileName, pdfView.currentPageIndex+1, pdfView.document.pageCount)
        if(self.titleBack != nil) {
            self.titleBack!(title)
        }
    }
}