Profile Any Indicator [Kioseff Trading]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © KioseffTrading

//@version=5
indicator("Profile Any Indicator [Kioseff Trading]", max_boxes_count = 500,  max_lines_count = 500)


src                     = input.source(defval = open, title = "Indicator", group = "Primary Settings")
profSize                = input.int   (defval = 1, minval = 1, title = "Profile Bar Size", group = "Primary Settings")
rows                    = input.int   (defval = 40, minval = 6, maxval = 500, title = "Rows", step = 25, group = "Primary Settings") - 1
ori                     = input.string(defval = "Left", title = "Orientation", options = ["Left", "Right"], group = "Primary Settings")
plo                     = input.bool  ( defval = false, title = "Plot My Indicator In The Current Pane", group = "Do You Want To Plot Your Indicator In The Current New Pane?")
ploc                    = input.color(defval = color.lime, title = "Color", group = "Do You Want To Plot Your Indicator In The Current New Pane?")

nvacol                  = input.color(defval = color.new(color.blue, 75), title = 'NON-VA Color', group = "NON-VA")

poc                     = input.bool(defval = true, title = 'POC', group = "POC", inline = "1"), 
pocol                   = input.color(defval = color.new(color.red, 50), group = "POC", title = "", inline = "1"),
pocw                    = input.int(defval = 2, minval = 1, maxval = 4, title = 'Width', group = "POC", inline = "1")

vcalc                   = input.float(defval = 70, minval = 5, maxval = 95, title = "Value Area %", group = "Value Area")
val                     = input.bool(defval = true, title = "VA Lines", group = "Value Area", inline = "2")
vacolL                  = input.color(defval = color.new(color.blue, 75), title = "", group = "Value Area", inline = "2")
vaw                     = input.int(defval = 2, minval = 1, maxval = 4, title = "Width", group = "Value Area", inline = "2")
vacol                   = input.color(defval = color.new(color.yellow, 75), title = '"Value Area" Color', group = "Value Area")
vafill                  = input.color(defval = color.new(color.gray, 75), title = "Value Area Fill Color", group = "Value Area")
  
  
var int   [] timeArray  = array.new_int()
var float [] dist       = array.new_float()
var int   [] x2         = array.new_int(rows + 1, 5)
var          vh         = matrix.new<float>(1, 1)


array.unshift(timeArray, math.round(time)) 

if time >= chart.left_visible_bar_time and time <= chart.right_visible_bar_time
    matrix.add_col(vh)
    matrix.set(vh, 0, matrix.columns(vh) - 1, src)


if barstate.islast

    [pos, n] = switch ori
        "Left" =>  [chart.left_visible_bar_time , array.indexof(timeArray,  chart.left_visible_bar_time)]
        =>         [chart.right_visible_bar_time, array.indexof(timeArray, chart.right_visible_bar_time)]


    calc = (matrix.max(vh) - matrix.min(vh)) / (rows + 1)

    for i = 0 to rows
        array.push(dist, matrix.min(vh) + (i * calc))
    

    for i = 1 to matrix.columns(vh) - 1
        for x = 0 to array.size(dist) - 1
            if matrix.get(vh, 0, i) >= matrix.get(vh, 0, i - 1)
                if array.get(dist, x) >= matrix.get(vh, 0, i - 1) and array.get(dist, x) <= matrix.get(vh, 0, i)
                    array.set(x2, x, array.get(x2, x) + profSize)
            
            else 
                
                if array.get(dist, x) >= matrix.get(vh, 0, i) and array.get(dist, x) <= matrix.get(vh, 0, i - 1)
                    array.set(x2, x, array.get(x2, x) + profSize)

    boc = array.new_box()
    for i = 1 to rows
        
        right = array.get(timeArray, n + array.get(x2, i))
        
        if ori == "Left"
            switch math.sign(n - array.get(x2, i))

                -1 => right := chart.right_visible_bar_time
                =>    right := array.get(timeArray, n - array.get(x2, i))



        array.push(boc, box.new(pos, array.get(dist, i - 1), 
             right, array.get(dist, i), xloc = xloc.bar_time, border_color = 
             nvacol, bgcolor = nvacol
             ))
        if i == rows 
            array.push(boc, box.new(pos, array.get(dist, array.size(dist) - 1), 
                     right, array.get(dist, array.size(dist) - 1) + calc, xloc = xloc.bar_time, border_color = 
                     nvacol, bgcolor = nvacol
                     ))


    array.shift(x2), nx = array.indexof(x2, array.max(x2))
    nz = nx - 1, nz2 = 0, nz3 = 0, nz4 = 0
    for i = 0 to array.size(x2) - 1
        if nz > -1 and nx <= array.size(x2) - 1
            switch array.get(x2, nx) >= array.get(x2, nz)
                true => nz2 += array.get(x2, nx), nx += 1
                =>      nz2 += array.get(x2, nz), nz -= 1
                
        else if nz <= -1
            nz2 += array.get(x2, nx), nx += 1
        else if nx >= array.size(x2)
            nz2 += array.get(x2, nz), nz -= 1
        if nz2 >= array.sum(x2) * (vcalc / 100)
            nz3 := nx <= array.size(x2) - 1 ? nx : array.size(x2) - 1, nz4 := nz <= -1 ? 0 : nz
            break



    for i = nz3 to nz4
        box.set_border_color(array.get(boc, i), vacol)
        box.set_bgcolor(array.get(boc, i), vacol)
    if poc 
        var pocL = line(na)
        y = math.avg(box.get_top(array.get(boc, array.indexof(x2, array.max(x2)))), box.get_bottom(array.get(boc, array.indexof(x2, array.max(x2)))))
        if na(pocL)
            pocL := line.new(chart.left_visible_bar_time, y, chart.right_visible_bar_time, y, xloc = xloc.bar_time, color = pocol, width = pocw)
        else 
            line.set_xy1(pocL, chart.left_visible_bar_time, y)
            line.set_xy2(pocL, chart.right_visible_bar_time, y)
    if val 
        var vaup = line(na), var vadn = line(na)
        ydn = box.get_bottom(array.get(boc, nz3)), yup = box.get_top(array.get(boc, nz4))

        if na(vaup)

            vadn := line.new(chart.left_visible_bar_time, ydn, chart.right_visible_bar_time, ydn, xloc = xloc.bar_time, color = vacolL, width = vaw)
            vaup := line.new(chart.left_visible_bar_time, yup, chart.right_visible_bar_time, yup, xloc = xloc.bar_time, color = vacolL, width = vaw)

        else 

            line.set_xy1(vadn, chart.left_visible_bar_time, ydn), line.set_xy2(vadn, chart.right_visible_bar_time, ydn)
            line.set_xy1(vaup, chart.left_visible_bar_time, yup), line.set_xy2(vaup, chart.right_visible_bar_time, yup)

        linefill.new(vadn, vaup, vafill)

    if src == open
        var tab = table.new(position.middle_center, 1, 1)
        table.cell(tab, 0, 0, text = "Add Your Indicator In the Settings!", text_size = size.huge, text_color = color.white)    
    
plot(plo ? src : na, color = ploc, title = "My Indicator")