//
//  GradientView.swift
//  App
//
//  Created by James Magahern on 8/14/20.
//

import UIKit

class GradientView: UIImageView
{
    enum Direction {
        case horizontal
        case vertical
    }
    
    var direction: Direction = .horizontal {
        didSet { image = nil; setNeedsLayout() }
    }
    
    var colors: [UIColor] = [] {
        didSet { image = nil; setNeedsLayout() }
    }
    
    private var generatedImageSize: CGSize?
    
    convenience init(direction: Direction, colors: [UIColor]) {
        self.init(image: nil)
        self.direction = direction
        self.colors = colors
        
        registerForTraitChanges([UITraitUserInterfaceStyle.self]) { [weak self] (traitEnvironment: Self, previousTraitCollection) in
            self?.image = nil
            self?.setNeedsLayout()
        }
    }
    
    private func gradientImage(forSize size: CGSize) -> UIImage? {
        guard size.width > .leastNonzeroMagnitude && size.height > .leastNonzeroMagnitude else { return nil }
        
        var image: UIImage? = nil
        UIGraphicsBeginImageContext(size)
        if let context = UIGraphicsGetCurrentContext() {
            let gradientColorsArray = self.colors.map { $0.cgColor }
            
            if let gradient = CGGradient(colorsSpace: nil, colors: gradientColorsArray as CFArray, locations: nil) {
                if direction == .horizontal {
                    context.drawLinearGradient(gradient, start: .zero, end: CGPoint(x: size.width, y: 0.0), options: CGGradientDrawingOptions())
                } else if direction == .vertical {
                    context.drawLinearGradient(gradient, start: CGPoint(x: size.width / 2, y: 0), end: CGPoint(x: size.width / 2, y: size.height), options: CGGradientDrawingOptions())
                }
            }
            
            image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext();
        }
        
        return image
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        var needsNewImage: Bool = image == nil
        if let generatedImageSize = generatedImageSize {
            if generatedImageSize != bounds.size {
                needsNewImage = true
            }
        } else {
            needsNewImage = true
        }
        
        if needsNewImage {
            image = gradientImage(forSize: bounds.size)
            generatedImageSize = bounds.size
        }
    }
}
