//
//  KMPrintPresenter.swift
//  PDF Reader Pro
//
//  Created by lizhe on 2022/12/21.
//

import Cocoa
import PDFKit

//MARK: CPDFKit page 方法无法使用 暂时使用系统方法
class KMPrintPresenter: NSObject {
    lazy var printData: KMPrintModel = KMPrintModel() {
        didSet {
            self.reloadData()
        }
    }
    var password: String = ""
    var document: CPDFDocument?
    fileprivate weak var delegate: KMPrintPresenterDeleage?
    
    /**
     初始化presenter 绑定数据
     */
    func initPresenter(delegate: KMPrintPresenterDeleage, data: KMPrintModel, document: CPDFDocument) {
        self.delegate = delegate
        self.document = document
        self.printData = data
        
//        DispatchQueue.main.async {
//            let pdfDocument = self.updatePrintDocument(documentURL: document.documentURL, data: self.printData)
//            self.printData.url = pdfDocument.documentURL
//        }
    }
    
    /**
     刷新数据
     */
    func reloadData() {
        guard let document = document else { return }
        let pdfDocument = self.updatePrintDocument(documentURL: document.documentURL, data: self.printData)
        self.printData.url = pdfDocument.documentURL
    }
    
    /**
     @abstract 解除绑定
     */
    func free() {
        delegate = nil
    }
}

protocol KMPrintPresenterDeleage: NSObject {
    func showData(presenter: KMPrintPresenter, document: PDFDocument)
}

protocol KMPrintPresenterDocument: NSObject {}
extension KMPrintPresenter: KMPrintPresenterDocument {
    /**
     @abstract 获取打印document
     @param url  源文件url
     @param data 数据
     @retrun document
     */
    func updatePrintDocument(documentURL: URL, data: KMPrintModel) -> PDFDocument {
        // 获取基本参数
        let printModel: KMPrintModel = data
        //获取总page
        let pages = self.fetchPages(documentURL, printModel.page)
        //绘制PDF
        let result = self.drawPages(nil, printModel, pages)
        
//        let result = CPDFDocument(url: URL(fileURLWithPath: filePath))!
        
        if self.delegate != nil {
            self.delegate?.showData(presenter: self, document: result)
        }
//        KMPrint("保存地址" + filePath)
        return result
     }
    
    /**
     @abstract 插入page
     @param paperSet  纸张设置
     @param pageSet page设置
     @param pages page数组
     */
    func drawPages(_ toFilePath: String?,
                   _ printModel: KMPrintModel,
                   _ pages: [KMPrintDrawPage]) -> PDFDocument {
        /**
         参数
         */
        //纸张大小
        let paperSize: CGSize = self.fetchPaperSize(printModel.paper)
        //总页数
        let paperCount: Int = self.fetchTotalPaperCount(paperSize, pages, printModel.page)
        //每页page数
        let pageOfPaperCount: Int = self.fetchPageOfPaper(printModel.page)
        //获取每张纸的page
        let drawPages: [KMPrintDrawPage] = self.fetchDrawPages(paperSize, printModel.page, paperCount, pageOfPaperCount, pages)
        //导出地址
        let filePath = KMPrintPresenter.fetchSaveFilePath(toFilePath)
        
        
        //方法一
        let tempDocument = PDFDocument()
        for i in 0..<drawPages.count {
            let page = drawPages[i]
            page.drawPageBlock = { [unowned self] box, context, pages in
                self.drawPageToContext(context, page, printModel)
            }
            tempDocument.insert(page, at: i)
        }
        
        return tempDocument
//        let isSuccess = tempDocument.write(toFile: filePath)
//        if isSuccess {
//            print("保存成功")
//        } else {
//            print("保存失败")
//        }
        
        /**
         //方法二
         /**
          绘制每张纸的内容
          */
         //创建画布
         let context: CGContext = self.createContext(filePath, paperSize)
         for drawPage in drawPages {
             context.beginPDFPage(nil)
             self.drawPageToContext(context, drawPage, printModel)
             context.endPDFPage()
         }
         context.closePDF()
         */
        
//        return filePath
    }
    
    
    /**
     获取绘制的pages
     @pageModel page参数
     @param paperCount 纸张数量
     @param pageOfPaperCount 每张纸的page数量
     @param pages 所有page数量
     */
    func fetchDrawPages(_ paperSize: CGSize, _ pageModel: KMPrintPageModel,_ paperCount: Int, _ pageOfPaperCount: Int, _ pages: [KMPrintDrawPage]) -> [KMPrintDrawPage] {
        guard pages.count != 0 else {
            return []
        }
        
        //一个page重复获取次数
        var pageRepetitionCount = 1
        if (pageModel.operation.type == .poster) {
            if (pageModel.operation.poster.type == .tile) {
                pageRepetitionCount = Int(pageModel.operation.poster.tilePoint.x * pageModel.operation.poster.tilePoint.y)
            } else if (pageModel.operation.poster.type == .breakUp) {
                pageRepetitionCount = Int(pageModel.operation.pageOfPaper.point.x * pageModel.operation.pageOfPaper.point.y)
            }
        }
        
        var drawPages:[KMPrintDrawPage] = []
        for i in 0..<paperCount {
            //获取多页page
            var tempPags: [KMPrintDrawPage] = []
            if pageModel.operation.type == .pamphlet {
                var currentPage = i
                var pageCount = paperCount
                
                if pageModel.operation.pamphlet.type == .onlyBack {
                    currentPage = currentPage * 2 + 1
                    pageCount = pageCount * 2
                } else if pageModel.operation.pamphlet.type == .onlyPositive {
                    currentPage = currentPage * 2
                    pageCount = pageCount * 2
                }
                
                let count = pageCount * pageOfPaperCount
                let pagesCount = pages.count
                var page = KMPrintDrawPage()
                var page2 = KMPrintDrawPage()
                
                //第一页
                let index = count - (currentPage + 1)
                if index < pagesCount {
                    page = pages[index]
                }
                
                //第二页
                let index2 = currentPage
                if index2 < pagesCount && index2 >= 0 {
                    page2 = pages[index2]
                }

                if currentPage % 2 != 0 {
                    let temp = page2
                    page2 = page
                    page = temp
                }
                
                if pageModel.operation.pamphlet.bookbindingType == .left ||
                    pageModel.operation.pamphlet.bookbindingType == .leftHigh {

                } else {
                    let temp = page2
                    page2 = page
                    page = temp
                }
                
                let pageCropRect = self.fetchPageCropRect(paperSize,i % pageRepetitionCount, pageModel, page)
                let pageShowRect = pageCropRect
                page.cropRect = pageCropRect
                page.showRect = pageShowRect
                tempPags.append(page)
                
                let pageCropRect2 = self.fetchPageCropRect(paperSize,i % pageRepetitionCount, pageModel, page2)
                let pageShowRect2 = pageCropRect
                page2.cropRect = pageCropRect2
                page2.showRect = pageShowRect2
                tempPags.append(page2)
                
                let drawPage = KMPrintDrawPage()
                drawPage.pages = tempPags
                drawPages.append(drawPage)
            } else {
                for j in 0..<pageOfPaperCount {
                    let pageIndex = i / pageRepetitionCount
                    if (pageIndex * pageOfPaperCount + j < pages.count) {
                        let originDrawPage = (pages[pageIndex * pageOfPaperCount + j])
                        let drawPage = KMPrintDrawPage()
                        drawPage.page = originDrawPage.page
                        var pageCropRect = self.fetchPageCropRect(paperSize,i % pageRepetitionCount, pageModel, drawPage)
                        var pageShowRect = pageCropRect
                        if (pageModel.operation.type == .poster) {
                            if (pageModel.operation.poster.type == .tile) {
                                pageShowRect = self.fetchPageShowRect(paperSize, i % pageRepetitionCount, pageModel, drawPage)
                            } else if (pageModel.operation.poster.type == .breakUp) {
                                pageShowRect = pageCropRect
                            }
                        }
                        drawPage.cropRect = pageCropRect
                        drawPage.showRect = pageShowRect
                        tempPags.append(drawPage)
                    }
                }
                let drawPage = KMPrintDrawPage()
                drawPage.pages = tempPags
                drawPages.append(drawPage)
            }
        }
        
        return drawPages
    }
    
