import Foundation
import Metal

public class MaskedCircleAuraRenderable: ConfiguredQuadRenderable<MaskedCircleAuraRenderable.Config> {
    
    public struct Config: QuadRenderConfiguration {
        
        internal let display_size: ADVector2
        internal let fractal_noise_x: ADFloat
        internal let fractal_noise_y: ADFloat
        internal let fractal_noise_z: ADFloat
        internal let fractal_uniform_scale: ADFloat
        
        internal let grain_noise_z: ADFloat
        internal let grain_noise_scale: ADFloat
        
        internal let mask_radius: ADFloat
        internal let mask_center_x: ADFloat
        internal let mask_center_y: ADFloat
        internal let mask_edge_fade: ADFloat
        internal let mask_min_value_scalar: ADFloat
        
        internal let background_color: ADVector3
        internal let color_a: ADVector3
        internal let color_b: ADVector3
        internal let color_c: ADVector3
        internal let dark_color_a: ADVector3
        internal let dark_color_b: ADVector3
        internal let dark_color_c: ADVector3
        
        internal let dark_mix_point_start: ADFloat
        internal let dark_mix_point_background: ADFloat
        internal let dark_mix_point_backgroundA: ADFloat
        internal let dark_mix_point_AB: ADFloat
        internal let dark_mix_point_BC: ADFloat
        internal let dark_mix_point_end: ADFloat
        
        internal let mix_point_start: ADFloat
        internal let mix_point_background: ADFloat
        internal let mix_point_backgroundA: ADFloat
        internal let mix_point_AB: ADFloat
        internal let mix_point_BC: ADFloat
        internal let mix_point_end: ADFloat
        
        public init(
            displaySize: ADVector2 = .ones,
            fractalNoiseX: ADFloat = .zero,
            fractalNoiseY: ADFloat = .zero,
            fractalNoiseZ: ADFloat = .zero,
            fractalUniformScale: ADFloat = .zero,
            grainNoiseZ: ADFloat = .zero,
            grainNoiseScale: ADFloat = 1.0,
            
            maskRadius: ADFloat = 0.25,
            maskCenterX: ADFloat = 0.5,
            maskCenterY: ADFloat = 0.5,
            maskEdgeFade: ADFloat = 0.3,
            maskMinValueScalar: ADFloat = 0.3,
            
            backgroundColor: ADVector3 = .zero,
            colorA: ADVector3 = .zero,
            colorB: ADVector3 = .init(x: 0.5, y: 0.5, z: 0.5),
            colorC: ADVector3 = .ones,
            darkColorA: ADVector3 = .init(x: 0.1, y: 0.1, z: 0.1),
            darkColorB: ADVector3 = .init(x: 0.07, y: 0.07, z: 0.07),
            darkColorC: ADVector3 = .init(x: 0.02, y: 0.02, z: 0.02),
            
            darkMixPointStart: ADFloat = -0.2,
            darkMixPointBackground: ADFloat = -0.1,
            darkMixPointBackgroundA: ADFloat = 0.0,
            darkMixPointAB: ADFloat = 0.2,
            darkMixPointBC: ADFloat = 0.4,
            darkMixPointEnd: ADFloat = 2.0,
            
            mixPointStart: ADFloat = 0.0,      // Below zero doesn't really matter
            mixPointBackground: ADFloat = 0.1,
            mixPointBackgroundA: ADFloat = 0.2,
            mixPointAB: ADFloat = 0.3,
            mixPointBC: ADFloat = 0.4,
            mixPointEnd: ADFloat = 2.0) {
                
            display_size = displaySize
            fractal_noise_x = fractalNoiseX
            fractal_noise_y = fractalNoiseY
            fractal_noise_z = fractalNoiseZ
            fractal_uniform_scale = fractalUniformScale
            grain_noise_z = grainNoiseZ
            grain_noise_scale = grainNoiseScale
            
            mask_radius = maskRadius
            mask_center_x = maskCenterX
            mask_center_y = maskCenterY
            mask_edge_fade = maskEdgeFade
            mask_min_value_scalar = maskMinValueScalar
                
            background_color = backgroundColor
            color_a = colorA
            color_b = colorB
            color_c = colorC
            dark_color_a = darkColorA
            dark_color_b = darkColorB
            dark_color_c = darkColorC
            
            dark_mix_point_start = darkMixPointStart
            dark_mix_point_background = darkMixPointBackground
            dark_mix_point_backgroundA = darkMixPointBackgroundA
            dark_mix_point_AB = darkMixPointAB
            dark_mix_point_BC = darkMixPointBC
            dark_mix_point_end = darkMixPointEnd
                
            mix_point_start = mixPointStart
            mix_point_background = mixPointBackground
            mix_point_backgroundA = mixPointBackgroundA
            mix_point_AB = mixPointAB
            mix_point_BC = mixPointBC
            mix_point_end = mixPointEnd
        }
        
        public static var defaultConfiguration: Config {
            return Config()
        }
    }
    
    override public var configureAction: ConfigureAction {
        return { encoder in
            super.configureAction(encoder)
        }
    }
    
    override var fragmentShaderName: String {
        return "masked_circle_aura_frag"
    }
}
