//
//  PDFDataProcessor.swift
//  PrinterDemo
//
//  Created by ios on 2021/12/17.
//  Copyright © 2021 Printer. All rights reserved.
//

import UIKit
import PDFKit
import SwifterBaseKit

protocol PDFDataProcessor {
    
    var width: CGFloat { get }
    var height: CGFloat { get }
    func draw(ctx: CGContext?) -> Void
    func baw_rotate90(clockwise: Bool) -> Self
    func getReprImage() -> UIImage
}

extension UIImage: PDFDataProcessor {
    
    var width: CGFloat {
        return pixelWidth
    }
    
    var height: CGFloat {
        return pixelHeight
    }
    
    func draw(ctx: CGContext?) {
        draw(in: CGRect.init(origin: .zero, size: CGSize.init(width: pixelWidth, height: pixelHeight)))
    }
    
    func baw_rotate90(clockwise: Bool) -> Self {
        return rotate90(clockwise: clockwise) as! Self
    }
    
    func getReprImage() -> UIImage {
        return self
    }
}

extension CGPDFPage: PDFDataProcessor {
    
    struct Key {
        static var c_rotationAngle = 0
    }
    
    var c_rotationAngle: Int32 {
        
        set {
            if newValue % 90 != 0 {
                fatalError()
            }
            objc_setAssociatedObject(self, &Key.c_rotationAngle, newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
        
        get {
            guard let temp = objc_getAssociatedObject(self, &Key.c_rotationAngle) as? Int32 else { return 0 }
            return temp
        }
    }
    
    var width: CGFloat {
        return (rotationAngle + c_rotationAngle) % 180 == 0 ? getBoxRect(.cropBox).width : getBoxRect(.cropBox).height
    }
    
    var height: CGFloat {
        return (rotationAngle + c_rotationAngle) % 180 == 0 ? getBoxRect(.cropBox).height : getBoxRect(.cropBox).width
    }
    
    func draw(ctx: CGContext?) {
        let size = CGSize.init(width: width, height: height)
        let t = getDrawingTransform(.cropBox, rect: CGRect.init(origin: .zero, size: size), rotate: c_rotationAngle, preserveAspectRatio: true)
        ctx?.saveGState()
        ctx?.translateBy(x: 0, y: size.height)
        ctx?.scaleBy(x: 1, y: -1)
        ctx?.concatenate(t)
        ctx?.drawPDFPage(self)
        ctx?.restoreGState()
    }
    
    func baw_rotate90(clockwise: Bool) -> Self {
        c_rotationAngle += 90
        return self
    }
    
    func getReprImage() -> UIImage {
        let size = CGSize.init(width: width, height: height)
        UIGraphicsBeginImageContextWithOptions(size, true, 0)
        UIColor.white.setFill()
        UIRectFill(CGRect.init(origin: .zero, size: size))
        let ctx = UIGraphicsGetCurrentContext()!
        draw(ctx: ctx)
        let result = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return result
    }
}

@available(iOS 11.0, *)
extension PDFPage: PDFDataProcessor {
    
    var width: CGFloat {
        return rotation % 180 == 0 ? bounds(for: .cropBox).width : bounds(for: .cropBox).height
    }
    
    var height: CGFloat {
        return rotation % 180 == 0 ? bounds(for: .cropBox).height : bounds(for: .cropBox).width
    }
    
    func draw(ctx: CGContext?) {
        
        guard let ctx = ctx else { return }
        ctx.saveGState()
        ctx.translateBy(x: 0, y: height)
        ctx.scaleBy(x: 1, y: -1)
        draw(with: .cropBox, to: ctx)
        ctx.restoreGState()
    }
    
    func baw_rotate90(clockwise: Bool) -> Self {
        rotation += 90
        return self
    }
    
    func getReprImage() -> UIImage {
        let size = CGSize.init(width: width, height: height)
        UIGraphicsBeginImageContextWithOptions(size, true, 0)
        UIColor.white.setFill()
        UIRectFill(CGRect.init(origin: .zero, size: size))
        let ctx = UIGraphicsGetCurrentContext()!
        draw(ctx: ctx)
        let result = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return result
    }
}