    /**
     获取pages
     @param type 页面类型
     @param contentType annoation类型
     @param selectPages 当type 为custom时  传入选中page的下标
     */
    static func fetchSaveFilePath(_ filePath: String?) -> String {
        var saveFilePath = filePath ?? ""
        if saveFilePath.count == 0 {
            saveFilePath = NSTemporaryDirectory() + "/PDFReaderProTest/test2.pdf"
        }
        
        if !FileManager.default.fileExists(atPath: NSTemporaryDirectory() + "/PDFReaderProTest") {
            try?FileManager.default.createDirectory(atPath: NSTemporaryDirectory() + "/PDFReaderProTest", withIntermediateDirectories: true)
        }
        
        if FileManager.default.fileExists(atPath: saveFilePath) {
            try?FileManager.default.removeItem(atPath: saveFilePath)
        }
        
        return saveFilePath
    }
    
    /**
     获取pages
     @param type 页面类型
     @param contentType annoation类型
     @param selectPages 当type 为custom时  传入选中page的下标
     */
    static func creatDocument(_ url: URL) -> CPDFDocument {
        if !FileManager.default.fileExists(atPath: url.path) {
            FileManager.default.createFile(atPath: url.path, contents: nil)
        }
        
        
        let document = CPDFDocument(url: url)!
//        document.importPages(IndexSet(integer: 0), from: document, at: 0)
        let count = document.pageCount
        for _ in 0..<count {
            document.removePage(at: 0)
        }
        return document
    }
    
    
    /**
     获取pages
     @param type 页面类型
     @param contentType annoation类型
     @param selectPages 当type 为custom时  传入选中page的下标
     */
    func fetchPages(_ documentURL: URL, _ pageModel: KMPrintPageModel) -> [KMPrintDrawPage] {
//        let document = CPDFDocument.init(url: documentURL)!
        let document = PDFDocument.init(url: documentURL)!
        document.unlock(withPassword: password)
        var pageIndexs: [Int] = []
        let range = pageModel.range
        let contentType = pageModel.contentType
        let reversePrintOrder = range.reversePrintOrder
        
        switch range.type {
        case .allPage:
            for index in 0...document.pageCount - 1 {
                pageIndexs.append(Int(index))
            }
    
        case .evenPage:
            for index in 0...document.pageCount - 1 {
                if index % 2 == 0 {
                    pageIndexs.append(Int(index))
                }
            }
            
        case .oddPage:
            for index in 0...document.pageCount - 1 {
                if index % 2 != 0 {
                    pageIndexs.append(Int(index))
                }
            }
            
        case .currentPage:
            pageIndexs.append(0)
            
        case .custom:
            pageIndexs.append(0)
            
        default:
            pageIndexs.append(0)
        }
        
        var pagesArray: [KMPrintDrawPage] = []
        for index in pageIndexs {
            let page = document.page(at: index)!
            let drawPage = KMPrintDrawPage()
            drawPage.page = page
            self.dealPageContent(contentType, [drawPage])
            if reversePrintOrder {
                pagesArray.insert(drawPage, at: 0)
            } else {
                pagesArray.append(drawPage)
            }
        }
        
        return pagesArray
    }
    
