CyclicRsiLib
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © RozaniGhani-RG

//@version=5

// @description TODO: add library description here
library('CyclicRsiLib')

//  0. AlertFrequency
//  1. CyclicRSI
//  2. AddToZigzag
//  3. UpdateZigzag
//  4. BoolZigzag
//  4. NoiseSwitch
//  5. StringSwitch
//  6. LineGray
//  7. LabelDir
//  8. TernaryLabel
//  9. TernaryColor
// 10. ColorNewSwitch

// —————————————————————————————————————————————————————————————————————————————   0. AlertFrequency {
// @function : AlertFrequency
// @param    : _string
// @returns  : _freq
export AlertFrequency(string _string) =>
    _freq = switch _string
        'Once Per Bar Close' => alert.freq_once_per_bar_close
        'Once Per Bar'       => alert.freq_once_per_bar
        'All'                => alert.freq_all
// }
// —————————————————————————————————————————————————————————————————————————————   1. CyclicRSI {
// @function : CyclicRSI
// @param    : _source, _length, _expression
// @returns  : osc
// Credits to WhenToTrade
export CyclicRSI(float _source, int _length, string _expression) =>
	//TODO : add function body and return value here
    crsi       = 0.0
    vibration  = 10
    torque     = 0.618 / (vibration + 1)
    phasingLag = (vibration - 1) / 0.618
    
    rsi        = ta.rsi(_source, _length)
    crsi      := torque * (2 * rsi - rsi[phasingLag]) + (1 - torque) * nz(crsi[1])
	osc = switch _expression
        'Cyclic RSI' => crsi
        'RSI'        => rsi
    [osc, crsi, rsi]
// }
// —————————————————————————————————————————————————————————————————————————————   2. AddToZigzag {
// @function : AddToZigzag
// @param    : _id, value, max_array_size
// @returns  : array.unshift, array.pop
// Credits to LonesomeTheBlue
export AddToZigzag(simple float[] _id, float value, int max_array_size = 10) =>
    array.unshift(_id, bar_index)
    array.unshift(_id, value)
    if array.size(_id) > max_array_size
        array.pop(_id)
        array.pop(_id)
// }
// —————————————————————————————————————————————————————————————————————————————   3. UpdateZigzag {
// @function : UpdateZigzag
// @param    : _id, value, max_array_size, dir
// @returns  : AddToZigzag, array.set
// Credits to LonesomeTheBlue
export UpdateZigzag(simple float[] _id, float value, int max_array_size = 10, int dir = 0) =>
    if array.size(_id) == 0
        AddToZigzag(_id, value, max_array_size)
    else
        if dir == 1 and value > array.get(_id, 0) or dir == -1 and value < array.get(_id, 0)
            array.set(_id, 0, value)
            array.set(_id, 1, bar_index)
        0.
// }
// —————————————————————————————————————————————————————————————————————————————   4. BoolZigzag {
// @function : BoolZigzag
// @param    : ph, pl, dirchanged, _id, dir
// @returns  : AddToZigzag, UpdateZigzag
// Credits to LonesomeTheBlue
export BoolZigzag(float ph, float pl, float dirchanged, simple float[] _id, int dir) =>
    if ph or pl
        if dirchanged
            AddToZigzag(_id, dir == 1 ? ph : pl)
        else
            UpdateZigzag(_id, dir == 1 ? ph : pl, dir)
// }
// —————————————————————————————————————————————————————————————————————————————   4. NoiseSwitch {
// @function : NoiseSwitch
// @param    : _string, _id
// @returns  : FilterNoise
export NoiseSwitch(string _string, simple float[] _id) =>
    FilterNoise = switch _string
        '35 < value < 65' => array.get(_id, 2) <= 65 and array.get(_id, 2) >= 35
        '50 < value < 65' => array.get(_id, 2) >= 35
        '30 < value < 50' => array.get(_id, 2) <= 65
    FilterNoise
// }
// —————————————————————————————————————————————————————————————————————————————   5. StringSwitch {
// @function : StringSwitch
// @param    : _string
// @returns  : str_OB, str_OS
export StringSwitch(string _string) =>
    [str_OB, str_OS] = switch _string
        'both'  => ['OB\n▼', '▲\nOS']
        'OB/OS' => [   'OB', 'OS']
        'arrow' => [    '▼', '▲']
    [str_OB, str_OS] 
// }
// —————————————————————————————————————————————————————————————————————————————   6. LineGray {
// @function : LineGray
// @param    : _id
// @returns  : LineGray
export LineGray(simple float[] _id) =>
    line.new(
     x1    = math.round(array.get(_id, 1)),
     y1    =            array.get(_id, 0),
     x2    = math.round(array.get(_id, 3)),
     y2    =            array.get(_id, 2),
     color = color.gray,
     width = 2)
// }
// —————————————————————————————————————————————————————————————————————————————   7. LabelDir {
// @function : LabelDir
// @param    : _id, _string, _color, _dir
// @returns  : LabelDir
export LabelDir(simple float[] _id, string _string, color _color, float _dir) =>
    label.new(
     x         = math.round(array.get(_id, 1)),
     y         =            array.get(_id, 0),
     text      = _string,
     color     = color.new(color.blue, 100),
     textcolor = _color,
     style     = _dir == 1 ? label.style_label_down : label.style_label_up)
// }
// —————————————————————————————————————————————————————————————————————————————   8. TernaryLabel {
// @function : TernaryLabel
// @param    : _dir, _bool1, _bool2, _string1, _string2
// @returns  : str_label
export TernaryLabel(int _dir, bool _bool1, bool _bool2, string _string1, string _string2) =>
    str_label = _dir == 1 ?
     _bool1 ? _string1 : '◍' :
     _bool2 ? _string2 : '◍'
// }
// —————————————————————————————————————————————————————————————————————————————   9. TernaryColor {
// @function : TernaryColor
// @param    : _dir, _bool1, _bool2
// @returns  : col_label
export TernaryColor(int _dir, bool _bool1, bool _bool2) =>
    col_label = _dir == 1 ?
     _bool1 ? color.red  : color.teal :
     _bool2 ? color.teal : color.red
// }
// —————————————————————————————————————————————————————————————————————————————  10. ColorNewSwitch {
// @function : ColorNewSwitch
// @param    : _dir, _bool1, _bool2
// @returns  : NewColor
export ColorNewSwitch(int _int1 = 0, bool _bool, int _int2 = 0, int _int3 = 0) =>
    _color = switch _int1
        0 => color.teal
        1 => color.red
        2 => color.yellow
    _transp1 = switch _int2
        0 => 0
        1 => 65
    _transp2 = switch _int3
        0 => 50
        1 => 100
    cn = color.new(_color, _bool ? _transp1 : _transp2)
    cn
// }
    