//
//  KMSignatureViewController.swift
//  PDF Reader Pro
//
//  Created by lxy on 2022/11/17.
//

import Cocoa

@objc protocol KMSignatureViewControllerDelegate {
    @objc optional func removeDocumentSignatues(signatures:[CPDFSignature])
}


class KMSignatureViewController: NSViewController {
    @IBOutlet weak var sigOutlineView: KMOutlineView!
    
    @IBOutlet weak var deleteButton: NSButton!
    @IBOutlet weak var validationButton: NSButton!
    @IBOutlet weak var tipTextField: NSTextField!
    @IBOutlet weak var emptyLabel: NSTextField!
    @IBOutlet weak var emptyView: NSView!
    var listView : CPDFListView!
    var signatures : [CPDFSignature] = []
    open weak var delete: KMSignatureViewControllerDelegate?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do view setup here.
        self.view.wantsLayer = true
        self.view.layer?.backgroundColor = NSColor.yellow.cgColor
        self.tipTextField.stringValue = NSLocalizedString("Digitally Sign", comment: "");
        self.deleteButton.toolTip = NSLocalizedString("Delete", comment: "");
        self.validationButton.toolTip = NSLocalizedString("Validate All Signatures", comment: "");
        self.emptyLabel.stringValue = NSLocalizedString("No digital signature was added", comment: "");

        let signatures : [CPDFSignature] = self.listView.document.signatures() ?? []
        var mSignatures : [CPDFSignature] = []
        for sign in signatures {
            if sign.signers.count > 0 {
                mSignatures.append(sign)
            }
        }
        self.signatures = mSignatures
        
        self.sigOutlineView.delegate = self
        self.sigOutlineView.dataSource = self
        let menu = NSMenu()
        menu.delegate = self
        self.sigOutlineView.menu = menu
        
        self.sigOutlineView.doubleAction = #selector(tableViewAction)
    }
        
    //MAAK: Accessors
    public func reloadData() {
        self.sigOutlineView.reloadData()
    }
    
    private func outlineForItem(item:Any) -> [Any] {
        var itemChildren : [Any] = []
        if  (item is String) && ((item as! String) == "") {
            if self.signatures.count > 0 {
                let lastSignates : CPDFSignature = self.signatures.last ?? CPDFSignature()
                if (lastSignates.permissions > 0) {
                    var mutableArr : [Any] = self.signatures
                    mutableArr.append("      \(NSLocalizedString("Already locked by", comment: ""))\(String(describing: lastSignates.fieldName))")
                    itemChildren = mutableArr
                } else {
                    itemChildren = self.signatures
                }
            } else {
                itemChildren = self.signatures
            }
        } else if (item is CPDFSignature) {
            itemChildren = (item as! CPDFSignature).numberOfChildren(document: self.listView.document)
        } else if (item is [String:Any]) {
            let key = (item as! [String:Any]).keys.first ?? ""
            itemChildren = (item as! [String:Any])[key] as! [Any]
        }
        return itemChildren
    }
    
    @IBAction func deleteButtonAction(_ sender: Any) {
        let alert = NSAlert()
        alert.alertStyle = .critical
        alert.messageText = NSLocalizedString("Are you sure you want to clear all signature fields in this document?", comment: "")
        alert.informativeText = NSLocalizedString("You cannot undo this operation.", comment: "")
        alert.addButton(withTitle: NSLocalizedString("Yes", comment: ""))
        alert.addButton(withTitle: NSLocalizedString("No", comment: ""))
        alert.beginSheetModal(for: self.view.window!, completionHandler: { result in
            if result != .OK {
              
            }
        })
    }
    
    @IBAction func validationButtonAction(_ sender: Any) {
        
    }
    
    @IBAction func jumpItemAction(item: NSMenuItem) {
        let indexSet : NSIndexSet = item.representedObject as! NSIndexSet
        let outlineItem  = self.sigOutlineView.item(atRow: indexSet.firstIndex)
        if outlineItem is CPDFSignature {
            let index: Int = Int((outlineItem as! CPDFSignature).pageIndex(with: listView.document))
            if self.listView.currentPageIndex != index {
                self.listView.go(toPageIndex: index, animated: true)
            }
        }
    }
    
    @IBAction func removeItemAction(item:NSMenuItem) {
        let index : NSIndexSet = item.representedObject as! NSIndexSet
        let outlineItem  = self.sigOutlineView.item(atRow: index.firstIndex)
        if outlineItem is CPDFSignature {
            let index: Int = Int((outlineItem as! CPDFSignature).pageIndex(with: listView.document))
            if self.listView.currentPageIndex != index {
                self.delete?.removeDocumentSignatues?(signatures: [outlineItem as! CPDFSignature])
            }
        }

    }
    
    @IBAction func validateItemAction(item:NSMenuItem) {
        let index : NSIndexSet = item.representedObject as! NSIndexSet
        let outlineItem  = self.sigOutlineView.item(atRow: index.firstIndex)
        if outlineItem is CPDFSignature {
         
        }

    }

    @IBAction func showItemAction(item:NSMenuItem) {
        let index : NSIndexSet = item.representedObject as! NSIndexSet
        let outlineItem  = self.sigOutlineView.item(atRow: index.firstIndex)
        if outlineItem is CPDFSignature {
            let index: Int = Int((outlineItem as! CPDFSignature).pageIndex(with: listView.document))
            if self.listView.currentPageIndex != index {
                
            }
        }

    }
    
    @IBAction func tableViewAction(sender:Any) {
        let row = self.sigOutlineView.clickedRow
        if (row >= 0) && (row < self.signatures.count) {
            let outlineItem : CPDFSignature = self.sigOutlineView.item(atRow: row) as! CPDFSignature
            let index: Int = Int((outlineItem).pageIndex(with: listView.document))
            if self.listView.currentPageIndex != index {
                
                if self.listView.currentPageIndex != index {
                    self.listView.go(toPageIndex: index, animated: true)
                }
            }
        }
    }
    
}

