lib_retracement_label
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © robbatt

//@version=5
import robbatt/lib_plot_objects/32 as D
import robbatt/lib_pivot/45 as P
import robbatt/lib_priceaction/6 as PA

// @description creates a retracement label between the origin and target of a retracement, updating it's position (via draw) when the target moves.
library("lib_retracement_label", overlay = true)

export type RetracementLabel
    chart.point move_endpoint // start and retracement point inside center_label
    D.CenterLabel center_label

export create_tooltip(string name = '', float min, float max, float tol_min, float tol_max) =>
    var string tooltip_format_exact = "{0} {1}"
    var string tooltip_format_range = "{0} {1} - {2}"
    var string tolerance_format = "{0}\nTolerance ({1} - {2})"

    tooltip = min == max 
     ? str.format(tooltip_format_exact, name, min, tol_min, tol_max)
     : str.format(tooltip_format_range, name, min, max, tol_min, tol_max)

    if (tol_min != min or tol_max != max) and not na(tol_min) and not na(tol_max)
        tooltip := str.format(tolerance_format, tooltip, tol_min, tol_max)
    
    tooltip


export method update(RetracementLabel this) =>
	ratio = math.round(PA.retracement_ratio(this.center_label.points.get(0).price, this.move_endpoint.price, this.center_label.points.get(1).price),3)
    txt = str.tostring(ratio)
	this.center_label.center_label.txt := txt


//@function Creates a new RetracementLabel object.
export method create_retracement_label(D.Line this, chart.point move_endpoint, D.LabelArgs args, string tooltip = na) =>
    ratio = math.round(PA.retracement_ratio(this.start.price, move_endpoint.price, this.end.price),3)
    txt = str.tostring(ratio)
	RetracementLabel.new(move_endpoint, this.create_center_label(txt, args, tooltip)) 

//@function Creates a new RetracementLabel object.
export method create_retracement_label(D.Line this, P.Pivot move_end, D.LabelArgs args, string tooltip = na) =>
    this.create_retracement_label(move_end.point, args, tooltip)


export method enqueue(RetracementLabel[] id, RetracementLabel item, int max = 0) =>
    if not na(id) and not na(item)
        id.unshift(item)
        if max > 0 and id.size() > max
            id.pop()
    id

export method draw(RetracementLabel this) =>
    if na(this) ? false : not na(this.center_label) and not na(this.move_endpoint)
        cl = this.center_label
        l = cl.center_label
        l.txt := str.tostring(math.round(PA.retracement_ratio(cl.points.get(0).price, this.move_endpoint.price, cl.points.get(1).price), 3))
        cl.draw()
	this

export method draw(RetracementLabel[] this) =>
    if not na(this)
        for l in this
            l.draw()
    this

export method delete(RetracementLabel this) =>
    if not na(this)
        this.center_label.delete()
    this

export method delete(RetracementLabel[] this) =>
    if not na(this)
        for l in this
            l.delete()
    this


highest_offset = -ta.highestbars(30)
prev_highest_offset = highest_offset[31] + 31
lowest_offset = -ta.lowestbars(30)
prev_lowest_offset = lowest_offset[31] + 31

if barstate.islast
	var origin = chart.point.new(time[prev_highest_offset], bar_index[prev_highest_offset], high[prev_highest_offset])
	var mid = chart.point.new(time[lowest_offset], bar_index[lowest_offset], high[lowest_offset])
	var target = chart.point.new(time[highest_offset], bar_index[highest_offset], high[highest_offset])
	var args = D.LineArgs.new(color.gray, line.style_dashed)
	var retracement_line = origin.create_line(target, args).draw()
	var retracement_tooltip = create_tooltip('name label', 50, 100, 45, 105) 
	var retracement_label_args = D.LabelArgs.new(color.white, #00000000, style = label.style_label_center, size = size.normal)
	var retracement_label = retracement_line.create_retracement_label(mid, retracement_label_args, retracement_tooltip)
	target.update(time, bar_index, close)
	retracement_line.draw()
	retracement_label.update()
	retracement_label.draw()

	