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

//@version=5

// @description Functions to create labels, from simple to complex.
library("Labels", overlay=true)

string inputShowLabel = input.string(title="Show Label:", options=["labelSimple","labelLast","labelTextAndFloat","labelTextAndFloatSigFig","labelTextAndFloatDecimals"], defval="labelSimple")
int inputOffset = input.int(title="Label Offset", minval=0, maxval=20, defval=0)
int inputSigNumFig = input.int(defval=3, minval=1, title="Number of significant figures for the labelTextAndFloatSigFig function")
int inputDecimals = input.int(defval=3, minval=0, title="Number of decimal places for the labelTextAndFloatDecimals function")



// ===========================================//
//               SIMPLE LABEL                 //
// ===========================================//

// @function Creates a label each time a condition is true. All label parameters can be customised.
// @param _condition The condition which must evaluate true for the label to be printed.
// @param _x The x location.
// @param _y The y location.
// @param _text The text to print on the label.
// @param _color The colour of the label.
// @param _textColor The colour of the text.
// @param _style The style of the label.
// @param _yloc The y location type.
// @returns An unnamed label object with the supplied characteristics. To give it a name, assign the output of the function to a label variable, as in the examples below.

export labelSimple(bool _condition=true, int _x=bar_index, float _y=high, string _text="Your text here", color _color=color.white, color _textColor=color.black, string _style=label.style_label_down, string _yloc=yloc.price) =>
    if _condition
        label.new(x = _x, y = _y, text = _text, color=_color, textcolor=_textColor, style=_style, yloc=_yloc)
    else
        na

// mySimpleLabel1 is an example of supplying only a few of the parameters. The parameters that are not supplied will revert to the defaults.
var label mySimpleLabel1 = na
mySimpleLabel1 := labelSimple(_condition=inputShowLabel=="labelSimple", _text="Bender cracked\ncorn")

// mySimpleLabel2 is an example of supplying all parameters. Some parameters duplicate the defaults and some replace them.
var label mySimpleLabel2 = na
mySimpleLabel2 := labelSimple(_condition=barstate.islast and inputShowLabel=="labelSimple",_x=bar_index, _y=low, _text="and I don't care", _color=color.yellow, _textColor=color.gray, _style=label.style_label_up, _yloc=yloc.price)



// ===========================================//
//                + KEEP LAST                 //
//                + OFFSET                    //
// ===========================================//

// @function Creates a label each time a condition is true. All label parameters can be customised. + Option to keep only the most recent label. + Option to display the label a configurable number of bars ahead; otherwise the x location is fixed at the bar time.
// @param _offset How many bars ahead to draw the label.
// @param _keepLast If true (the default), keeps only the most recent label. If false, prints labels up to the TradingView limit.
// @param _condition The condition which must evaluate true for the label to be printed.
// @param _y The y location.
// @param _text The text to print on the label.
// @param _color The colour of the label.
// @param _textColor The colour of the text.
// @param _textAlign The alignment of the text.
// @param _style The style of the label.
// @param _yloc The y location type.
// @returns A named label object with the supplied characteristics. You can rename it, as in the second example below.

export labelLast(int _offset = 0, bool _keepLast = true, bool _condition=true, float _y=open, string _text="Your text here", color _color=color.white, color _textColor=color.black, string _textAlign=text.align_center, string _style=label.style_label_left, string _yloc=yloc.price) =>
    var label SCL_myLabelLast = na
    _timeblock1 = (time - time[1])
    _futureTime = time + (_timeblock1 * _offset)
    _x = _futureTime
    if _condition
        SCL_myLabelLast := label.new(x = _x, y = _y, text = _text, color=_color, textcolor=_textColor, textalign=_textAlign, style=_style, yloc=_yloc, xloc=xloc.bar_time)
    else
        na
    if _keepLast
        label.delete(SCL_myLabelLast[1])
    SCL_myLabelLast

// 1. Use this method of calling the function if you don't care what the name is.
labelLast(_condition=inputShowLabel=="labelLast",_text="labelLast", _offset=inputOffset)

// 2. Use this method if you want to rename the label.
// var label myLabelLast = na, myLabelLast := labelLast(_condition=inputShowLabel=="labelLast",_text="labelLast", _offset=inputOffset)


// ===========================================//
//                + FLOAT                     //
// ===========================================//

// @function Creates a label each time a condition is true. All label parameters can be customised. Option to keep only the most recent label. Option to display the label a configurable number of bars ahead; otherwise the x location is fixed at the bar time. + Prints (optional) text and a floating-point number on the next line.
// @param _offset How many bars ahead to draw the label.
// @param _float The floating-point number that you want to display on the label.
// @param _keepLast If true (the default), keeps only the most recent label. If false, prints labels up to the TradingView limit.
// @param _condition The condition which must evaluate true for the label to be printed.
// @param _y The y location.
// @param _text The text to print on the label.
// @param _color The colour of the label.
// @param _textColor The colour of the text.
// @param _textAlign The alignment of the text.
// @param _style The style of the label.
// @param _yloc The y location type.
// @returns A named label object with the supplied characteristics.

export labelTextAndFloat(int _offset = 0, float _float=123.456, bool _keepLast = true, bool _condition=true, float _y=open, string _text="My lovely float:", color _color=color.white, color _textColor=color.black, string _textAlign=text.align_center, string _style=label.style_label_left, string _yloc=yloc.price) =>
    string _floatText = not na (_float) ? str.tostring(_float) : na
    string _newline = not na(_text) ? '\n' : na
    var label SCL_myLabelTextAndFloat = na
    _timeblock1 = (time - time[1])
    _futureTime = time + (_timeblock1 * _offset)
    if _condition
        SCL_myLabelTextAndFloat := label.new(x = _futureTime, y = _y, text = _text+_newline+_floatText, color=_color, textcolor=_textColor, textalign=_textAlign, style=_style, yloc=_yloc, xloc=xloc.bar_time)
    else
        na
    if _keepLast
        label.delete(SCL_myLabelTextAndFloat[1])
    SCL_myLabelTextAndFloat