extension KMSignatureViewController : NSOutlineViewDelegate,NSOutlineViewDataSource {
    func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
        var count = self.outlineForItem(item: item ?? "").count
        if case Optional<Any>.none = item {
            if count > 0 {
                self.emptyView.isHidden = true
                self.deleteButton.isEnabled = true
                self.validationButton.isEnabled = true
            } else {
                self.emptyView.isHidden = false
                self.deleteButton.isEnabled = false
                self.validationButton.isEnabled = false
            }
        } else if item is [String:Any] {
            count = 1
        }
        return count
    }
    
    func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
        return self.outlineForItem(item: item ?? "")[index]
    }
    
    func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
        return self.outlineForItem(item: item).count > 0
    }
    
    func outlineView(_ outlineView: NSOutlineView, shouldShowOutlineCellForItem item: Any) -> Bool {
        return true
    }
    
    func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
        let cell : KMSignatureCellView = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "KMSignatureCellView"), owner: self) as! KMSignatureCellView
        var contentString = ""
        if item is CPDFSignature {
            let signer : CPDFSigner = (item as! CPDFSignature).signers.first ?? CPDFSigner()
            contentString = "\(NSLocalizedString("Signature by", comment: ""))\(signer.timestampSignature.name ?? "")"
            if signer.isSignVerified && signer.isCertTrusted {
                cell.signatureImageView.image = NSImage(named: "KMImageNameSigntureVerifySuccess")
            } else if signer.isSignVerified && !signer.isCertTrusted {
                cell.signatureImageView.image = NSImage(named: "KMImageNameSigntureVerifySuccess")
            } else {
                cell.signatureImageView.image = NSImage(named: "KMImageNameSigntureVerifySuccess")
            }
            cell.signatureImageView.isHidden = false
            cell.leftOffset.constant = 36
            cell.contenLabel.font = NSFont.systemFont(ofSize: 13)
        } else if item is String {
            cell.signatureImageView.isHidden = true
            cell.leftOffset.constant = 4
            cell.contenLabel.font = NSFont.systemFont(ofSize: 12)
            contentString = item as! String
        } else if item is [String:Any] {
            cell.signatureImageView.isHidden = true
            cell.leftOffset.constant = 4
            cell.contenLabel.font = NSFont.systemFont(ofSize: 12)
            contentString = (item as! [String:Any]).keys.first ?? ""
        }
        cell.contenLabel.stringValue = contentString
        return cell
    }
    
    func outlineView(_ outlineView: NSOutlineView, rowViewForItem item: Any) -> NSTableRowView? {
        let rowView = KMCustomTableRowView()
        return rowView
    }
    
    func outlineView(_ outlineView: NSOutlineView, heightOfRowByItem item: Any) -> CGFloat {
        var contentString = ""
        var font = NSFont.systemFont(ofSize: 12)
        if item is CPDFSignature {
            let signer = (item as! CPDFSignature).signers.first
            contentString = "\(NSLocalizedString("Signature by", comment: ""))\(String(describing: signer?.timestampSignature.name))"
            font = NSFont.systemFont(ofSize: 13)
        } else if (item is String){
            contentString = item as! String
        } else if (item is [String : Any]) {
            contentString = (item as! [String:Any]).keys.first ?? ""
        }
        
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineBreakMode = .byWordWrapping
        var attribute = [NSAttributedString.Key.font : font, NSAttributedString.Key.paragraphStyle : paragraphStyle]
        let rect = NSString(string: contentString).boundingRect(with: NSSize(width: outlineView.frame.size.width-20, height:CGFloat(MAXFLOAT)),options: NSString.DrawingOptions(rawValue: 3), attributes: attribute).size
        if(rect.height < 40) {
            return 40
        } else {
            return rect.height
        }
    }
    
    func outlineView(_ outlineView: NSOutlineView, shouldSelect tableColumn: NSTableColumn?) -> Bool {
        
        return true
    }
}

