HighLow Box Highlight between Earnings
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © processingclouds

//@version=5
indicator("Highlight Earning Span", "Earning Blocks", overlay = true)

//  ----- Variables {
var lowest = low
var highest = high
var flip = false
var count = 0
drawBox = box(na)
drawLabel = label(na)
showWhichBox = input.string(defval = "both", title="Choose Boxes To Display", options=["both","earnings only","custom only"])
//  ----- }

//  ----- Custom Date Boxes {
//  ----- Variables
var string separator = ','
var string currentInput = na
var string currentColor = na
var customLowest = 100000000.
var customHighest = 0.
var customArrayCount = 1
var extractedDates = array.new_int()
var extractedColor = array.new_color()
var errorCustomTable = table.new("top_center", 1, 1)
var hasErrorCustomInput = false
drawBoxCustom = box(na)


//  ----- Custom Box Inputs
customGroup = "Custom Box Dates"
customDateTip = "Please seperate the dates by commas. Input in form of DATE, DATE,.... DATE where DATE=yyyymmdd"
customColorTip = "Please seperate the colors by commas. Supported colors are blue, yellow, green, purple, orange, gray, red, olive, clear"
customDates = input.string(defval="",title="Custom Dates", tooltip=customDateTip, group=customGroup) // e.g. 20210901,20211101,20211205,20220201
customColors = input.string(defval="", title="Colors", tooltip = customColorTip, group=customGroup)  // e.g. orange,clear,purple

//  ----- Convert Inputs to Arrays
var dateArray = str.split(customDates, separator)
var colorArray = str.split(customColors, separator)

//  ----- Color Function - Returns Hex Code from String
hexColorCode(colorString) =>
    colorInput = str.replace(str.lower(colorString)," ", "")
    colorInput == "blue"   ?   #2196F340 :
     colorInput == "gray"   ?   #787B8640 :
     colorInput == "yellow" ?   #FFEB3B40 :
     colorInput == "green"  ?   #4CAF5040 :
     colorInput == "orange" ?   #FF980040 :
     colorInput == "red"    ?   #FF525240 :
     colorInput == "olive"  ?   #80800040 :
     colorInput == "purple" ?   #9C27B040 :
     #FFFFFF40

if (not(customDates == "" or customColors == "") and (showWhichBox == "both" or showWhichBox == "custom only"))
    if (array.size(dateArray)-1 == array.size(colorArray))
        if barstate.isfirst
            for i = 0 to array.size(dateArray) - 1
                currentInput := str.replace(array.get(dateArray, i)," ","")
                if (not na(str.tonumber(currentInput)) and str.length(currentInput)==8)
                    tempDate = timestamp(syminfo.timezone, 
                         int(str.tonumber(str.substring(currentInput,0,4))),
                         int(str.tonumber(str.substring(currentInput,4,6))),
                         int(str.tonumber(str.substring(currentInput,6))),
                         0,0)
                    array.push(extractedDates, tempDate)
            for i = 0 to array.size(colorArray) - 1 
                array.push(extractedColor, color(hexColorCode(array.get(colorArray, i))))
                
        if (array.size(extractedDates)-1 == array.size(extractedColor) and array.size(extractedDates) > 1)
            if (customArrayCount - 1 < array.size(dateArray)-1)
                if (time >= array.get(extractedDates, customArrayCount-1))
                    customLowest := math.min(customLowest, low)
                    customHighest := math.max(customHighest, high)
                else
                    customLowest := low
                    customHighest := high
            if (customArrayCount < array.size(dateArray))
                if (time > array.get(extractedDates, customArrayCount))
                    if (array.get(extractedColor, customArrayCount - 1) != color(#FFFFFF40))
                        drawBoxCustom := box.new(array.get(extractedDates, customArrayCount-1), customHighest, array.get(extractedDates, customArrayCount), customLowest,
                             border_color = color.green, border_width=1, border_style=line.style_dotted, xloc=xloc.bar_time,
                             bgcolor = array.get(extractedColor, customArrayCount - 1))
                    customArrayCount += 1
                    customLowest := low
                    customHighest := high
        else
            hasErrorCustomInput := true
    else
        hasErrorCustomInput := true

// Show messages on error from input
if (barstate.isfirst and hasErrorCustomInput)
    table.cell_set_text (errorCustomTable, 0, 0, text = "ERROR in Custom Inputs\n 1.Make sure dates are formatted as yyyymmdd.\n2.Number of colors is one less than number of dates.\n3.Dates are in ascending order.\n4. There must be atleast 2 custom dates.")
    table.cell_set_text_color(errorCustomTable, 0, 0, text_color =  color.red)
    table.cell_set_text_size (errorCustomTable, 0, 0, text_size  = size.normal)
    table.cell_set_bgcolor (errorCustomTable, 0, 0, bgcolor = color.gray)
//  ----- }


//  ----- Get earnings and high and low points {
e = request.earnings(syminfo.tickerid)
lowest := math.min(lowest, low)
highest := math.max(highest, high)
//  ----- }
//  ----- Check if new period has started to draw box on previous period
if (showWhichBox == "both" or showWhichBox == "earnings only")
    if (e != e[1] or barstate.islast)
        if(count <= 1000) // Max Supported Value is 5279 but 1000 is good enough here
            flip := not flip
            drawBox := box.new(bar_index[count], highest, bar_index, lowest, 
                 border_color = color.green,border_width=1, border_style=line.style_dotted, 
                 bgcolor=(flip ? color.new(color.blue, 70) : color.new(color.yellow,70)))
        count := 0
        lowest := low
        highest := high
    
    count += 1


// Updates - Version Histroy since v6:
// 02162022 - Fixed Bug where lowest and highest points were not correctly being fetched
// 02172022 - Cleaned up color input part of the code
//          - Added error check, so it removes blanks from color string input
//          - Added option to choose which boxes to display
//          