import Foundation
import UIKit
import Display
import ImageBlur

protocol PasscodeBackground {
    var size: CGSize { get }
    var backgroundImage: UIImage { get }
    var foregroundImage: UIImage { get }
}

final class GradientPasscodeBackground: PasscodeBackground {
    public private(set) var size: CGSize
    public private(set) var backgroundImage: UIImage
    public private(set) var foregroundImage: UIImage
    
    init(size: CGSize, backgroundColors: (UIColor, UIColor), buttonColor: UIColor) {
        self.size = size
        self.backgroundImage = generateImage(CGSize(width: 8.0, height: size.height), contextGenerator: { size, context in
            let gradientColors = [backgroundColors.1.cgColor, backgroundColors.0.cgColor] as CFArray
            var locations: [CGFloat] = [0.0, 1.0]
            let colorSpace = CGColorSpaceCreateDeviceRGB()
            let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors, locations: &locations)!
            context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
        })!
        self.foregroundImage = generateImage(CGSize(width: 1.0, height: 1.0), contextGenerator: { size, context in
            let bounds = CGRect(origin: CGPoint(), size: size)
            context.clear(bounds)
            if buttonColor != UIColor.clear {
                context.setFillColor(buttonColor.cgColor)
            } else {
                context.setFillColor(UIColor.white.withAlphaComponent(0.5).cgColor)
            }
            context.fill(bounds)
        })!
    }
}

final class ImageBasedPasscodeBackground: PasscodeBackground {
    public private(set) var size: CGSize
    public private(set) var backgroundImage: UIImage
    public private(set) var foregroundImage: UIImage
    
    init(image: UIImage, size: CGSize) {
        self.size = size
        
        let contextSize = size.aspectFilled(CGSize(width: 320.0, height: 320.0))
        let foregroundContext = DrawingContext(size: contextSize, scale: 1.0)
        let bounds = CGRect(origin: CGPoint(), size: contextSize)
        
        let filledImageSize = image.size.aspectFilled(contextSize)
        let filledImageRect = CGRect(origin: CGPoint(x: (contextSize.width - filledImageSize.width) / 2.0, y: (contextSize.height - filledImageSize.height) / 2.0), size: filledImageSize)
        
        foregroundContext.withFlippedContext { c in
            c.interpolationQuality = .medium
            c.draw(image.cgImage!, in: filledImageRect)
        }
        telegramFastBlurMore(Int32(contextSize.width), Int32(contextSize.height), Int32(foregroundContext.bytesPerRow), foregroundContext.bytes)
        telegramFastBlurMore(Int32(contextSize.width), Int32(contextSize.height), Int32(foregroundContext.bytesPerRow), foregroundContext.bytes)
        telegramFastBlurMore(Int32(contextSize.width), Int32(contextSize.height), Int32(foregroundContext.bytesPerRow), foregroundContext.bytes)
        telegramBrightenImage(Int32(contextSize.width), Int32(contextSize.height), Int32(foregroundContext.bytesPerRow), foregroundContext.bytes)
        
        foregroundContext.withFlippedContext { c in
            c.setFillColor(UIColor(white: 1.0, alpha: 0.1).cgColor)
            c.fill(bounds)
        }
        self.foregroundImage = foregroundContext.generateImage()!
        
        let backgroundContext = DrawingContext(size: contextSize, scale: 1.0)
        backgroundContext.withFlippedContext { c in
            c.interpolationQuality = .medium
            c.draw(image.cgImage!, in: filledImageRect)
        }
        telegramFastBlurMore(Int32(contextSize.width), Int32(contextSize.height), Int32(backgroundContext.bytesPerRow), backgroundContext.bytes)
        telegramFastBlurMore(Int32(contextSize.width), Int32(contextSize.height), Int32(backgroundContext.bytesPerRow), backgroundContext.bytes)
        telegramFastBlurMore(Int32(contextSize.width), Int32(contextSize.height), Int32(foregroundContext.bytesPerRow), foregroundContext.bytes)
        
        backgroundContext.withFlippedContext { context in
            context.setFillColor(UIColor(white: 0.0, alpha: 0.35).cgColor)
            context.fill(bounds)
        }
        self.backgroundImage = backgroundContext.generateImage()!
    }
}