    /**
     处理page annoation 内容
     @param contentType annoation类型
     @param pages page
     */
    func dealPageContent (_ contentType: KMPrintContentType, _ pages: [KMPrintDrawPage]) -> Void {
        for page in pages {
//            let annoations: [CPDFAnnotation] = page.page.annotations
            let annoations: [PDFAnnotation] = page.page.annotations
            //内容处理
            switch contentType {
            case .document:
                for annoation in annoations {
                    annoation.page!.removeAnnotation(annoation)
                }
            case .documentAndStamp:
                for annoation in annoations {
                    if !self.isAnnoationStamp(type: annoation.type!) {
                        annoation.page!.removeAnnotation(annoation)
                    }
                }
            case .documentAndMarkup:
                for annoation in annoations {
                    if !self.isAnnoationMarkup(type: annoation.type!) {
                        annoation.page!.removeAnnotation(annoation)
                    }
                }
            case .documentAndForm:
                for annoation in annoations {
                    if !self.isAnnoationForm(type: annoation.type!) {
                        annoation.page!.removeAnnotation(annoation)
                    }
                }
            default:
                KMPrint("未找到")
                break
            }
        }
    }
    
    /**
     @abstract 获取context
     @param size纸张大小
     */
    func createContext(_ saveFilePath: String, _ size: CGSize) ->  CGContext {
        var mediaBox: CGRect = NSMakeRect(0, 0, size.width, size.height)
        let url = CFURLCreateWithFileSystemPath(nil, saveFilePath as CFString, .cfurlposixPathStyle, false)
        let content: CGContext = CGContext.init(url!, mediaBox: &mediaBox, nil)!
        return content
    }
    
    /**
     @abstract 绘制page
     @param context
     @pages page数组 [CPDFPage]
     */
    func drawPageToContext(_ context: CGContext, _ drawPage: KMPrintDrawPage, _ data: KMPrintModel, _ drawPageRect: CGRect = NSZeroRect) {
        //左下角有坐标系原点
        /**
         paper
         */
        let paperSize: CGSize = self.fetchPaperSize(data.paper)//纸张大小
        let paperItemSize: CGSize = self.fetchPaperItemSize(data.paper) //页面paper大小(去除边框)
        let paperInset: NSEdgeInsets = data.paper.info.inset //绘制paper大小
        let border: Bool = data.page.operation.multipage.isBorder //是否存在边框
        
        /**
         page
         */
        let pageOrder: KMPrintPageOperation.Multipage.Order = .horizontal //页面顺序
        let pageSize: CGSize = self.fetchPageItemSize(data.page, paperItemSize) //page大小
        let showModel: KMPrintPageOperation.Size = self.fetchShowModel(data.page)
        let autoRotate = self.fetchAutoRotate(data.page)
        let autoSize: Bool = self.fetchAutoSize(data.page)
        
        //行列
        let columnAndRow = self.fetchPageColumnAndRow(data.page) //行 列数量
        let columnAndRowSpace = CGPoint(x: data.page.operation.multipage.lineSpacing, y: data.page.operation.multipage.columnsSpacing) //行 列之间的空间

        for i in 0..<Int(columnAndRow.x) {
            for j in 0..<(Int(columnAndRow.y)) {
                let index = j + i * Int(columnAndRow.y)
                if index < drawPage.pages.count {
                    //参数
                    let page: KMPrintDrawPage = drawPage.pages[index]
                    let rect = page.showRect
                    //裁剪当前Page
                    page.page.setBounds(page.cropRect, for: .cropBox)
                    let pageItemSize = rect.size
                    let rotate = page.page.rotation
                    var scale = self.fetchPageScale(page, pageSize, autoRotate, autoSize)
                    if data.page.operation.type == .size {
                        if showModel.model == .custom {
                            scale *= showModel.scale
                        } else if showModel.model == .full {
                            scale = 1
                        }
                    } else if (data.page.operation.type == .poster) {
                        if (data.page.operation.poster.type == .tile) {
                            scale = data.page.operation.poster.scale
                        }
                    } else if (data.page.operation.type == .pamphlet) {
                        let margin = data.page.operation.pamphlet.margin
                        let tempSize = CGSizeMake((pageSize.width - margin) / 2, pageSize.height)
                        scale = min(tempSize.width / pageSize.width, tempSize.height / pageSize.height)
                    }

                    //当前item的自身中心点
                    let center = CGPoint(x: (pageSize.width - pageItemSize.width * scale) / 2.0 ,
                                         y: (pageSize.height - pageItemSize.height * scale) / 2.0)
                    var origin = rect.origin

                    //多页Page自动旋转
//                    if autoSize {
                        switch pageOrder {
                        case .horizontal:
                            origin.x = (pageSize.width + columnAndRowSpace.x) * CGFloat(i) + paperInset.left + center.x
                            //页面内容高度 + 下边的行间距 - 第几个cell的高度 +居中
                            origin.y = paperSize.height - (pageSize.height + columnAndRowSpace.y) * (CGFloat(j) + 1) + center.y  + columnAndRowSpace.y
                        case .horizontalReverseSequence:
                            origin.x = paperSize.width - (pageSize.width + columnAndRowSpace.x) * (CGFloat(i) + 1) + center.x + columnAndRowSpace.x
                            origin.y = paperSize.height - (pageSize.height + columnAndRowSpace.y) * (CGFloat(j) + 1) + center.y + paperInset.bottom + columnAndRowSpace.y
                        case .vertical:
                            origin.x = (pageSize.width + columnAndRowSpace.x)  * CGFloat(i) + paperInset.left + center.x
                            origin.y = paperSize.height - (pageSize.height + columnAndRowSpace.y) * (CGFloat(j) + 1) + center.y + paperInset.bottom + columnAndRowSpace.y
                        case .verticalReverseSequence:
                            origin.x = paperSize.width - (pageSize.width + columnAndRowSpace.x) * (CGFloat(i) + 1) + center.x + columnAndRowSpace.x
                            origin.y = paperSize.height - (pageSize.height + columnAndRowSpace.y) * (CGFloat(j) + 1) + center.y + paperInset.bottom + columnAndRowSpace.y
                        default:
                            KMPrint("未找到")
                            break
                        }
//                    }
                    
                    NSGraphicsContext.current = NSGraphicsContext(cgContext: context, flipped: false)
                    NSGraphicsContext.saveGraphicsState()
                    //平移
                    context.translateBy(x: origin.x, y: origin.y)
                    //缩放
                    context.scaleBy(x: CGFloat(scale), y: CGFloat(scale))
                    
//                    page.page.draw(with: CPDFDisplayBox.cropBox, to: context)
//                    page.page.transform(context, for: CPDFDisplayBox.cropBox)
                    page.page.draw(with: PDFDisplayBox.cropBox, to: context)
                    page.page.transform(context, for: PDFDisplayBox.cropBox)
                    if border {
                        var dirtyRect = rect
                    //CGRectMake(origin.x, origin.y, 100, 100)
                        if rotate == 90 ||
                            rotate == 270 {
                            dirtyRect = NSMakeRect(dirtyRect.origin.x, dirtyRect.origin.y, dirtyRect.size.height, dirtyRect.size.width)
                        }

                        context.addRect(dirtyRect)
                    context.setStrokeColor(red: 0, green: 0, blue: 0, alpha: 1.0)
                        context.strokePath()
                    }
                    NSGraphicsContext.restoreGraphicsState()
//                        page.setBounds(NSRect(x: 0, y: 0, width: pageRect.size.width, height: pageRect.size.height), for: .cropBox)
                }
            }
        }
    }
    
