//
//  KMWatermarkAdjectiveTools.swift
//  PDF Reader Pro
//
//  Created by tangchao on 2022/12/27.
//

import Cocoa

enum KMWatermarkAdjectiveType: Int {
case watermark = 1
case background = 2
case headerfooter = 3
case bates = 4
}

@objc class KMWatermarkAdjectiveTools: NSObject {
    class func fetchAvailableFonts(_ size: CGFloat) -> [NSAttributedString] {
        let fonts = NSFontManager.shared.availableFontFamilies
        var result: Array<NSAttributedString> = []
        for fontName in fonts {
            let font = NSFont(name: fontName, size: size)
            let attribute = [NSAttributedString.Key.font : font]
            let string = NSAttributedString(string: fontName, attributes: attribute as [NSAttributedString.Key : Any])
            result.append(string)
        }
        
        return result
    }
    
    class func fontNameToAttribute(_ name: String, _ size: CGFloat) -> NSAttributedString? {
        let names = NSFontManager.shared.availableFontFamilies
        if (!names.contains(name)) {
            return nil
        }
        
        let font = NSFont(name: name, size: size)
        if (font == nil) {
            return nil
        }
        
        let attribute = [NSAttributedString.Key.font : font]
        return NSAttributedString(string: name, attributes: attribute as [NSAttributedString.Key : Any])
    }
    
