//
//  AutoSaveManager.swift
//  PDF Reader Pro
//
//  Created by tangchao on 2023/11/8.
//

import Cocoa

public let KAutoSaveTimeValueChangedNoti = "KAutoSaveTimeValueChangedNoti"

@objcMembers class AutoSaveManager: NSObject {
    public static let kTimeValueChangedNotificationName = Notification.Name(KAutoSaveTimeValueChangedNoti)
    
    //APP是否允许进行自动缓存
    var autoSaveEnabled = false {
        didSet {
            UserDefaults.standard.setValue(self.autoSaveEnabled, forKey: "ComAutoSaveKey")
            UserDefaults.standard.synchronize()
        }
    }
    var timeInterval: CGFloat = 15 {
        didSet {
            UserDefaults.standard.setValue(Float(self.timeInterval), forKey: "AutoSaveTimeIntervalKey")
            UserDefaults.standard.synchronize()
        }
    }
    
    //防止重复弹出
    var autoSaveAlertShow = false
    var autoSaveDidEndAction = false
    // /当前是否正在保存
    var isSaving = false
    var isSaveNoti = false
    
    private var _autoSaveFolder: String = ""
    var autoSaveFolder: String {
        get {
            return self._autoSaveFolder
        }
    }
    
    private var _infoDict: NSMutableDictionary?
    // 保存的原文件信息
    private var _originalPaths: NSMutableArray?
    var originalPaths: NSMutableArray? {
        get {
            return self._originalPaths
        }
    }
    // 对应保存的信息
    private var _autoSavePaths: NSMutableArray?
    var autoSavePaths: NSMutableArray? {
        get {
            return self._autoSavePaths
        }
    }
    // 所有打开的文件信息汇总
    var opendPaths: NSMutableArray? {
        get {
            return self._opendPaths
        }
    }
    private var _opendPaths: NSMutableArray?
    
    static let manager: AutoSaveManager = {
        let man = AutoSaveManager()
        man.autoSaveEnabled = UserDefaults.standard.bool(forKey: "ComAutoSaveKey")

        let timeInterval = UserDefaults.standard.float(forKey: "AutoSaveTimeIntervalKey")
        if timeInterval > 0 {
            man.timeInterval = timeInterval.cgFloat
        } else {
            man.timeInterval = 15
        }

        man._loadData()

        man.autoSaveDidEndAction = true
        return man
    }()
    
    // MARK: - Public Method
    
    func clearCache() {
        if FileManager.default.fileExists(atPath: self.autoSaveFolder) {
            try?FileManager.default.removeItem(atPath: self.autoSaveFolder)
        }
        if FileManager.default.fileExists(atPath: self.autoSaveFolder) == false {
            try?FileManager.default.createDirectory(atPath: self.autoSaveFolder, withIntermediateDirectories: true)
        }
    }
    
    func autoSaveWithPath(_ filePath: String) -> String {
        let autoSaveFolder = self.autoSaveFolder

        let plistPath = String(format: "%@/autoSaveInfo.plist", autoSaveFolder)
        var savePath = String(format: "%@/%@_%@.%@", autoSaveFolder, filePath.deletingPathExtension.lastPathComponent, "recovered", filePath.customPathExtension)

        if FileManager.default.fileExists(atPath: plistPath) {
            var dict = NSMutableDictionary(contentsOfFile: plistPath)
            if let keys = dict?.allKeys as? [String], keys.contains(filePath) {
                savePath = dict?.value(forKey: filePath) as? String ?? ""
            }
            if savePath.isEmpty == false && filePath.isEmpty == false {
                if let values = dict?.allValues as? [String], values.contains(savePath) {
                    //不同路径下同名文件的保存覆盖的情况处理
                    var values = NSArray(array: values)

                    for key in dict?.allKeys ?? [] {
                        guard let _key = key as? String else {
                            continue
                        }
                        let value = dict?.object(forKey: key) as? String ?? ""
                        if savePath == value && _key != filePath {
                            var count = 1
                            savePath = String(format: "%@/%@_%@(%d).%@", autoSaveFolder, filePath.deletingPathExtension.lastPathComponent, "recovered", count, filePath.customPathExtension)
                            while values.contains(savePath) {
                                count += 1
                                savePath = String(format: "%@/%@_%@(%d).%@", autoSaveFolder, filePath.deletingPathExtension.lastPathComponent, "recovered", count, filePath.customPathExtension)
                            }
                        }
                    }
                }
                dict?.setValue(savePath, forKey: filePath)
            }
            try?dict?.write(to: URL(fileURLWithPath: plistPath))
        } else {
            var dict = NSMutableDictionary()
            if savePath.isEmpty == false && filePath.isEmpty == false {
                dict.setValue(savePath, forKey: filePath)
            }
            try?dict.write(to: URL(fileURLWithPath: plistPath))
        }
        return savePath
    }
    