    func drawLabelTextContextSize(context: CGContext) {
        let pageSize = CGSize(width: 0, height: 0)
        let KBlankA4W = pageSize.width
        let KBlankA4H = pageSize.height
        
        var contextString: String
//        if let labelString = PDFPrint.labelString, !labelString.isEmpty {
//            contextString = labelString
//        } else {
            let date = Date()
            let formatter = DateFormatter()
            formatter.dateFormat = "YYYY-MM-dd hh:mm:ss"
        contextString = "(\("1"),\("1")) \("filePath.lastPathComponent") \(formatter.string(from: date))"
//        }
        
        let fontSize = 12.0 * (max(KBlankA4W, KBlankA4H) / 842)
        let font = NSFont.systemFont(ofSize: fontSize)
        let color = NSColor.black
        
        var size = NSSize.zero
        var style = NSMutableParagraphStyle()
        style.alignment = .center
        style.lineBreakMode = .byCharWrapping
        var attributes = [NSAttributedString.Key: Any]()
        attributes[.paragraphStyle] = style
        attributes[.foregroundColor] = color
        attributes[.font] = font
        size = contextString.boundingRect(with: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude),
                                          options: [.usesLineFragmentOrigin, .usesFontLeading],
                                          attributes: attributes).size
        
//        if PDFPrint.splitType == .pageNumber {
            contextString.draw(in: CGRect(x: 10 + 10,
                                          y: KBlankA4H - 10 + size.height,
                                          width: size.width, height: size.height),
                                withAttributes: attributes)
//        } else {
//            contextString.draw(in: CGRect(x: PDFPrint.edgeInsets.left + 10,
//                                          y: KBlankA4H - PDFPrint.edgeInsets.top + size.height,
//                                          width: size.width, height: size.height),
//                                withAttributes: attributes)
//        }
    }

}

protocol KMPrintPresenterPage {}
extension KMPrintPresenter: KMPrintPresenterPage {
    /**
     获取pages
     @param type 页面类型
     @param contentType annoation类型
     @param selectPages 当type 为custom时  传入选中page的下标
     */
    func fetchPageCropRect(_ paperSize: CGSize, _ index: Int, _ pageModel: KMPrintPageModel, _ page: KMPrintDrawPage) -> CGRect {
        var newRect = page.page.bounds(for: .cropBox)
        if (pageModel.operation.type == .poster) {
            let originSize = newRect.size
            var cropPoint = CGPoint(x: 1, y: 1)
            var scale = 1.0
            if (pageModel.operation.poster.type == .tile) {
                cropPoint = pageModel.operation.poster.tilePoint
//                scale = pageModel.operation.poster.scale
            } else if (pageModel.operation.poster.type == .breakUp) {
                cropPoint = pageModel.operation.pageOfPaper.point
            }
            let width = originSize.width / cropPoint.x
            let height = originSize.height / cropPoint.y
            let column: Int = Int(cropPoint.x) //行
            let row: Int = Int(cropPoint.y) //列
            
            for i in 0...column - 1 {
                for j in 0...row - 1 {
                    if i + j + i * (row - 1) == index {
                        newRect.origin.x = CGFloat(i) * width * scale
                        newRect.origin.y = ((originSize.height - CGFloat(j) * height - height)) * scale
                        newRect.size.width = width * scale
                        newRect.size.height = height * scale
                        return newRect
                    }
                }
            }
        }
        return newRect
    }
    
