ColorArray
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © kaigouthro
//@version=5

import kaigouthro/calc/5
import kaigouthro/hsvColor/15 as h

// @description Color Array Resizer/Maker.
// Input up to 10 colors, or an array of colors as an argument
// set the desired output size of colors to a new color array
// NOTE: it pushes to the array, so not meant to be used on reassign,
// so . ! to (:=)
library('ColorArray',true)

// @function Helper
anySize(size,_c,bool _switchMode = false)=>
    cols             = array.size(_c) -1
    color[] colray   = array.new_color()
    int[]   percol   = calc.split(size,cols)
    _c2              = array.get(_c,0)
    for k            = 1 to cols 
        _count       = array.get(percol,k-1)
        _c1          = _c2
        _c2         := array.get(_c,k)
        for i        = 1 to _count 
            switch _count 
                1 => array.push(colray, _c2)
                =>
                    switch 
                        _switchMode => array.push(colray, h.hsl_gradient(i, 1, _count, _c1,_c2))
                        => array.push(colray, h.hsv_gradient(i, 1, _count, _c1,_c2))

    colray

// @function Color Gradient for Two through ~any~ amount of colors 
// (1-10 input colors, any more, use an array of cols as input)
// @param _array Your own color array (no size limit)
// @param _1  Color input #  1
// @param _2  Color input #  2
// @param _3  Color input #  3 (Optional)
// @param _4  Color input #  4 (Optional)
// @param _5  Color input #  5 (Optional)
// @param _6  Color input #  6 (Optional)
// @param _7  Color input #  7 (Optional)
// @param _8  Color input #  8 (Optional)
// @param _9  Color input #  9 (Optional)
// @param _10 Color input # 10 (Optional)
// @param _mode Switch to Alt HSL mode (i highly suggest fewer colors and larger size for this mode.)
// @returns array of colors to specified size.
export makeGradient(int size, color _1, color _2, color _3, color _4, color _5, color _6, color _7, color _8, color _9, color _10 , bool _mode = false )=>  
    _array = array.from(_1,  _2,  _3,  _4,  _5,  _6,  _7,  _8,  _9,  _10)  
    anySize(size, _array, _mode)
export makeGradient(int size, color _1, color _2, color _3, color _4, color _5, color _6, color _7, color _8, color _9            , bool _mode = false )=>  
    _array = array.from(_1,  _2,  _3,  _4,  _5,  _6,  _7,  _8,  _9)    
    anySize(size, _array, _mode)
export makeGradient(int size, color _1, color _2, color _3, color _4, color _5, color _6, color _7, color _8                      , bool _mode = false )=>  
    _array = array.from(_1,  _2,  _3,  _4,  _5,  _6,  _7,  _8)    
    anySize(size, _array, _mode)
export makeGradient(int size, color _1, color _2, color _3, color _4, color _5, color _6, color _7                                , bool _mode = false )=>  
    _array = array.from(_1,  _2,  _3,  _4,  _5,  _6,  _7)    
    anySize(size, _array, _mode)
export makeGradient(int size, color _1, color _2, color _3, color _4, color _5, color _6                                          , bool _mode = false )=>  
    _array = array.from(_1,  _2,  _3,  _4,  _5,  _6)    
    anySize(size, _array, _mode)
export makeGradient(int size, color _1, color _2, color _3, color _4, color _5                                                    , bool _mode = false )=>  
    _array = array.from(_1,  _2,  _3,  _4,  _5)    
    anySize(size, _array, _mode)
export makeGradient(int size, color _1, color _2, color _3, color _4                                                              , bool _mode = false )=>  
    _array = array.from(_1,  _2,  _3,  _4)    
    anySize(size, _array, _mode)
export makeGradient(int size, color _1, color _2, color _3                                                                        , bool _mode = false )=>  
    _array = array.from(_1,  _2,  _3)  
    anySize(size, _array, _mode)
export makeGradient(int size, color _1, color _2                                                                                  , bool _mode = false )=>  
    _array = array.from(_1,  _2)  
    anySize(size, _array, _mode)
export makeGradient(int size, color[] _array                                                                                      , bool _mode = false )=>  
    anySize(size, _array, _mode)



// @function Multiple Color Fader (Negative Limit, Negative strong, Negative mild, neutral, Positive mild, Positive strong, Positive limit)
// @param _source (float   ) input value to follow
// @param _mid    (float   ) midpoint ( 0 for osc)
// @param _colsin (color[] ) colors to generate the fades
// @param _th     (float   ) 0-1,threshold to first level
// @param _thmax  (float   ) 0-1,threshold to second level 
// @returns color output
export fade(float _source, float  _mid , color[] _colsin, float _th =0.01, float _thmax = 0.05)  =>  //   {
    var color hc3 = na,var color lc3 = na,var color hc2 = na, var color lc2 = na
    var color hc1 = na,var color lc1 = na,var color out = na, var _limit = 0. 
    var _cols  = makeGradient(6,_colsin), varip float src  =  0
    varip _src =  float(na)
    _s3a   =   array.get(_cols, 0)
    _s2a   =   array.get(_cols, 1)
    _s1a   =   array.get(_cols, 2)
    _s1b   =   array.get(_cols, 3)
    _s2b   =   array.get(_cols, 4)
    _s3b   =   array.get(_cols, 5)
    _1     =   math.max(0.01,math.min(_th,_thmax * 0.99 ))
    _2     =   math.min(0.99,math.max(_1*1.01 ,_thmax   ))
    _3     =   1.01
    _src   :=  nz(_source)
    _limit :=  math.max(_limit, calc.gapSize(_src,_mid))
    src    :=  (calc.percentOfDistance(calc.gapSize(_src,_mid) , 0 , _limit) *math.sign(_src-_mid)) 
    hc3    :=  h.hsv_gradient( src ,  _2 ,   _3 , _s2b  , _s3b  ) 
    hc2    :=  h.hsv_gradient( src ,  _1 ,   _2 , _s1b  ,  hc3  ) 
    hc1    :=  h.hsv_gradient( src ,  0  ,   _1 , lc2   ,  hc2  ) 
    lc3    :=  h.hsv_gradient( src , -_3 , - _2 , _s3a  , _s2a  ) 
    lc2    :=  h.hsv_gradient( src , -_2 , - _1 , lc3   , _s1a  ) 
    lc1    :=  h.hsv_gradient( src , -_1 ,   0  , lc2   ,  hc2  ) 
    out    :=  h.hsv_gradient( src , -_1 ,   _1 , lc1   ,  hc1  )


//@function Focus color to an array position
//@param   _source (float)       
//@param   _values (floa)       
//@param   _colss  (color[]) Colors to Use, 2 or more
//@param   _mode   (bool) Optional color from array val
//@returns Color array with focused color 
focus(_source , _values, _cols,bool _mode = false )=>
    size = array.size(_values)
    _colarray = makeGradient(size+1,_cols)
    _colors = array.new_color(size)
    _pow = 1/math.pow(size,1/3.)
    _dist = calc.gapSize(_source,array.min(_values))/array.range(_values)
    for [_i,_val] in _values
        _d = switch 
            _mode => calc.gapSize(_val,array.min(_values))/array.range(_values)
            => _i / size
        _weight = math.pow(calc.gapSize(_dist,_d ), _pow )
        array.set(_colors,_i, array.get(_cols,int(array.size(_colarray)*_weight)))
    array.set(_colors,math.floor(_dist *size ),array.get(_cols,0))
    _colors