    class func parseColor(color: NSColor) -> (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
        var red: CGFloat = 0.0
        var green: CGFloat = 0.0
        var blue: CGFloat = 0.0
        var alpha: CGFloat = 0.0
        color.usingColorSpaceName(NSColorSpaceName.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
        
        return (red, green, blue, alpha)
    }
    
    @objc class func getDateFormats() -> [String] {
        return ["m/d", "m/d/yy", "m/d/yyyy",
                "mm/dd/yy", "mm/dd/yyyy",
                "d/m/yy", "d/m/yyyy",
                "dd/mm/yy", "dd/mm/yyyy",
                "mm/yy", "mm/yyyy",
                "m.d.yy", "m.d.yyyy",
                "mm.dd.yy", "mm.dd.yyyy", "mm.yy", "mm.yyyy",
                "d.m.yy", "d.m.yyyy",
                "dd.mm.yy", "dd.mm.yyyy",
                "yy-mm-dd",
                "yyyy-mm-dd"]
    }
    
    class func getPageFormats() -> [String] {
        return ["1",
                "1 of n",
                "1/n",
                "Page 1",
                "Page 1 of n"]
    }
    
    class func parsePageFormat(formatString: String, startPage: String, pageCount: String) -> String {
        var result = formatString
        for pageFormat in self.getPageFormats() {
            let string = "<<\(pageFormat)>>"
            if (result.contains(string)) {
                var tempString = ""
                if (string == "<<1>>") {
                    tempString.append("<<\(startPage)>>")
                } else if (string == "<<1 of n>>") {
                    tempString.append("<<\(startPage)>>")
                    tempString.append(" of \(pageCount)")
                } else if (string == "<<1/n>>") {
                    tempString.append("<<\(startPage)>>")
                    tempString.append("/\(pageCount)")
                } else if (string == "<<Page 1>>") {
                    tempString.append("Page \(startPage)")
                } else if (string == "<<Page 1 of n>>") {
                    tempString.append("Page \(startPage)")
                    tempString.append("of \(pageCount)")
                }
                result = result.replacingOccurrences(of: string, with: tempString)
            }
        }
        
        return result
    }
    
    class func parseDateFormat(formatString: String) -> String {
        var result: String = formatString
        for dateFormat in self.getDateFormats() {
            if (result.contains(dateFormat)) {
                var formatString: String = dateFormat.replacingOccurrences(of: "m", with: "M")
                var replace = "<<\(dateFormat)>>"
                
                let date = Date()
                let dateFormatter = DateFormatter()
                dateFormatter.dateFormat = formatString
                var dateString = dateFormatter.string(from: date)
                result = result.replacingOccurrences(of: replace, with: dateString)
            }
        }
        return result
    }
    
    class func KMWatermarkAdjectiveType(from toolBarType: KMToolbarType) -> KMWatermarkAdjectiveType {
        if (toolBarType == .bates) {
            return .bates
        } else if (toolBarType == .headerAndFooter) {
            return .headerfooter
        } else if (toolBarType == .background) {
            return .background
        } else if (toolBarType == .watermark) {
            return .watermark
        }
        
        return .watermark
    }
    
    class func KMToolBarTypeToRightSubViewType(_ type: KMToolbarType) -> RightSubViewType {
        if (type == .bates) {
            return .Bates
        } else if (type == .headerAndFooter) {
            return .Headerfooter
        } else if (type == .background) {
            return .Background
        } else if (type == .watermark) {
            return .Watermark
        }
        
        return .None
    }
    
    // MARK: Apply
    class func apply(_ model: AnyObject, _ pdfView: CPDFView, _ toPath: String, completion: @escaping (_ result: Bool) -> ()) {
        if (model.isKind(of: KMHeaderFooterObject.self)) {
            KMWatermarkAdjectiveTools.applyBates(model as! KMHeaderFooterObject, pdfView, toPath, completion: completion)
        } else if (model.isKind(of: KMHeaderFooterObject.self)) {
            KMWatermarkAdjectiveTools.applyHeaderFooter(model as! KMHeaderFooterObject, pdfView, toPath, completion: completion)
        } else if (model.isKind(of: KMBackgroundModel.self)) {
            KMWatermarkAdjectiveTools.applyBackground(model as! KMBackgroundModel, pdfView, toPath, completion: completion)
        } else if (model.isKind(of: KMWatermarkModel.self)) {
            KMWatermarkAdjectiveTools.applyWatermark(model as! KMWatermarkModel, pdfView, toPath, completion: completion)
        }
    }
    
    class func delete(_ type: KMWatermarkAdjectiveType, _ pdfView: CPDFView, _ toPath: String, completion: @escaping (_ result: Bool) -> ()) {
        if (pdfView.document.allowsPrinting == false || pdfView.document.allowsCopying == false) {
            let alert = NSAlert()
            alert.alertStyle = .critical
            alert.messageText = NSLocalizedString("This PDF document's user permissions does not allow modifying, content copying and printing.", comment: "")
            alert.runModal()
            
            completion(false)
            return
        }
        
        DispatchQueue.global().async {
            let document: CPDFDocument = CPDFDocument(url: pdfView.document.documentURL)
            if (type == .bates) {
                let property = document.bates()
                property?.clear()
            } else if (type == .headerfooter) {
                let property = document.headerFooter()
                property?.clear()
            } else if (type == .background) {
                let property = document.background()
                property?.clear()
            } else if (type == .watermark) {
                let array: Array<CPDFWatermark> = document.watermarks()
                for model in array {
                    document.removeWatermark(model)
                }
            }

            /// 保存到临时路径
            let documentPath = NSTemporaryDirectory()
            let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)"
            if (FileManager.default.fileExists(atPath: tempPath)) {
                try?FileManager.default.removeItem(atPath: tempPath)
            }
            
            let result = document.write(to: URL(fileURLWithPath: tempPath))
            if (result) {
                if (FileManager.default.fileExists(atPath: toPath)) {
                    try?FileManager.default.removeItem(atPath: toPath)
                }
                
                try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath)
            } else {
                try?FileManager.default.removeItem(atPath: tempPath)
            }
            
            DispatchQueue.main.async {
                completion(result)
            }
        }
    }
    
    private class func applyBates(_ model: KMHeaderFooterObject, _ pdfView: CPDFView, _ toPath: String, completion: @escaping (_ result: Bool) -> ()) {
        DispatchQueue.global().async {
            let document: CPDFDocument = pdfView.document
            var property = document.bates()
            
            var fontSize = 0.0
            var fontName: String = ""
            switch model.textFont {
            case .font(name: let name, size: let size):
                fontName = name
                fontSize = size
                break
            default:
                break
            }
            
            let font = NSFont.boldSystemFont(ofSize:fontSize)
            let style = NSMutableParagraphStyle()
            style.alignment = .center
            style.lineBreakMode = .byCharWrapping
            let size: NSSize = "text".boundingRect(with: NSSize(width: 1000, height: 1000), options: NSString.DrawingOptions(rawValue: 3), attributes: [NSAttributedString.Key.font : font, NSAttributedString.Key.paragraphStyle : style]).size
            
            property?.margin = NSEdgeInsetsMake(max(CGFloat(model.topMargin)-size.height, 0), CGFloat(model.leftMargin), max(CGFloat(model.bottomMargin)-size.height, 0), CGFloat(model.rightMargin))
            
            let strings = [model.topLeftString, model.topCenterString, model.topRightString, model.bottomLeftString, model.bottomCenterString, model.bottomRightString]
            var count: Int = 0
            
            var color: NSColor!
            switch model.textColor {
            case .color(red: let red, green: let green, blue: let blue, alpha: let alpha):
                color = NSColor(red: red, green: green, blue: blue, alpha: alpha)
            default:
                break
            }
            
            if (color == nil) {
                color = NSColor.black
            }
            
            for text in strings {
                property?.setText(text, at: UInt(count))
                property?.setTextColor(color, at: UInt(count))
                property?.setFontSize(fontSize, at: UInt(count))
                property?.setFontName(fontName, at: UInt(count))
                count += 1
            }
            
            let pagesString = KMWatermarkAdjectiveTools.findPagesString(model)
            if (pagesString.isEmpty) {
                property?.pageString = "0-\(document.pageCount-1)"
            } else {
                property?.pageString = pagesString
            }
           
            property?.update()
            
            /// 保存到临时路径
            let documentPath = NSTemporaryDirectory()
            let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)"
            if (FileManager.default.fileExists(atPath: tempPath)) {
                try?FileManager.default.removeItem(atPath: tempPath)
            }
            
            let result = document.write(to: URL(fileURLWithPath: tempPath))
            if (result) {
                if (FileManager.default.fileExists(atPath: toPath)) {
                    try?FileManager.default.removeItem(atPath: toPath)
                }
                
                try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath)
            } else {
                try?FileManager.default.removeItem(atPath: tempPath)
            }
            
            DispatchQueue.main.async {
                completion(result)
            }
        }
    }
    
    private class func applyHeaderFooter(_ model: KMHeaderFooterObject, _ pdfView: CPDFView, _ toPath: String, completion: @escaping (_ result: Bool) -> ()) {
        DispatchQueue.global().async {
            let document: CPDFDocument = pdfView.document
            var property = document.headerFooter()
            
            var fontSize = 0.0
            var fontName: String = ""
            switch model.textFont {
            case .font(name: let name, size: let size):
                fontSize = size
                fontName = name
                break
            default:
                break
            }
            
            let font = NSFont.boldSystemFont(ofSize:fontSize)
            let style = NSMutableParagraphStyle()
            style.alignment = .center
            style.lineBreakMode = .byCharWrapping
            let size: NSSize = "text".boundingRect(with: NSSize(width: 1000, height: 1000), options: NSString.DrawingOptions(rawValue: 3), attributes: [NSAttributedString.Key.font : font, NSAttributedString.Key.paragraphStyle : style]).size
            
            property?.margin = NSEdgeInsetsMake(max(CGFloat(model.topMargin)-size.height, 0), CGFloat(model.leftMargin), max(CGFloat(model.bottomMargin)-size.height, 0), CGFloat(model.rightMargin))
            
            let strings = KMWatermarkAdjectiveTools.parseModel(model: model, pdfView.document.pageCount)
            var count: Int = 0
            
            var color: NSColor!
            switch model.textColor {
            case .color(red: let red, green: let green, blue: let blue, alpha: let alpha):
                color = NSColor(red: red, green: green, blue: blue, alpha: alpha)
            default:
                break
            }
            
            if (color == nil) {
                color = NSColor.black
            }
            
            for text in strings {
                property?.setText(text, at: UInt(count))
                property?.setTextColor(color, at: UInt(count))
                property?.setFontSize(fontSize, at: UInt(count))
                property?.setFontName(fontName, at: UInt(count))
                count += 1
            }
            let pagesString = KMWatermarkAdjectiveTools.findPagesString(model)
            if (pagesString.isEmpty) {
                property?.pageString = "0-\(document.pageCount-1)"
            } else {
                property?.pageString = pagesString
            }
            
            property?.update()
            
            /// 保存到临时路径
            let documentPath = NSTemporaryDirectory()
            let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)"
            if (FileManager.default.fileExists(atPath: tempPath)) {
                try?FileManager.default.removeItem(atPath: tempPath)
            }
            
            let result = document.write(to: URL(fileURLWithPath: tempPath))
            if (result) {
                if (FileManager.default.fileExists(atPath: toPath)) {
                    try?FileManager.default.removeItem(atPath: toPath)
                }
                
                try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath)
            } else {
                try?FileManager.default.removeItem(atPath: tempPath)
            }
            
            DispatchQueue.main.async {
                completion(result)
            }
        }
    }
    
    private class func applyBackground(_ model: KMBackgroundModel, _ pdfView: CPDFView, _ toPath: String, completion: @escaping (_ result: Bool) -> ()) {
        DispatchQueue.global().async {
            let document: CPDFDocument = pdfView.document
            var property = document.background()
            
            property!.scale = model.scale
            property!.rotation = CGFloat(-model.rotation)
            property!.opacity = model.opacity
            property?.xOffset = model.horizontalSpace
            property?.yOffset = model.verticalSpace
            property?.horizontalAlignment = UInt(model.horizontalMode)
            property?.verticalAlignment = UInt(model.verticalMode)
            
            if (model.type == .color) {
                property?.color = model.color
                property?.type = .color
            } else if (model.type == .file) {
                property?.setImage(NSImage(contentsOfFile: model.imagePath))
//                property?.setImage(model.image)
                property?.type = .image
            }
            property?.pageString = "0-\(document.pageCount-1)"
            property?.update()
            
            /// 保存到临时路径
            let documentPath = NSTemporaryDirectory()
            let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)"
            if (FileManager.default.fileExists(atPath: tempPath)) {
                try?FileManager.default.removeItem(atPath: tempPath)
            }
            
            let result = document.write(to: URL(fileURLWithPath: tempPath))
            if (result) {
                if (FileManager.default.fileExists(atPath: toPath)) {
                    try?FileManager.default.removeItem(atPath: toPath)
                }
                
                try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath)
            } else {
                try?FileManager.default.removeItem(atPath: tempPath)
            }
            
            DispatchQueue.main.async {
                completion(result)
            }
        }
    }
    
    private class func applyWatermark(_ model: KMWatermarkModel, _ pdfView: CPDFView, _ toPath: String, completion: @escaping (_ result: Bool) -> ()) {
        DispatchQueue.global().async {
            var property: CPDFWatermark!
            var scale: CGFloat = model.scale
            if (!model.text.isEmpty) {
                property = CPDFWatermark(document: pdfView.document, type: .text)
                property.text = model.text
                property.textColor = model.getTextColor()
                scale = model.getTextFontSize() / 24.0
            } else {
                property = CPDFWatermark(document: pdfView.document, type: .image)
                property.image = model.image
            }
            
            property.scale = scale
            property.rotation = -model.rotation
            property.opacity = model.opacity
            property.tx = model.horizontalSpace
            property.ty = model.verticalSpace
            property.isFront = model.isFront
            var pageString: String = ""
            if (model.pageRangeType == .all) {
                for i in 0 ..< pdfView.document.pageCount {
                    pageString.append("\(i)")
                    
                    if (i != pdfView.document.pageCount-1) {
                        pageString.append(",")
                    }
                }
            } else if (model.pageRangeType == .odd) {
                for i in 0 ..< pdfView.document.pageCount {
                    if (i % 2 == 0) {
                        pageString.append("\(i)")
                    } else {
                        continue
                    }
                    
                    if (i != pdfView.document.pageCount-1) {
                        pageString.append(",")
                    }
                }
            } else if (model.pageRangeType == .even) {
                for i in 0 ..< pdfView.document.pageCount {
                    if (i % 2 == 1) {
                        pageString.append("\(i)")
                    } else {
                        continue
                    }
                    
                    if (i != pdfView.document.pageCount-1) {
                        pageString.append(",")
                    }
                }
            } else {
                pageString = model.pagesString
            }
            property.pageString = pageString
            property.isTilePage = model.isTilePage
            property.horizontalSpacing = model.tileHorizontalSpace / scale
            property.verticalSpacing = model.tileVerticalSpace / scale
            if (model.verticalMode == 0) {
                property.verticalPosition = .top
            } else if (model.verticalMode == 1) {
                property.verticalPosition = .center
            } else if (model.verticalMode == 2) {
                property.verticalPosition = .bottom
            }
            
            if (model.horizontalMode == 0) {
                property.horizontalPosition = .left
            } else if (model.horizontalMode == 1) {
                property.horizontalPosition = .center
            } else if (model.horizontalMode == 2) {
                property.horizontalPosition = .right
            }
            model.watermark = property
            
            pdfView.document.addWatermark(property)
            
            /// 保存到临时路径
            let documentPath = NSTemporaryDirectory()
            let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)"
            if (FileManager.default.fileExists(atPath: tempPath)) {
                try?FileManager.default.removeItem(atPath: tempPath)
            }
            
            let result = pdfView.document.write(to: URL(fileURLWithPath: tempPath))
            if (result) {
                if (FileManager.default.fileExists(atPath: toPath)) {
                    try?FileManager.default.removeItem(atPath: toPath)
                }
                
                try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath)
            } else {
                try?FileManager.default.removeItem(atPath: tempPath)
            }
            
            DispatchQueue.main.async {
                completion(result)
            }
        }
    }
    
    // MARK: Add
    class func add(_ model: AnyObject, _ pdfView: CPDFView, completion: @escaping (_ result: Bool) -> ()) {
        if (model.isKind(of: KMHeaderFooterObject.self)) {
//            KMWatermarkAdjectiveTools.applyBates(model as! KMHeaderFooterObject, pdfView, toPath, completion: completion)
        } else if (model.isKind(of: KMHeaderFooterObject.self)) {
//            KMWatermarkAdjectiveTools.applyHeaderFooter(model as! KMHeaderFooterObject, pdfView, toPath, completion: completion)
        } else if (model.isKind(of: KMBackgroundModel.self)) {
//            KMWatermarkAdjectiveTools.applyBackground(model as! KMBackgroundModel, pdfView, toPath, completion: completion)
        } else if (model.isKind(of: KMWatermarkModel.self)) {
            KMWatermarkAdjectiveTools.addWatermark(model as! KMWatermarkModel, pdfView, completion: completion)
        }
    }
    
    private class func addWatermark(_ model: KMWatermarkModel, _ pdfView: CPDFView, completion: @escaping (_ result: Bool) -> ()) {
        DispatchQueue.global().async {
            var property: CPDFWatermark!
            var scale: CGFloat = model.scale
            if (!model.text.isEmpty) {
                property = CPDFWatermark(document: pdfView.document, type: .text)
                property.text = model.text
                property.textColor = model.getTextColor()
                scale = model.getTextFontSize() / 24.0
            } else {
                property = CPDFWatermark(document: pdfView.document, type: .image)
                property.image = model.image
            }
            
            property.scale = scale
            property.rotation = -model.rotation
            property.opacity = model.opacity
            property.tx = model.horizontalSpace
            property.ty = model.verticalSpace
            property.isFront = model.isFront
            var pageString: String = ""
            if (model.pageRangeType == .all) {
                for i in 0 ..< pdfView.document.pageCount {
                    pageString.append("\(i)")
                    
                    if (i != pdfView.document.pageCount-1) {
                        pageString.append(",")
                    }
                }
            } else if (model.pageRangeType == .odd) {
                for i in 0 ..< pdfView.document.pageCount {
                    if (i % 2 == 0) {
                        pageString.append("\(i)")
                    } else {
                        continue
                    }
                    
                    if (i != pdfView.document.pageCount-1) {
                        pageString.append(",")
                    }
                }
            } else if (model.pageRangeType == .even) {
                for i in 0 ..< pdfView.document.pageCount {
                    if (i % 2 == 1) {
                        pageString.append("\(i)")
                    } else {
                        continue
                    }
                    
                    if (i != pdfView.document.pageCount-1) {
                        pageString.append(",")
                    }
                }
            } else {
                pageString = model.pagesString
            }
            property.pageString = pageString
            property.isTilePage = model.isTilePage
            property.horizontalSpacing = model.tileHorizontalSpace / scale
            property.verticalSpacing = model.tileVerticalSpace / scale
            if (model.verticalMode == 0) {
                property.verticalPosition = .top
            } else if (model.verticalMode == 1) {
                property.verticalPosition = .center
            } else if (model.verticalMode == 2) {
                property.verticalPosition = .bottom
            }
            
            if (model.horizontalMode == 0) {
                property.horizontalPosition = .left
            } else if (model.horizontalMode == 1) {
                property.horizontalPosition = .center
            } else if (model.horizontalMode == 2) {
                property.horizontalPosition = .right
            }
            model.watermark = property
            
            let result = pdfView.document.addWatermark(property)
            DispatchQueue.main.async {
                completion(result)
            }
        }
    }
    
    // MARK: Update
    class func update(_ model: AnyObject, _ pdfView: CPDFView, completion: @escaping (_ result: Bool) -> ()) {
        if (model.isKind(of: KMHeaderFooterObject.self)) {
//            KMWatermarkAdjectiveTools.applyBates(model as! KMHeaderFooterObject, pdfView, toPath, completion: completion)
        } else if (model.isKind(of: KMHeaderFooterObject.self)) {
//            KMWatermarkAdjectiveTools.applyHeaderFooter(model as! KMHeaderFooterObject, pdfView, toPath, completion: completion)
        } else if (model.isKind(of: KMBackgroundModel.self)) {
//            KMWatermarkAdjectiveTools.applyBackground(model as! KMBackgroundModel, pdfView, toPath, completion: completion)
        } else if (model.isKind(of: KMWatermarkModel.self)) {
            KMWatermarkAdjectiveTools.updateWatermark(model as! KMWatermarkModel, pdfView, completion: completion)
        }
    }
    
    private class func updateWatermark(_ model: KMWatermarkModel, _ pdfView: CPDFView, completion: @escaping (_ result: Bool) -> ()) {
        DispatchQueue.global().async {
            var property: CPDFWatermark!
            var scale: CGFloat = model.scale
            if (!model.text.isEmpty) {
                property = CPDFWatermark(document: pdfView.document, type: .text)
                property.text = model.text
                property.textColor = model.getTextColor()
                scale = model.getTextFontSize() / 24.0
            } else {
                property = CPDFWatermark(document: pdfView.document, type: .image)
                property.image = model.image
            }
            
            property.scale = scale
            property.rotation = -model.rotation
            property.opacity = model.opacity
            property.tx = model.horizontalSpace
            property.ty = model.verticalSpace
            property.isFront = model.isFront
            var pageString: String = ""
            if (model.pageRangeType == .all) {
                for i in 0 ..< pdfView.document.pageCount {
                    pageString.append("\(i)")
                    
                    if (i != pdfView.document.pageCount-1) {
                        pageString.append(",")
                    }
                }
            } else if (model.pageRangeType == .odd) {
                for i in 0 ..< pdfView.document.pageCount {
                    if (i % 2 == 0) {
                        pageString.append("\(i)")
                    } else {
                        continue
                    }
                    
                    if (i != pdfView.document.pageCount-1) {
                        pageString.append(",")
                    }
                }
            } else if (model.pageRangeType == .even) {
                for i in 0 ..< pdfView.document.pageCount {
                    if (i % 2 == 1) {
                        pageString.append("\(i)")
                    } else {
                        continue
                    }
                    
                    if (i != pdfView.document.pageCount-1) {
                        pageString.append(",")
                    }
                }
            } else {
                pageString = model.pagesString
            }
            property.pageString = pageString
            property.isTilePage = model.isTilePage
            property.horizontalSpacing = model.tileHorizontalSpace / scale
            property.verticalSpacing = model.tileVerticalSpace / scale
            if (model.verticalMode == 0) {
                property.verticalPosition = .top
            } else if (model.verticalMode == 1) {
                property.verticalPosition = .center
            } else if (model.verticalMode == 2) {
                property.verticalPosition = .bottom
            }
            
            if (model.horizontalMode == 0) {
                property.horizontalPosition = .left
            } else if (model.horizontalMode == 1) {
                property.horizontalPosition = .center
            } else if (model.horizontalMode == 2) {
                property.horizontalPosition = .right
            }
            model.watermark = property
            let watermarks = pdfView.document.watermarks()
            if (watermarks != nil) {
                for i in 0 ..< watermarks!.count {
                    let watermark = watermarks![i]
                    pdfView.document.removeWatermark(watermark)
                }
            }
  
            let result = pdfView.document.addWatermark(property)
            DispatchQueue.main.async {
                completion(result)
            }
        }
    }
    
    private class func parseModel(model: KMHeaderFooterObject, _ pageCount: UInt) -> [String] {
        var topLeftString: String = ""
        if (!model.topLeftString.isEmpty) {
            var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.topLeftString, startPage: model.startString, pageCount: "\(pageCount)")
            string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string)
            topLeftString = string
        }
        
        var topCenterString: String = ""
        if (!model.topCenterString.isEmpty) {
            var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.topCenterString, startPage: model.startString, pageCount: "\(pageCount)")
            string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string)
            topCenterString = string
        }
        
        var topRightString: String = ""
        if (!model.topRightString.isEmpty) {
            var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.topRightString, startPage: model.startString, pageCount: "\(pageCount)")
            string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string)
            topRightString = string
        }
        
        var bottomLeftString: String = ""
        if (!model.bottomLeftString.isEmpty) {
            var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.bottomLeftString, startPage: model.startString, pageCount: "\(pageCount)")
            string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string)
            bottomLeftString = string
        }
        var bottomCenterString: String = ""
        if (!model.bottomCenterString.isEmpty) {
            var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.bottomCenterString, startPage: model.startString, pageCount: "\(pageCount)")
            string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string)
            bottomCenterString = string
        }
        var bottomRightString: String = ""
        if (!model.bottomRightString.isEmpty) {
            var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.bottomRightString, startPage: model.startString, pageCount: "\(pageCount)")
            string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string)
            bottomRightString = string
        }
        
        return [topLeftString, topCenterString, topRightString, bottomLeftString, bottomCenterString, bottomRightString]
    }
    
    class func findPagesString(_ model: KMWatermarkAdjectiveBaseModel) -> String{
        if (model.pageRangeType == .all) { /// 全部页面
            return "0-\(model.pageCount-1)"
        } else if (model.pageRangeType == .odd) { /// 奇数页面
            var string: String = ""
            for i in 0 ..< model.pageCount {
                if (i % 2 == 1) {
                    continue
                }
                
                string.append("\(i)")
                if (i != model.pageCount-1) {
                    string.append(",")
                }
            }
            return string
        } else if (model.pageRangeType == .even) { /// 偶数页面
            var string: String = ""
            for i in 0 ..< model.pageCount {
                if (i % 2 == 0) {
                    continue
                }
                
                string.append("\(i)")
                if (i != model.pageCount-1) {
                    string.append(",")
                }
            }
            return string
        } else { /// 自定义
            return model.pageRangeString
        }
    }
}