    func fetchPageShowRect(_ paperSize: CGSize, _ index: Int, _ pageModel: KMPrintPageModel, _ page: KMPrintDrawPage) -> CGRect {
        var newRect = NSZeroRect
        var pageRect = CGRect(x: 0, y: 0, width: paperSize.width, height: paperSize.height)
        if (pageModel.operation.type == .poster) {
            let pageSize = page.page.bounds(for: .cropBox)
            var cropPoint = CGPoint(x: 1, y: 1)
            var scale = 1.0
            if (pageModel.operation.poster.type == .tile) {
                cropPoint = pageModel.operation.poster.tilePoint
                scale = pageModel.operation.poster.scale
            } else if (pageModel.operation.poster.type == .breakUp) {
                cropPoint = pageModel.operation.pageOfPaper.point
            }
            if (cropPoint.x == 1 && cropPoint.y == 1) {
                
            } else {
                let originPaperSize = CGSize(width: paperSize.width * cropPoint.x, height: paperSize.height * cropPoint.y)
                
                let pageWidth = pageSize.width * scale
                let pageHeight = pageSize.height * scale
                let pageOrigin = CGPoint(x: (originPaperSize.width - pageWidth) / 2, y: (originPaperSize.height - pageHeight) / 2)
                
                let width = originPaperSize.width / cropPoint.x
                let height = originPaperSize.height / cropPoint.y
                let column: Int = Int(cropPoint.x) //行
                let row: Int = Int(cropPoint.y) //列
                
                for i in 0...column - 1 {
                    for j in 0...row - 1 {
                        if i + j + i * (row - 1) == index {
                            newRect.origin.x = CGFloat(i) * width
                            newRect.origin.y = ((originPaperSize.height - CGFloat(j) * height - height))
                            newRect.size.width = width
                            newRect.size.height = height
                            
                            if (pageOrigin.x > newRect.origin.x) {
                                pageRect.origin.x = pageOrigin.x
                                pageRect.size.width = newRect.size.width - pageOrigin.x
                                
                            } else if (originPaperSize.width - pageOrigin.x > newRect.origin.x) {
                                pageRect.origin.x = 0
                                pageRect.size.width = newRect.size.width - pageOrigin.x
                            } else {
                                pageRect.origin.x = 0
                                pageRect.size.width = newRect.size.width
                            }
                            
                            if (originPaperSize.height - pageOrigin.y < newRect.origin.y + newRect.size.height) {
                                pageRect.origin.y = 0
                                pageRect.size.height = newRect.size.height - pageOrigin.y
                            } else if (pageOrigin.y > newRect.origin.y) {
                                pageRect.origin.y = pageOrigin.y
                                pageRect.size.height = newRect.size.height - pageOrigin.y
                            } else {
                                pageRect.origin.y = newRect.origin.y - pageOrigin.y
                                pageRect.size.height = newRect.size.height
                            }
                            return pageRect
                        }
                    }
                }
            }
        }
        return pageRect
    }
    
    func fetchPageColumnAndRow(_ pageModel: KMPrintPageModel) -> CGPoint {
        var point = NSZeroPoint
        let pageOrder: KMPrintPageOperation.Multipage.Order = pageModel.operation.multipage.orderType //页面顺序
        
        switch pageModel.operation.type {
        case .multipage:
            point.x = pageModel.operation.pageOfPaper.point.x
            point.y = pageModel.operation.pageOfPaper.point.y
        case .pamphlet:
            point.x = 1
            point.y = 2
        default:
            point.x = 1
            point.y = 1
        }
        
        //如果是横向参数需切换
        if pageOrder == .horizontal ||
            pageOrder == .horizontalReverseSequence {
            let temp = point.x
            point.x = point.y
            point.y = temp
        }
        
        return point
    }
    
    func fetchAutoRotate(_ pageModel: KMPrintPageModel) -> Bool  {
        var autoRotate = false
        switch pageModel.operation.type {
        case .multipage:
            autoRotate = pageModel.operation.isAutoRotate
        case .pamphlet:
            autoRotate = pageModel.operation.isAutoRotate
        default:
            autoRotate = false
        }
        return autoRotate
    }
    
    func fetchAutoSize(_ pageModel: KMPrintPageModel) -> Bool  {
        var autoSize = false
        switch pageModel.operation.type {
        case .size:
            autoSize = true
        default:
            autoSize = false
        }
        return autoSize
    }
    
    func fetchShowModel(_ pageModel: KMPrintPageModel) -> KMPrintPageOperation.Size {
        var model = KMPrintPageOperation.Size()
        switch pageModel.operation.type {
        case .size:
            model = pageModel.operation.size
        default:
            model = KMPrintPageOperation.Size()
        }
        return model
    }
    
    func fetchPageItemSize(_ pageModel: KMPrintPageModel, _ paperSize: CGSize) -> CGSize {
        var size = NSZeroSize
        let columnAndRow = self.fetchPageColumnAndRow(pageModel) //行 列数量
        let lineSpacing = pageModel.operation.multipage.lineSpacing
        let columnsSpacing = pageModel.operation.multipage.columnsSpacing
        let columnAndRowSpace = CGPoint(x: lineSpacing, y: columnsSpacing) //行 列之间的空间
        
        //page大小
        if pageModel.operation.type == .multipage {
            size = CGSize(width: (paperSize.width - CGFloat((columnAndRow.x - 1)) * CGFloat(columnAndRowSpace.x)) / columnAndRow.x,
                          height: (paperSize.height - CGFloat((columnAndRow.y - 1)) * CGFloat(columnAndRowSpace.y)) / columnAndRow.y)
        } else {
            size = CGSize(width: (paperSize.width - CGFloat((columnAndRow.x - 1)) * CGFloat(columnAndRowSpace.x)) / columnAndRow.x,
                          height: (paperSize.height - CGFloat((columnAndRow.y - 1)) * CGFloat(columnAndRowSpace.y)) / columnAndRow.y)
        }
        return size
    }
    
    func fetchPageScale(_ page: KMPrintDrawPage, _ pageItemSize: CGSize, _ autoRotate: Bool, _ autoSize: Bool) -> CGFloat {
        var scale = 1.0
        let originSize = page.page.bounds(for: .cropBox)
        var rotate = page.page.rotation
        //取出page横竖时能显示的最大Rect
        if autoRotate {
            //page旋转度数为0度或者180度时,在指定的大小内,能显示的比例
            let scale1 = min(pageItemSize.width / originSize.width, pageItemSize.height / originSize.height)
            //page旋转度数为90度或者270度时,在指定的大小内,能显示的比例
            let scale2 = min(pageItemSize.width / originSize.height, pageItemSize.height / originSize.width)
            scale = max(scale1, scale2)
            
            if scale1 > scale2 {
                //高为竖直排列时,显示最大,则需将page时90度或者270度需要进行旋转
                if rotate == 90 || rotate == 270 {
                    rotate = rotate - 90
                }
            } else {
                //宽为竖直排列时,显示最大,则需将page时0度或者180度需要进行旋转
                if rotate == 0 || rotate == 180 {
                    rotate = rotate - 90
                }
            }
        } else {
            scale = min(pageItemSize.width / originSize.width, pageItemSize.height / originSize.height)
        }
        
        if (autoSize) {
            
        } else {
            scale = min(scale, 1)
        }
            
        return scale
    }
    
