//
//  KMBatchAddBackgroundOperation.swift
//  PDF Reader Pro
//
//  Created by liujiajie on 2023/12/11.
//

import Foundation

class KMBatchAddBackgroundOperation: KMBatchOperation{
    var background: KMBackgroundModel?
    var pdfDocument: CPDFDocument!
    var password: String = ""
    
    init(file: KMBatchOperateFile, backgroundM: KMBackgroundModel) {
        super.init(file: file)
        self.background = backgroundM
       
        self.password = file.password
    }
    
    override func start() {
        self.pdfDocument = CPDFDocument(url: URL(fileURLWithPath: self.operateFile?.filePath ?? ""))
        if let data = self.pdfDocument?.isLocked, data {
            self.pdfDocument?.unlock(withPassword: self.operateFile?.password)
        }
        if !self.isCancelled {
            self.delegate?.fileBeginOperate?(self.operateFile!, info: self.operateFile!.addBackgroundInfo)
            willChangeValue(forKey: "isExecuting")
            self.hasExcuting = true
            didChangeValue(forKey: "isExecuting")
            
            let newArr = NSMutableArray()
            for i in 0..<(self.operateFile?.addBackgroundInfo.pagesArray?.count ?? 0) {
                let number = self.operateFile?.addBackgroundInfo.pagesArray![i]
                newArr.add(number!.intValue - 1)
            }
            
            if !FileManager.default.fileExists(atPath: self.operateFile!.filePath) {
                self.delegate?.fileOperateFailed?(self.operateFile!, error: self.errorWithMsg(KMLocalizedString("File Not Exist", nil)), info: self.operateFile!.addBackgroundInfo)
                
                self.willChangeValue(forKey: "isFinished")
                self.hasFinished = true
                self.didChangeValue(forKey: "isFinished")
                return
            }
            
            if self.pdfDocument == nil {
                self.delegate?.fileOperateFailed?(self.operateFile!, error: self.errorWithMsg(KMLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.", nil)), info: self.operateFile!.addBackgroundInfo)
                self.willChangeValue(forKey: "isFinished")
                self.hasFinished = true
                self.didChangeValue(forKey: "isFinished")
                return
            }
            
            if !self.pdfDocument!.allowsPrinting || !self.pdfDocument!.allowsCopying {
                self.delegate?.fileOperateFailed?(self.operateFile!, error: self.errorWithMsg(KMLocalizedString("This is a secured document. Editing is not permitted.", nil)), info: self.operateFile!.addBackgroundInfo)
                self.willChangeValue(forKey: "isFinished")
                self.hasFinished = true
                self.didChangeValue(forKey: "isFinished")
                return
            }
            
            if newArr.count < 1 {
                let err = NSError(domain: "LocalError", code: 0, userInfo: [NSLocalizedDescriptionKey: KMLocalizedString("Invalid page range or the page number is out of range. Please try again.", nil)])
                self.delegate?.fileOperateFailed?(self.operateFile!, error: err, info: self.operateFile!.addBackgroundInfo)
                self.willChangeValue(forKey: "isFinished")
                self.hasFinished = true
                self.didChangeValue(forKey: "isFinished")
            }
            self.background?.pagesString = newArr.componentsJoined(by: ",")
            self.saveAsPDF(background: self.background!, path: (self.operateFile?.addBackgroundInfo.fetchDestinationFilepath())!)
           
        }else {
            willChangeValue(forKey: "isFinished")
            willChangeValue(forKey: "isExecuting")
            hasExcuting = false
            hasFinished = true
            didChangeValue(forKey: "isExecuting")
            didChangeValue(forKey: "isFinished")
        }
    }
    
    func saveAsPDF(background: KMBackgroundModel, path: String) {
        var filePath = self.pdfDocument?.documentURL?.path
        let password = self.password
        if filePath?.count ?? 0 < 1 {
            let str = String(format: "%@.pdf", KMLocalizedString("Untitled", nil))
            let writeSuccess = self.pdfDocument!.write(to: URL(fileURLWithPath: (kTempSavePath?.stringByAppendingPathComponent(str))!))
            if writeSuccess {
                let newDocument: CPDFDocument = CPDFDocument(url: URL(fileURLWithPath: (kTempSavePath?.stringByAppendingPathComponent(str))!))
                filePath = newDocument.documentURL?.path
            } else {
                NSSound.beep()
                return
            }
        }
        guard let document = CPDFDocument(url: URL(fileURLWithPath: filePath!)) else {
            return
        }
        
        if password.count > 0 {
            document.unlock(withPassword: password)
        }
        
        let tBackground: CPDFBackground = document.background()
        tBackground.opacity = background.opacity
        tBackground.scale = background.scale
        tBackground.rotation = CGFloat(-background.rotation)
        tBackground.horizontalAlignment = UInt(background.horizontalMode)
        tBackground.verticalAlignment = UInt(background.verticalMode)
        tBackground.xOffset = background.horizontalSpace
        tBackground.yOffset = background.verticalSpace

        if background.imagePath.count != 0 {
            let image = NSImage(contentsOfFile: background.imagePath)!
            tBackground.setImage(image)
            tBackground.type = .image
        } else if let color = background.color {
            tBackground.color = color
            tBackground.type = .color
        }

        if background.pagesString.count != 0 {
            tBackground.pageString = background.pagesString
        } else {
            let pageString = "0-\(document.pageCount - 1)"
            tBackground.pageString = pageString
        }

        tBackground.update()

        // Save to temporary path
        let documentPath = NSTemporaryDirectory()
        let tempPath = (documentPath as NSString).appendingPathComponent((path as NSString).lastPathComponent)
        try? FileManager.default.removeItem(atPath: tempPath)

        let result = document.write(to: URL(fileURLWithPath: tempPath))
        if result {
            if FileManager.default.fileExists(atPath: path) {
                try? FileManager.default.removeItem(atPath: path)
            }
            try? FileManager.default.moveItem(atPath: tempPath, toPath: path)
        } else {
            try? FileManager.default.removeItem(atPath: tempPath)
        }

        if result {
            self.delegate?.fileOperateSuccessed?(self.operateFile!, info: self.operateFile!.addBackgroundInfo)
        }else {
            self.delegate?.fileOperateFailed?(self.operateFile!, error: self.errorWithMsg(KMLocalizedString("Failed", nil)), info: self.operateFile!.addBackgroundInfo)
        }
        self.willChangeValue(forKey: "isFinished")
        self.hasFinished = true
        self.didChangeValue(forKey: "isFinished")
        
    }
    
    override func cancel() {
        //        super.cancel()
        if isExecuting {
            operateFile!.removeWatermarkInfo.status = .Waiting
            if FileManager.default.fileExists(atPath: (self.operateFile?.addBackgroundInfo.outPutPath)!) { try? FileManager.default.removeItem(atPath: (self.operateFile?.addBackgroundInfo.outPutPath)!)
            }
            self.delegate?.fileOperateCanceled?(self.operateFile!, info: self.operateFile!.addBackgroundInfo)
            
            willChangeValue(forKey: "isFinished")
            hasFinished = true
            didChangeValue(forKey: "isFinished")
        } else {
            willChangeValue(forKey: "isCancelled")
            hasCanceled = true
            didChangeValue(forKey: "isCancelled")
        }
    }
    
}