import Foundation
import simd

public enum SunoColorPalette {
    
    case backgroundDotCom
    
    case popcornYellow
    case sunsetOrange
    case bubblegumPink
    case vacationViolet
    case fadedBlue
    case wallpaperGreen
    case discoGold
    case rubikRed
    case vintageCherry
    case lavaLavender
    case laserBlue
    case neonLime
    case playgroundSand
    case californiaTan
    case arcadeMaroon
    case mixtapeMauve
    case electricBlue
    case cadillacMoss
    case custom(_ r: Float, _ g: Float, _ b: Float)
    
    public var floatThree: SIMD3<Float> {
        switch self {
        case .backgroundDotCom:
            return SIMD3<Float>(0.050980392156862744, 0.03137254901960784, 0.03137254901960784)
        case .popcornYellow:
            return SIMD3<Float>(1, 0.8627450980392157, 0.5019607843137255)
        case .sunsetOrange:
            return SIMD3<Float>(1, 0.4470588235294118, 0.13333333333333333)
        case .bubblegumPink:
            return SIMD3<Float>(1, 0.5450980392156862, 0.6274509803921569)
        case .vacationViolet:
            return SIMD3<Float>(0.8823529411764706, 0.6941176470588235, 0.9725490196078431)
        case .fadedBlue:
            return SIMD3<Float>(0.3176470588235294, 0.5490196078431373, 0.7647058823529411)
        case .wallpaperGreen:
            return SIMD3<Float>(0.7529411764705882, 0.803921568627451, 0.5411764705882353)
        case .discoGold:
            return SIMD3<Float>(1, 0.7215686274509804, 0.0)
        case .rubikRed:
            return SIMD3<Float>(0.9490196078431372, 0.25098039215686274, 0.09411764705882353)
        case .vintageCherry:
            return SIMD3<Float>(0.7803921568627451, 0.23921568627450981, 0.4)
        case .lavaLavender:
            return SIMD3<Float>(0.7686274509803922, 0.3843137254901961, 0.9019607843137255)
        case .laserBlue:
            return SIMD3<Float>(0.37254901960784315, 0.7725490196078432, 1)
        case .neonLime:
            return SIMD3<Float>(0.7647058823529411, 0.9058823529411765, 0.20392156862745098)
        case .playgroundSand:
            return SIMD3<Float>(0.7647058823529411, 0.615686274509804, 0.4)
        case .californiaTan:
            return SIMD3<Float>(0.6470588235294118, 0.27450980392156865, 0.0784313725490196)
        case .arcadeMaroon:
            return SIMD3<Float>(0.42745098039215684, 0.10980392156862745, 0.10980392156862745)
        case .mixtapeMauve:
            return SIMD3<Float>(0.5294117647058824, 0.050980392156862744, 0.45098039215686275)
        case .electricBlue:
            return SIMD3<Float>(0.06274509803921569, 0.0, 0.7529411764705882)
        case .cadillacMoss:
            return SIMD3<Float>(0.44313725490196076, 0.49411764705882355, 0.23137254901960785)
        case .custom(let r, let g, let b):
            return SIMD3<Float>(r, g, b)
        }
    }
}

public enum SunoTriColorSet {
    case redLVioletBlue         // Done
    case tanLaserBluePink       // Done
    case cherryYellowMoss       // Done
    case goldMossPink           // Done
    case orangeMauveLime        // Done
    case yellowOrangeBlue       // Done
    case mauveVioletGreen       // Done
    case fadedBlueGoldSand      // Done
    case maroonVioletRed        // Done
    case custom(_ base: SunoColorPalette, _ middle: SunoColorPalette, _ highlight: SunoColorPalette)
    
    //Middle
    public var colorA: SunoColorPalette {
        switch self {
        case .redLVioletBlue:
            return .rubikRed
        case .tanLaserBluePink:
            return .laserBlue
        case .cherryYellowMoss:
            return .popcornYellow
        case .goldMossPink:
            return .bubblegumPink
        case .orangeMauveLime:
            return .sunsetOrange
        case .yellowOrangeBlue:
            return .sunsetOrange
        case .mauveVioletGreen:
            return .vacationViolet
        case .fadedBlueGoldSand:
            return .discoGold
        case .maroonVioletRed:
            return .vacationViolet
        case .custom(_, let middle, _):
            return middle
        }
    }
    
    // Background
    public var colorB: SunoColorPalette {
        switch self {
        case .redLVioletBlue:
            return .electricBlue
        case .tanLaserBluePink:
            return .californiaTan
        case .cherryYellowMoss:
            return .vintageCherry
        case .goldMossPink:
            return .cadillacMoss
        case .orangeMauveLime:
            return .neonLime
        case .yellowOrangeBlue:
            return .popcornYellow
        case .mauveVioletGreen:
            return .wallpaperGreen
        case .fadedBlueGoldSand:
            return .playgroundSand
        case .maroonVioletRed:
            return .rubikRed
        case .custom(let base, _, _):
            return base
        }
    }
    
    // Top
    public var colorC: SunoColorPalette {
        switch self {
        case .redLVioletBlue:
            return .vacationViolet
        case .tanLaserBluePink:
            return .bubblegumPink
        case .cherryYellowMoss:
            return .cadillacMoss
        case .goldMossPink:
            return .discoGold
        case .orangeMauveLime:
            return .mixtapeMauve
        case .yellowOrangeBlue:
            return .electricBlue
        case .mauveVioletGreen:
            return .mixtapeMauve
        case .fadedBlueGoldSand:
            return .laserBlue
        case .maroonVioletRed:
            return .arcadeMaroon
        case .custom(_, _, let highlight):
            return highlight
        }
    }
    
    public var floatColorA: SIMD3<Float> {
        return colorA.floatThree
    }
    
    public var floatColorB: SIMD3<Float> {
        return colorB.floatThree
    }
    
    public var floatColorC: SIMD3<Float> {
        return colorC.floatThree
    }
    
    func mixSets(setA: SunoTriColorSet, setB: SunoTriColorSet, mixScalar: Float) ->
        (colorA: SIMD3<Float>, colorB: SIMD3<Float>, colorC: SIMD3<Float>) {
        
        let clampMix = simd_clamp(mixScalar, 0.0, 1.0);
        let aR = simd_mix(setA.floatColorA.x, setB.floatColorA.x, clampMix)
        let aG = simd_mix(setA.floatColorA.y, setB.floatColorA.y, clampMix)
        let aB = simd_mix(setA.floatColorA.z, setB.floatColorA.z, clampMix)
        let newMixA = simd_float3(x: aR, y: aG, z: aB)
        
        let bR = simd_mix(setA.floatColorB.x, setB.floatColorB.x, clampMix)
        let bG = simd_mix(setA.floatColorB.y, setB.floatColorB.y, clampMix)
        let bB = simd_mix(setA.floatColorB.z, setB.floatColorB.z, clampMix)
        let newMixB = simd_float3(x: bR, y: bG, z: bB)
        
        let cR = simd_mix(setA.floatColorC.x, setB.floatColorC.x, clampMix)
        let cG = simd_mix(setA.floatColorC.y, setB.floatColorC.y, clampMix)
        let cB = simd_mix(setA.floatColorC.z, setB.floatColorC.z, clampMix)
        let newMixC = simd_float3(x: cR, y: cG, z: cB)
        
        return (newMixA, newMixB, newMixC)
    }
}