    func fetchPageRotate(_ page: KMPrintDrawPage, _ pageItemSize: CGSize, _ autoRotate: Bool) -> CGFloat {
        var scale = 1.0
        let originSize = page.page.bounds(for: .cropBox)
        var rotate = page.page.rotation
        //取出page横竖时能显示的最大Rect
        if autoRotate {
            //page旋转度数为0度或者180度时,在指定的大小内,能显示的比例
            let scale1 = min(pageItemSize.width / originSize.width, pageItemSize.height / originSize.height)
            //page旋转度数为90度或者270度时,在指定的大小内,能显示的比例
            let scale2 = min(pageItemSize.width / originSize.height, pageItemSize.height / originSize.width)
            scale = max(scale1, scale2)
            
            if scale1 > scale2 {
                //高为竖直排列时,显示最大,则需将page时90度或者270度需要进行旋转
                if rotate == 90 || rotate == 270 {
                    rotate = rotate - 90
                }
            } else {
                //宽为竖直排列时,显示最大,则需将page时0度或者180度需要进行旋转
                if rotate == 0 || rotate == 180 {
                    rotate = rotate - 90
                }
            }
        } else {
            scale = min(pageItemSize.width / originSize.width, pageItemSize.height / originSize.height)
        }
            
        return scale
    }
    
    func fetchPageLite(pageModel: KMPrintPageModel) {
        
    }
}

protocol KMPrintPresenterPaper {}
extension KMPrintPresenter: KMPrintPresenterPaper {
    /**
     获取每张纸的page
     @param type 页面类型
     @param contentType annoation类型
     @param selectPages 当type 为custom时  传入选中page的下标
     */
    func fetchPageOfPaper(_ pageModel: KMPrintPageModel) -> Int {
        var count = 1
        switch pageModel.operation.type {
            case .multipage:
                count = Int(pageModel.operation.pageOfPaper.point.x * pageModel.operation.pageOfPaper.point.y)
            case .poster:
                count = Int(pageModel.operation.pageOfPaper.point.x * pageModel.operation.pageOfPaper.point.y)
            case .pamphlet:
                count = 2
            default:
                count = 1
        }
        return count
    }
    
    /**
     获取总纸张数
     @param pages page总数
     @param contentType annoation类型
     @param selectPages 当type 为custom时  传入选中page的下标
     */
    func fetchTotalPaperCount (_ paperSize: CGSize, _ pages: [KMPrintDrawPage], _ pageModel: KMPrintPageModel) -> Int {
        var count = 1
        let pageOfPaper = self.fetchPageOfPaper(pageModel)
        switch pageModel.operation.type {
        case .multipage:
            count = Int(ceilf(Float(pages.count / pageOfPaper)))
        case .poster:
            if (pageModel.operation.poster.type == .tile) {
                //1 2 4 9 16
                let scale = pageModel.operation.poster.scale
                let pageSize = pages.first?.page.bounds(for: .cropBox).size ?? paperSize
                
                let point = self.fetchPosterPageCount(paperSize: paperSize, pageSize: pageSize, scale: scale)
                pageModel.operation.poster.tilePoint = point
                count = Int((point.x * point.y)) * pages.count
                
            } else if (pageModel.operation.poster.type == .breakUp) {
                count = Int((pageModel.operation.pageOfPaper.point.x * pageModel.operation.pageOfPaper.point.y)) * pages.count
            } else {
                count = Int(ceilf(Float(pages.count / pageOfPaper)))
            }
        case .pamphlet: do {
            let temp = pages.count%4
            if temp == 0 {
                count = pages.count / 4
            } else {
                count = pages.count / 4 + 1
            }
            if pageModel.operation.pamphlet.type == .doubleSided {
                count = count * 2
            }
        }
        default:
            count = Int(ceilf(Float(pages.count / pageOfPaper)))
        }
        return count
    }
    
    func fetchPosterPageCount(paperSize: CGSize, pageSize: CGSize, scale: CGFloat) -> CGPoint {
        var xCount: Int = 1
        var yCount: Int = 1
        var contain: Bool = true
        while (contain) {
            if (pageSize.width * scale < CGFloat(xCount) * paperSize.width &&
                pageSize.height * scale < CGFloat(yCount) * paperSize.height) {
                contain = false
                break
            }
            
            //增加行数 和 列数
            if xCount == yCount {
                xCount += 1
            } else {
                yCount += 1
            }
        }
        return CGPoint(x: xCount, y: yCount)
    }
    
    /**
     获取pages
     @param type 页面类型
     @param contentType annoation类型
     @param selectPages 当type 为custom时  传入选中page的下标
     */
    func fetchPaperSize(_ paperModel: KMPrintPaperModel) -> CGSize {
        var paperSize = KMPrintPaperInfo.KMPaperType.paperSize(type: paperModel.info.type, unit: .px)
        let direction = paperModel.direction
        
        if direction == .vertical {
            paperSize = CGSize(width: paperSize.width, height: paperSize.height)
        } else if direction == .horizontal {
            paperSize = CGSize(width: paperSize.height, height: paperSize.width)
        }
        return paperSize
    }
    
    func fetchPaperItemSize(_ paperModel: KMPrintPaperModel) -> CGSize {
        var paperSize = self.fetchPaperSize(paperModel)
        let paperInset = paperModel.info.inset
        
        paperSize = CGSize(width: paperSize.width - paperInset.left - paperInset.right,
                           height: paperSize.height - paperInset.bottom - paperInset.top)
        return paperSize
    }
}

