//
//  ImageProcess.swift
//  KdanAuto
//
//  Created by 朱东勇 on 2023/2/7.
//

import Foundation
import AppKit

class ImageProcess : NSObject {
    
    //  Image compare
    class func compareJPEG(_ resultPath:String, checkPath:String) -> Double {
        if !FileManager.default.fileExists(atPath: resultPath) || !FileManager.default.fileExists(atPath: checkPath) {
            return -1
        }
        
        let rImage = NSImage.init(contentsOfFile: resultPath) ?? nil
        let cImage = NSImage.init(contentsOfFile: checkPath) ?? nil
        
        if nil == rImage || nil == cImage {
            return -1
        }
        
        let resultImage = rImage as! NSImage
        let checkImage = cImage as! NSImage
        
        let resultImageRep = NSBitmapImageRep.init(cgImage: resultImage.cgImage(forProposedRect: nil, context: nil, hints: nil)!)
        let checkImageRep = NSBitmapImageRep.init(cgImage: checkImage.cgImage(forProposedRect: nil, context: nil, hints: nil)!)
        
        let rWidth = resultImageRep.pixelsWide
        let rHeight = resultImageRep.pixelsHigh
        let rBitPerPixel = resultImageRep.bitsPerPixel / 8
        let rBytePerRow = resultImageRep.bytesPerRow
        
        let cWidth = checkImageRep.pixelsWide
        let cHeight = checkImageRep.pixelsHigh
        let cBitPerPixel = checkImageRep.bitsPerPixel / 8
        let cBytePerRow = checkImageRep.bytesPerRow
        
        let maxWidth = min(rWidth, cWidth) - 1
        let maxHeight = min(rHeight, cHeight) - 1
        
        // check background color
        // 挑选图片 对角斜线 上的相素进行识别
        var markInfo = NSMutableDictionary.init()
        for w in 0...maxWidth {
            let x = Int(w)
            for mark in 0...1 {
                let color = checkImageRep.colorAt(x: min(x, cWidth-1), y: min(mark == 0 ? x : (maxWidth - x), (cHeight-1))) as! NSColor
                
                if (markInfo[color] != nil) {
                    let count = (markInfo[color] as? NSNumber)!.intValue ?? 0
                    
                    markInfo[color] = NSNumber.init(value: count + 1)
                }else {
                    markInfo[color] = NSNumber.init(value: 1)
                }
            }
        }
        
        var maxCount = Int(0);
        var bgColor : NSColor? = nil
        for color in markInfo.allKeys {
            let count = (markInfo[color] as? NSNumber)!.intValue ?? 0
            
            if count > maxCount {
                maxCount = count
                bgColor = color as! NSColor
            }
        }
        
        if nil != bgColor {
            NSLog(String("识别到背景色\(bgColor)"))
        }
        
        // Compare
        let compareDifValue = DataModel.shared.comparativeDifference()
        var equalCount = 0 as Double
        var bgCount = 0 as Double
        for w in 0...maxWidth {
            let x = Int(w)
            
            for h in 0...maxHeight {
                let y = Int(h)
                
                let cColor = checkImageRep.colorAt(x: x, y: y) as! NSColor
                let rColor = resultImageRep.colorAt(x: x, y: y) as! NSColor
                
                let cr = Int(cColor.redComponent*255)
                let cg = Int(cColor.greenComponent*255)
                let cb = Int(cColor.blueComponent*255)
                let ca = Int(cColor.blueComponent*255)
                
                let rr = Int(rColor.redComponent*255)
                let rg = Int(rColor.greenComponent*255)
                let rb = Int(rColor.blueComponent*255)
                let ra = Int(rColor.blueComponent*255)
                
//                if (cColor.isEqual(to: rColor)) {
                if (abs(cr - rr) <= compareDifValue &&
                    abs(cg - rg) <= compareDifValue &&
                    abs(cb - rb) <= compareDifValue &&
                    abs(ca - ra) <= compareDifValue) {
                    equalCount = equalCount + 1
                    
                    if bgColor != nil &&
                        cColor.isEqual(to: bgColor) {
                        bgCount += 1
                    }
                }
            }
        }
        
        NSLog(String("过滤点数目\(bgCount)"))
        
        return Double(max(equalCount-bgCount, 1)/(max(Double(cWidth) * Double(cHeight)-bgCount, 1)) * 100.0)
    }
    
    //Genera Image
    class func processImage(_ resultPath:String, checkPath:String) -> NSImage? {
        if !FileManager.default.fileExists(atPath: resultPath) || !FileManager.default.fileExists(atPath: checkPath) {
            return nil
        }
        
        let rImage = NSImage.init(contentsOfFile: resultPath) ?? nil
        let cImage = NSImage.init(contentsOfFile: checkPath) ?? nil
        
        if nil == rImage || nil == cImage {
            return nil
        }
        
        let resultImage = rImage as! NSImage
        let checkImage = cImage as! NSImage
        