labelTextAndFloat(_condition=inputShowLabel=="labelTextAndFloat", _float=close[1], _offset=inputOffset)



// ===========================================//
//      + FLOAT TO SIGNIFICANT FIGURES        //
// ===========================================//

// @function Creates a label each time a condition is true. All label parameters can be customised. Option to keep only the most recent label. Option to display the label a configurable number of bars ahead; otherwise the x location is fixed at the bar time. Prints (optional) text and a floating-point number on the next line + to a given number of significant figures.
// @param _offset How many bars ahead to draw the label.
// @param _sigNumFig The number of significant figures to display the floating-point number to.
// @param _float The floating-point number that you want to display on the label.
// @param _keepLast If true (the default), keeps only the most recent label. If false, prints labels up to the TradingView limit.
// @param _condition The condition which must evaluate true for the label to be printed.
// @param _y The y location.
// @param _text The text to print on the label.
// @param _color The colour of the label.
// @param _textColor The colour of the text.
// @param _textAlign The alignment of the text.
// @param _style The style of the label.
// @param _yloc The y location type.
// @returns A named label object with the supplied characteristics.

import SimpleCryptoLife/SignificantFigures/1 as SCLSigFig
export labelTextAndFloatSigFig(int _offset=0, int _sigNumFig=5, float _float=123456.7891234, bool _keepLast=true, bool _condition=true, float _y=open, string _text="My lovely float:", color _color=color.white, color _textColor=color.black, string _textAlign=text.align_center, string _style=label.style_label_left, string _yloc=yloc.price) =>
    var string _floatText = na
    if not na(_float)
        _sigFloat = SCLSigFig.sigFig(_float, _sigNumFig)
        _floatText := str.tostring(_sigFloat)
    _timeblock1 = (time - time[1])
    _futureTime = time + (_timeblock1 * _offset)
    _x = _futureTime
    string _newline = not na(_text) ? '\n' : na
    var label SCL_myLabelTextAndFloatSigFig = na
    if _condition
        SCL_myLabelTextAndFloatSigFig := label.new(x = _futureTime, y = _y, text = _text+_newline+_floatText, color=_color, textcolor=_textColor, textalign=_textAlign, style=_style, yloc=_yloc, xloc=xloc.bar_time)
    else
        na
    if _keepLast
        label.delete(SCL_myLabelTextAndFloatSigFig[1])
    SCL_myLabelTextAndFloatSigFig

exampleFloat = 98765.4321987
labelTextAndFloatSigFig(_condition=inputShowLabel=="labelTextAndFloatSigFig", _offset=inputOffset, _textColor = color.white, _float=exampleFloat, _text="Float: " + str.tostring(exampleFloat) + "\n to " + str.tostring(inputSigNumFig) + "\nsignificant figures:", _sigNumFig = inputSigNumFig, _color=color.teal)



// ===========================================//
//         + FLOAT TO DECIMAL PLACES          //
// ===========================================//

// @function Creates a label each time a condition is true. All label parameters can be customised. Option to keep only the most recent label. Option to display the label a configurable number of bars ahead. Prints (optional) text and a floating-point number on the next line + to a given number of decimal places.
// @param _offset How many bars ahead to draw the label.
// @param _decimals The number of decimal places to display the floating-point number to.
// @param _float The floating-point number that you want to display on the label.
// @param _keepLast If true (the default), keeps only the most recent label. If false, prints labels up to the TradingView limit.
// @param _condition The condition which must evaluate true for the label to be printed.
// @param _y The y location.
// @param _text The text to print on the label.
// @param _color The colour of the label.
// @param _textColor The colour of the text.
// @param _textAlign The alignment of the text.
// @param _style The style of the label.
// @param _yloc The y location type.
// @returns A named label object with the supplied characteristics.

export labelTextAndFloatDecimals(int _offset=0, int _decimals=5, float _float=9876.5432198, bool _keepLast = true, bool _condition=true, float _y=open, string _text="My lovely float:", color _color=color.white, color _textColor=color.black, string _textAlign=text.align_center, string _style=label.style_label_left, string _yloc=yloc.price) =>
    var string _floatText = na
    if not na(_float)
        _floatDecimals = math.round(_float,_decimals)
        _floatText := str.tostring(_floatDecimals)
    _timeblock1 = (time - time[1])
    _futureTime = time + (_timeblock1 * _offset)
    _x = _futureTime
    string _newline = not na(_text) ? '\n' : na
    var label SCL_myLabelTextAndFloatDecimals = na
    if _condition
        SCL_myLabelTextAndFloatDecimals := label.new(x = _futureTime, y = _y, text = _text+_newline+_floatText, color=_color, textcolor=_textColor, textalign=_textAlign, style=_style, yloc=_yloc, xloc=xloc.bar_time)
    else
        na
    if _keepLast
        label.delete(SCL_myLabelTextAndFloatDecimals[1])
    SCL_myLabelTextAndFloatDecimals

exampleFloat2 = 98765.4321987
labelTextAndFloatDecimals(_condition=inputShowLabel=="labelTextAndFloatDecimals", _offset=inputOffset, _float=exampleFloat2, _text="Float: " + str.tostring(exampleFloat2) + "\n to " + str.tostring(inputDecimals) + "\ndecimal places:", _decimals = inputDecimals, _color=color.orange)