protocol KMPrintPresenterDraw {}
extension KMPrintPresenter: KMPrintPresenterDraw {
    //    -(void)drawCutMarkContext:(CGContextRef)context contextSize:(CGSize)size
    //    {
    //        CGContextSetStrokeColorWithColor(context, [NSColor blackColor].CGColor);
    //        CGContextSetLineWidth(context, 1.0);
    //        CGContextSetLineCap(context, kCGLineCapSquare);
    //
    //        if(self.columnIndex == 1 && self.lineIndex == 1) {
    //            [self drawLeftBottomCutMarks:context size:size];
    //            [self drawRightTopCutMarks:context size:size];
    //            [self drawRightBottomCutMarks:context size:size];
    //        } else if (self.lineIndex == 1 && self.columnIndex == self.vertArray.count) {
    //            [self drawLeftTopCutMarks:context size:size];
    //            [self drawRightTopCutMarks:context size:size];
    //            [self drawRightBottomCutMarks:context size:size];
    //        } else if (self.columnIndex == 1 && self.lineIndex == self.hourArray.count) {
    //            [self drawLeftTopCutMarks:context size:size];
    //            [self drawLeftBottomCutMarks:context size:size];
    //            [self drawRightBottomCutMarks:context size:size];
    //        } else if (self.columnIndex == self.vertArray.count && self.hourArray.count == self.lineIndex) {
    //            [self drawLeftTopCutMarks:context size:size];
    //            [self drawLeftBottomCutMarks:context size:size];
    //            [self drawRightTopCutMarks:context size:size];
    //        } else {
    //            [self drawLeftTopCutMarks:context size:size];
    //            [self drawLeftBottomCutMarks:context size:size];
    //            [self drawRightTopCutMarks:context size:size];
    //            [self drawRightBottomCutMarks:context size:size];
    //        }
    //        //绘制完成
    //        CGContextStrokePath(context);
    //    }
    //
    //    //左上角切割标记
    //    -(void)drawLeftTopCutMarks:(CGContextRef)context size:(CGSize)size
    //    {
    //        CGFloat KBlankA4H =size.height;
    //        CGPoint point_LeftTop = CGPointZero;
    //
    //        if (self.PDFPrint.splitType == kKMPDFPosterSplitType_PageNumber) {
    //            point_LeftTop.x = self.PDFPrint.fullPageEdgeInsets.left;
    //        } else {
    //            point_LeftTop.x = self.PDFPrint.edgeInsets.left;
    //        }
    //
    //        point_LeftTop.y = KBlankA4H - self.PDFPrint.edgeInsets.top;
    //
    //        CGContextMoveToPoint(context, 10,point_LeftTop.y);
    //        CGContextAddLineToPoint(context,point_LeftTop.x, point_LeftTop.y);
    //
    //        CGContextMoveToPoint(context, point_LeftTop.x - 10,KBlankA4H -10);
    //        CGContextAddLineToPoint(context,point_LeftTop.x - 10,point_LeftTop.y);
    //    }
    //
    //    //右上角切割标记
    //    -(void)drawRightTopCutMarks:(CGContextRef)context size:(CGSize)size
    //    {
    //        CGFloat KBlankA4W =size.width;
    //        CGFloat KBlankA4H =size.height;
    //
    //        CGPoint point_RightTop = CGPointZero;//右上角
    //
    //        if (self.PDFPrint.splitType == kKMPDFPosterSplitType_PageNumber) {
    //            point_RightTop.x = KBlankA4W - self.PDFPrint.fullPageEdgeInsets.right;
    //            point_RightTop.y = KBlankA4H - self.PDFPrint.fullPageEdgeInsets.top;
    //        } else {
    //            point_RightTop.x = KBlankA4W - self.PDFPrint.edgeInsets.right;
    //            point_RightTop.y = KBlankA4H - self.PDFPrint.edgeInsets.top;
    //        }
    //
    //        CGContextMoveToPoint(context,point_RightTop.x,point_RightTop.y);
    //        CGContextAddLineToPoint(context,KBlankA4W - 10,point_RightTop.y);
    //
    //        CGContextMoveToPoint(context,point_RightTop.x + 10,KBlankA4H - 10);
    //        CGContextAddLineToPoint(context,point_RightTop.x + 10,point_RightTop.y);
    //    }
    //
    //    //左下角切割标记
    //    -(void)drawLeftBottomCutMarks:(CGContextRef)context size:(CGSize)size
    //    {
    //        CGPoint point_LeftBottom = CGPointZero;//左下角
    //        if (self.PDFPrint.splitType == kKMPDFPosterSplitType_PageNumber) {
    //            point_LeftBottom.x = self.PDFPrint.fullPageEdgeInsets.left;
    //            point_LeftBottom.y = self.PDFPrint.fullPageEdgeInsets.bottom;
    //        } else {
    //            point_LeftBottom.x = self.PDFPrint.edgeInsets.left;
    //            point_LeftBottom.y = self.PDFPrint.edgeInsets.bottom;
    //        }
    //
    //        //左下角
    //        CGContextMoveToPoint(context, 10,point_LeftBottom.y);
    //        CGContextAddLineToPoint(context,point_LeftBottom.x, point_LeftBottom.y);
    //
    //        CGContextMoveToPoint(context, point_LeftBottom.x- 10,10);
    //        CGContextAddLineToPoint(context,point_LeftBottom.x - 10,point_LeftBottom.y);
    //    }
    //
    //    //右下角切割标记
    //    -(void)drawRightBottomCutMarks:(CGContextRef)context size:(CGSize)size
    //    {
    //        CGFloat KBlankA4W =size.width;
    //
    //        CGPoint point_RightBottom = CGPointZero;//右下角
    //        if (self.PDFPrint.splitType == kKMPDFPosterSplitType_PageNumber) {
    //            point_RightBottom.x = KBlankA4W - self.PDFPrint.fullPageEdgeInsets.right;
    //            point_RightBottom.y = self.PDFPrint.fullPageEdgeInsets.bottom;
    //        } else {
    //            point_RightBottom.x = KBlankA4W - self.PDFPrint.edgeInsets.right;
    //            point_RightBottom.y = self.PDFPrint.edgeInsets.bottom;
    //        }
    //
    //        CGContextMoveToPoint(context,KBlankA4W - 10,point_RightBottom.y);
    //        CGContextAddLineToPoint(context,point_RightBottom.x,point_RightBottom.y);
    //
    //        CGContextMoveToPoint(context,point_RightBottom.x+ 10,10);
    //        CGContextAddLineToPoint(context,point_RightBottom.x+ 10,point_RightBottom.y);
    //    }
    