    func removeAutoSavePath(_ filePath: String) {
        let autoSaveFolder = self.autoSaveFolder

        let plistPath = String(format: "%@/autoSaveInfo.plist", autoSaveFolder)
        if FileManager.default.fileExists(atPath: plistPath) {
            var dict = NSMutableDictionary(contentsOfFile: plistPath)
            if let savePath =  dict?.value(forKey: filePath) as? String {
                if FileManager.default.fileExists(atPath: savePath) {
                    try?FileManager.default.removeItem(atPath: savePath)
                }
                dict?.removeObject(forKey: filePath)
            }

            if let keys = dict?.allKeys, keys.count > 0 {
                try?dict?.write(to: URL(fileURLWithPath: plistPath))
            } else {
                try?FileManager.default.removeItem(atPath: plistPath)
            }
        }
    }
    
    // MARK: - Private Methods
    
    private func _loadData() {
        var cachesPath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first ?? ""

        let filepath = "\(cachesPath)/\(Bundle.main.bundleIdentifier ?? "")"
        if FileManager.default.fileExists(atPath: filepath) {
            cachesPath = filepath
        }
        cachesPath = "\(cachesPath)/autoSaveFolder"
        if FileManager.default.fileExists(atPath: cachesPath) == false {
            try?FileManager.default.createDirectory(atPath: cachesPath, withIntermediateDirectories: true)
        }
        self._autoSaveFolder = cachesPath

        KMPrint("autoSaveFolder===\(cachesPath)")

        let plistPath = String(format: "%@/autoSaveInfo.plist", self.autoSaveFolder)
        guard let dict = NSMutableDictionary(contentsOfFile: plistPath) else {
            return
        }
        if (dict.allKeys.count == 0) {
            return
        }

        self._infoDict = dict

        if (self._autoSavePaths == nil) {
            self._autoSavePaths = NSMutableArray()
        }

        if (self._originalPaths == nil) {
            self._originalPaths = NSMutableArray()
        }

        self._originalPaths?.addObjects(from: dict.allKeys)

        self._opendPaths = NSMutableArray()

        var arr = (try?FileManager.default.contentsOfDirectory(atPath: self.autoSaveFolder)) ?? []

        for fileName in arr {
            let savedKey = "\(self.autoSaveFolder)/\(fileName)"
            guard let values = dict.allValues as? [String] else {
                continue
            }
            if values.contains(savedKey) {
                self.autoSavePaths?.add(savedKey)
            } else {
                if fileName == "autoSaveInfo.plist" {

                } else {
                    try?FileManager.default.removeItem(atPath: savedKey)
                }
            }
        }
    }
    
    /*

     - (NSString *)URLEncodedString:(NSString *)string {
         CFStringRef stringRef = CFBridgingRetain(string);
     #pragma clang diagnostic push
     #pragma clang diagnostic ignored "-Wdeprecated-declarations"
         CFStringRef encoded = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                       stringRef,
                                                                       NULL,
                                                                       CFSTR("!*'\"();:@&=+$,/?%#[]% "),
                                                                       kCFStringEncodingUTF8);
     #pragma clang diagnostic pop
         CFRelease(stringRef);
         return CFBridgingRelease(encoded);
     }

     - (NSString *)getValidFilePath:(NSString *)oldPath {
         NSFileManager *fileManager = [NSFileManager defaultManager];
         NSDictionary  *fileDic     = [fileManager attributesOfItemAtPath:oldPath error:nil];
         NSString      *fileType    = [fileDic objectForKey:NSFileType];
         int i =1;
         NSString *newPath = oldPath;
         while ([fileManager fileExistsAtPath:newPath]) {
             if ([fileType isEqualToString:NSFileTypeDirectory]) {
                 newPath = [oldPath stringByAppendingFormat:@"(%d)",i];
             } else {
                 NSString *fileExtension = [oldPath pathExtension];
                 newPath = [[oldPath stringByDeletingPathExtension] stringByAppendingFormat:@"(%d).%@",i,fileExtension];
             }
             i++;
         }
         return newPath;
     }
     */

}