        let resultImageRep = NSBitmapImageRep.init(cgImage: resultImage.cgImage(forProposedRect: nil, context: nil, hints: nil)!)
        let checkImageRep = NSBitmapImageRep.init(cgImage: checkImage.cgImage(forProposedRect: nil, context: nil, hints: nil)!)
        
        let rWidth = resultImageRep.pixelsWide
        let rHeight = resultImageRep.pixelsHigh
        let rBitPerPixel = resultImageRep.bitsPerPixel / 8
        let rBytePerRow = resultImageRep.bytesPerRow
        
        let cWidth = checkImageRep.pixelsWide
        let cHeight = checkImageRep.pixelsHigh
        let cBitPerPixel = checkImageRep.bitsPerPixel / 8
        let cBytePerRow = checkImageRep.bytesPerRow
        let data = NSMutableData.init(length: cWidth * cHeight * 4)
        if nil == data {
            return nil
        }
        
        let maxWidth = min(rWidth, cWidth) - 1
        let maxHeight = min(rHeight, cHeight) - 1
        
        // check background color
        // 挑选图片 对角斜线 上的相素进行识别
        var markInfo = NSMutableDictionary.init()
        for w in 0...maxWidth {
            let x = Int(w)
            for mark in 0...1 {
                let color = checkImageRep.colorAt(x: min(x, cWidth-1), y: min(mark == 0 ? x : (maxWidth - x), (cHeight-1))) as! NSColor
                
                if (markInfo[color] != nil) {
                    let count = (markInfo[color] as? NSNumber)!.intValue ?? 0
                    
                    markInfo[color] = NSNumber.init(value: count + 1)
                }else {
                    markInfo[color] = NSNumber.init(value: 1)
                }
            }
        }
        
        var maxCount = Int(0);
        var bgColor : NSColor? = nil
        for color in markInfo.allKeys {
            let count = (markInfo[color] as? NSNumber)!.intValue ?? 0
            
            if count > maxCount {
                maxCount = count
                bgColor = color as! NSColor
            }
        }
        
        if nil != bgColor {
            NSLog(String("识别到背景色\(bgColor)"))
        }
        
        // Compare
        let compareDifValue = DataModel.shared.comparativeDifference()
        for w in 0...maxWidth {
            let x = Int(w)
            
            for h in 0...maxHeight {
                let y = Int(h)
                
                let cColor = checkImageRep.colorAt(x: x, y: y) as! NSColor
                let rColor = resultImageRep.colorAt(x: x, y: y) as! NSColor
                
                let cr = Int(cColor.redComponent*255)
                let cg = Int(cColor.greenComponent*255)
                let cb = Int(cColor.blueComponent*255)
                let ca = Int(cColor.blueComponent*255)
                
                let rr = Int(rColor.redComponent*255)
                let rg = Int(rColor.greenComponent*255)
                let rb = Int(rColor.blueComponent*255)
                let ra = Int(rColor.blueComponent*255)
                
                //                if (cColor.isEqual(to: rColor)) {
                if (abs(cr - rr) <= compareDifValue &&
                    abs(cg - rg) <= compareDifValue &&
                    abs(cb - rb) <= compareDifValue &&
                    abs(ca - ra) <= compareDifValue) {
                    if bgColor != nil &&
                        cColor.isEqual(to: bgColor) {
                    }
                }else {
//                    NSLog("(\(cr),\(cg),\(cb),\(cr))=(\(rr),\(rg),\(rb),\(rr))")
                    let addr = cWidth * 4 * y + x * 4
                    
                    var r = uint8(255)
                    data!.replaceBytes(in: NSRange.init(location: addr+0, length: 1), withBytes: &r)
                    var g = uint8(255 * rColor.greenComponent/2)
                    data!.replaceBytes(in: NSRange.init(location: addr+1, length: 1), withBytes: &g)
                    var b = uint8(255 * rColor.blueComponent/2)
                    data!.replaceBytes(in: NSRange.init(location: addr+2, length: 1), withBytes: &b)
                    var a = uint8(255 * rColor.alphaComponent * 0.7)
                    data!.replaceBytes(in: NSRange.init(location: addr+3, length: 1), withBytes: &a)
                }
            }
        }
        
        let cfData = CFDataCreate(kCFAllocatorDefault, data?.bytes, data!.length)
        let dataProvider = CGDataProvider.init(data: cfData!)
        
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let cgImage = CGImage.init(width: cWidth,
                                   height: cHeight,
                                   bitsPerComponent: 8,
                                   bitsPerPixel: 8 * 4,
                                   bytesPerRow: cWidth * 4,
                                   space: colorSpace,
                                   bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrderDefault.rawValue) ?? CGBitmapInfo.byteOrderDefault,
                                   provider: dataProvider!,
                                   decode: nil,
                                   shouldInterpolate: true,
                                   intent: CGColorRenderingIntent.defaultIntent)
        
        if nil != cgImage {
            return NSImage.init(cgImage: cgImage!, size: NSSize.init(width: cWidth, height: cHeight))
        }
        
        return nil
    }
}
