//
//  UIImage+Filter.swift 
//  EvidationCommonUI 
//  Copyright © 2021 Evidation Health Inc. All rights reserved.
//  

import UIKit

public enum ColorFilter {
    case noir
    case monochrome(intensity: CGFloat, color: UIColor)
    case brightness(percent: CGFloat)
    case contrast(percent: CGFloat)
    
    public func apply(to image: UIImage) -> UIImage {
        switch (self) {
        case .noir:
            return image.noir
        case .monochrome(let intensity, let color):
            return image.monochrome(intensity: intensity, color: color)
        case .brightness(let percent):
            return image.brightness(percent: percent)
        case .contrast(let percent):
            return image.contrast(percent: percent)
        }
    }
}

extension UIImage {
    var noir: UIImage {
        let context = CIContext(options: nil)
        guard let filter = CIFilter(name: "CIPhotoEffectNoir") else {
            return self
        }
        
        filter.setValue(CIImage(image: self), forKey: kCIInputImageKey)
        return processedImage(from: filter, context: context)
    }
    
    
    func monochrome(intensity: CGFloat, color: UIColor) ->  UIImage {
        let context = CIContext(options: nil)
        guard let filter = CIFilter(name: "CIColorMonochrome") else {
            return self
        }
        
        filter.setValue(CIImage(image: self), forKey: kCIInputImageKey)
        filter.setValue(intensity, forKey: kCIInputIntensityKey)
        filter.setValue(CIColor(color: color), forKey: kCIInputColorKey)
        return processedImage(from: filter, context: context)
    }
    
    func brightness(percent: CGFloat) -> UIImage {
        let context = CIContext(options: nil)
        guard let filter = CIFilter(name: "CIColorControls") else {
            return self
        }
        
        filter.setValue(CIImage(image: self), forKey: kCIInputImageKey)
        filter.setValue(percent, forKey: kCIInputBrightnessKey)
        return processedImage(from: filter, context: context)
    }
    
    func contrast(percent: CGFloat) -> UIImage {
        let context = CIContext(options: nil)
        guard let filter = CIFilter(name: "CIColorControls") else {
            return self
        }
        
        filter.setValue(CIImage(image: self), forKey: kCIInputImageKey)
        filter.setValue(percent, forKey: kCIInputContrastKey)
        return processedImage(from: filter, context: context)
    }
    
    private func processedImage(from filter: CIFilter, context: CIContext) -> UIImage {
        guard let output = filter.outputImage,
              let cgImage = context.createCGImage(output, from: output.extent) else {
            return self
        }
        
        return UIImage(cgImage: cgImage, scale: scale, orientation: imageOrientation)
    }
    
    public func apply(filters: [ColorFilter]) -> UIImage {
        return filters.reduce(self, { (image, filter) in filter.apply(to: image) })
    }
    
}