//MARK: NSMenuDelegate

extension KMSignatureViewController : NSMenuDelegate {
    func menuNeedsUpdate(_ menu: NSMenu) {
        menu.removeAllItems()
        let clickedRow = self.sigOutlineView.clickedRow
        let item = self.sigOutlineView.item(atRow: clickedRow)
        if clickedRow > 0 && (item is CPDFSignature) {
            var item = NSMenuItem()
            item = menu.addItem(withTitle: NSLocalizedString("Jump To The Signature Field", comment: ""), action: #selector(jumpItemAction), target: self)!
            item.representedObject = NSIndexSet(index: clickedRow)
            menu.addItem(NSMenuItem.separator())
            item = menu.addItem(withTitle: NSLocalizedString("Remove Signature", comment: ""), action: #selector(removeItemAction), target: self)!
            item.representedObject = NSIndexSet(index: clickedRow)
            item = menu.addItem(withTitle: NSLocalizedString("Remove Signature", comment: ""), action: #selector(validateItemAction), target: self)!
            item.representedObject = NSIndexSet(index: clickedRow)
            menu.addItem(NSMenuItem.separator())
            item = menu.addItem(withTitle: NSLocalizedString("Show Signature Properties…", comment: ""), action: #selector(showItemAction), target: self)!
            item.representedObject = NSIndexSet(index: clickedRow)
        }
    }
}

//MARK: CPDFSignature

extension CPDFSignature {
    func numberOfChildren(document:CPDFDocument) -> [Any] {
        var datas : [Any] = []
        let signer  = self.signers.first
        
        var validString = ""
        if signer?.isSignVerified != nil {
            validString = NSLocalizedString("Signature is valid", comment: "")
        } else {
            validString = NSLocalizedString("Signature is invalid", comment: "")
        }
        
        var certTrusted = ""
        if signer?.isCertTrusted != nil {
            certTrusted = NSLocalizedString("Signer's identity is valid", comment: "")
        } else {
            certTrusted = NSLocalizedString("Signer's identity is invalid", comment: "")
        }
        
        var timestampSigners = ""
        if signer?.timestampSignature.signers != nil {
            let tSign = signer?.timestampSignature.signers.first
            if tSign?.isSignVerified != nil && tSign?.isSignVerified != nil {
                timestampSigners = NSLocalizedString("The signature includes an embedded timestamp.", comment: "")
            } else {
                timestampSigners = NSLocalizedString("The signature includes an embedded timestamp but it could not be verified.", comment: "")
            }
        }
        
        var str3 = "\(validString)\n\n    \(certTrusted)"
        if timestampSigners.lengthOfBytes(using: String.Encoding(rawValue: String.Encoding.utf16.rawValue)) > 0 {
            str3 = "\(str3)\n\n    \(timestampSigners)"
        }
        datas.append(str3)
        
        var dic : [String:Any] = [:]
        let array = [NSLocalizedString("Certificate Details...", comment: ""),signer ?? CPDFSigner()] as [Any]
        dic[NSLocalizedString("Signature Details...", comment: "")] = array
        datas.append(dic)
        if signer?.timestampSignature.signers != nil && signer?.timestampSignature.signers.first?.authenDate != nil{
            var dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
            let strDate = dateFormatter.string(from: signer?.timestampSignature.signers.first?.authenDate ?? Date())
            datas.append("\(NSLocalizedString("Last Checked:", comment: ""))\(strDate)")
        } else {
            datas.append("\(NSLocalizedString("Last Checked:", comment: ""))\(NSLocalizedString("Never", comment: ""))")
        }
        let pageIndex = self.pageIndex(with: document)
        datas.append("\(NSLocalizedString("Field:", comment: ""))\(self.fieldName.description)\(NSLocalizedString("on Page", comment: ""))\(pageIndex+1)")
        return datas
    }
}