    func drawString(_ pageModel: KMPrintPageModel, _ contextSize: CGSize) {
        var string = pageModel.operation.poster.tags.first ?? ""
//        if string.isEmpty {
//            string =
//        }
        
    }
    //
    //    - (void)drawLabelTextContextSize:(CGSize)contextSize
//        {
//            CGFloat KBlankA4W =contextSize.width;
//            CGFloat KBlankA4H =contextSize.height;
//
//            NSString *contextString = nil;
//            if (self.PDFPrint.labelString && self.PDFPrint.labelString.length > 0) {
//                contextString = self.PDFPrint.labelString;
//            } else {
//                NSDate *date = [NSDate date];
//                NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
//                [formatter setDateFormat:@"YYYY-MM-dd hh:mm:ss"];
//                contextString = [NSString stringWithFormat:@"(%ld,%ld) %@ %@",self.columnIndex,self.lineIndex,[self.filePath lastPathComponent],[formatter stringFromDate:date]];
//            }
//
//            CGFloat fontSize = 12.0 * (MAX(KBlankA4W, KBlankA4H)/842);
//            NSFont *font = [NSFont systemFontOfSize:fontSize];
//            NSColor *color = [NSColor blackColor];
//
//            NSSize size = NSZeroSize;
//            NSMutableParagraphStyle *style = [[[NSMutableParagraphStyle alloc] init] autorelease];
//            [style setAlignment:NSCenterTextAlignment];
//            [style setLineBreakMode:NSLineBreakByCharWrapping];
//            NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
//            [dictionary setObject:style forKey:NSParagraphStyleAttributeName];
//            [dictionary setObject:color forKey:NSForegroundColorAttributeName];
//            [dictionary setObject:font forKey:NSFontAttributeName];
//            size = [contextString boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT)
//                                               options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
//                                            attributes:dictionary].size;
//
//            if (self.PDFPrint.splitType == kKMPDFPosterSplitType_PageNumber) {
//                [contextString drawInRect:CGRectMake(self.PDFPrint.fullPageEdgeInsets.left +10,
//                                                     KBlankA4H - self.PDFPrint.fullPageEdgeInsets.top + size.height,
//                                                     size.width, size.height)
//                           withAttributes:dictionary];
//            } else {
//                [contextString drawInRect:CGRectMake(self.PDFPrint.edgeInsets.left +10,
//                                                     KBlankA4H - self.PDFPrint.edgeInsets.top + size.height,
//                                                     size.width, size.height)
//                           withAttributes:dictionary];
//            }
//
//        }
}


protocol KMPrintPresenterPrivate {}
extension KMPrintPresenter: KMPrintPresenterPrivate {
    func isAnnoationStamp(type: String) -> Bool {
        let annotationStamp: [String] = ["Square", "Stamp"]
        return annotationStamp.contains(type)
    }
    
    func isAnnoationMarkup(type: String) -> Bool {
        let annotationStamp: [String] = ["Widget", "Freehand", "Highlight", "Underline", "Squiggly", "Circle", "StrikeOut", "Ink"]
        return annotationStamp.contains(type)
    }
    
    func isAnnoationForm(type: String) -> Bool {
        let annotationStamp: [String] = ["FreeText"]
        return annotationStamp.contains(type)
    }
}

protocol KMPrintPresenterProtocol: NSObject {
    
}



///**
// @abstract 获取context
// @param size纸张大小
// */
//func createContext(_ saveFilePath: String, size: CGSize) -> CGContext {
//    let s = CGSize(width: nearbyint(size.width), height: nearbyint(size.height))
//    let rep = NSBitmapImageRep.init(bitmapDataPlanes: nil,
//                                    pixelsWide: Int(s.width),
//                                    pixelsHigh: Int(s.height),
//                                    bitsPerSample: 8,
//                                    samplesPerPixel: 4,
//                                    hasAlpha: true,
//                                    isPlanar: false,
//                                    colorSpaceName: NSColorSpaceName.calibratedRGB,
//                                    bytesPerRow: 0,
//                                    bitsPerPixel: 0)!
//    let context: CGContext = NSGraphicsContext.init(bitmapImageRep: rep)!.cgContext
//    return context
//}

//MARK: 渲染单页
extension KMPrintPresenter {
    static func drawPage(context: CGContext, page: PDFPage, model: KMPrintModel) {
//        let drawPage = KMPrintDrawPage()
//        drawPage.page = page
//        drawPage.cropRect = page.bounds(for: .cropBox)
//        drawPage.showRect = page.bounds(for: .cropBox)
//        let prinsenter = KMPrintPresenter()
//        prinsenter.printData = model
//        prinsenter.drawTestPage(context, model, [drawPage])
    }
    
    func drawTestPage(_ context: CGContext,
                   _ printModel: KMPrintModel,
                   _ pages: [KMPrintDrawPage]) {
        /**
         参数
         */
//        //纸张大小
//        let paperSize: CGSize = self.fetchPaperSize(printModel.paper)
//        //总页数
//        let paperCount: Int = self.fetchTotalPaperCount(paperSize, pages, printModel.page)
//        //每页page数
//        let pageOfPaperCount: Int = self.fetchPageOfPaper(printModel.page)
//        //获取每张纸的page
//        let drawPages: [[KMPrintDrawPage]] = self.fetchDrawPages(paperSize, printModel.page, paperCount, pageOfPaperCount, pages)
//        
//        
//        self.drawPageToContext(context, drawPages.first!, printModel)
    }
}