/*****************************************************************
Provided By : neoTOOLBOX (Daniel Christal)
Study:        Pivot Trend Lines

Notes:
	* USES neoLib
    * Based on the last two pivots, draw a top and bottom trend line
    * Optionally draw lines from the top/bottom primary or major pivot
    * Note: If AGET changes the labeling of a pivot, it may change/remove these lines.  Also, study only goes back 200 bars looking for pivots.  If pivot further away, then lines not drawn.
    * Must be set to "Scale Right/Left"

1.0
	* Initial Creation
1.1
	* FIXED Display of labels for instruments with an apostrophe (ex: Bonds, 119'05)
1.2
	* FIXED Tick charts not handled properly
1.3
	* ADDED Version check
1.4
	* ADDED Ability to turn off Trendlines and only have horizontal pivot lines
1.5
	* ADDED neoLib support
1.6
	* ADDED Ability to turn off labels


*****************************************************************/


var version = 1.6;
var neoLib = addLibrary( "neoLibrary.efsLib" );

var studyPivots = null;
var fpArray = new Array();
var x = 0;

function preMain()
{
    checkVersion(version, "http://neoTOOLBOX.com/studies/neoPivotTrendLines.efs");

    //debugClear();

    setStudyTitle("(neo)Pivot Trend Lines " + version);
	setPriceStudy(true);
    setShowCursorLabel( false );
    setShowTitleParameters(false);

	// Set to only execute when each bar closes
    setComputeOnClose();

	// Line Thickness
    fpArray[x] = new FunctionParameter( "LineThickness", FunctionParameter.NUMBER);
	with( fpArray[x++] ) {
		setName( "Line Thickness" );
		setLowerLimit(1);
		setDefault(2);
	}

	// Top Line Color
    fpArray[x] = new FunctionParameter( "TopColor", FunctionParameter.COLOR);
	with( fpArray[x++] ) {
		setName( "Top Line Color" );
		setDefault(Color.RGB(160,160,255));
	}

	// Bottom Line Color
    fpArray[x] = new FunctionParameter( "BottomColor", FunctionParameter.COLOR);
	with( fpArray[x++] ) {
		setName( "Bottom Line Color" );
		setDefault(Color.RGB(255,192,87));
	}


	// Draw Primary Extensions?
    fpArray[x] = new FunctionParameter( "DrawPriExtensions", FunctionParameter.BOOLEAN);
	with( fpArray[x++] ) {
		setName( "Draw Primary Pivot Extensions?" );
		setDefault(true);
	}

	// Draw Major Extensions?
    fpArray[x] = new FunctionParameter( "DrawMajExtensions", FunctionParameter.BOOLEAN);
	with( fpArray[x++] ) {
		setName( "Draw Major Pivot Extensions?" );
		setDefault(true);
	}

	// Draw Trend Lines?
    fpArray[x] = new FunctionParameter( "DrawTrendLines", FunctionParameter.BOOLEAN);
	with( fpArray[x++] ) {
		setName( "Draw Trend Lines?" );
		setDefault(true);
	}

	// Draw Labels?
    fpArray[x] = new FunctionParameter( "DrawLabels", FunctionParameter.BOOLEAN);
	with( fpArray[x++] ) {
		setName( "Draw Labels?" );
		setDefault(true);
	}
}

var bInit = false;

// For the Pivot Rays
var TopPivot1Index = null;
var TopPivot1Value = null;
var TopPivot2Index = null;
var TopPivot2Value = null;
var BottomPivot1Index = null;
var BottomPivot1Value = null;
var BottomPivot2Index = null;
var BottomPivot2Value = null;

var TopPriIndex = null;
var TopPriValue = null;
var TopMajIndex = null;
var TopMajValue = null;
var BottomPriIndex = null;
var BottomPriValue = null;
var BottomMajIndex = null;
var BottomMajValue = null;

var BarLimitForPivotSearch = 200;

var IndexOffset = -1;	// Due to using "setComputeOnClose()" the index seems to be off when drawing, have to introduce an offset

function main(LineThickness, TopColor, BottomColor, DrawPriExtensions, DrawMajExtensions, DrawTrendLines, DrawLabels)
{
	// Wait until last bar drawn before we do our stuff
	// NOTE: Breaks the line drawing for some reason!  Lines don't shift with new bars
    if (getCurrentBarIndex() != -1 && !isReplayMode() && !bInit)  {return;}

    if (!bInit)
    {
    	studyPivots = new GetPivotsStudy();

    	// Non-intraday charts don't need an altered index, so set back to zero (and NOT a TICK chart)
    	if (!isIntraday() && getInterval().indexOf("T") == -1)
    		IndexOffset = 0;

    	bInit = true;
    }

	//if (getBarState() == BARSTATE_NEWBAR)
	{
		// Reset our vars
		TopPriIndex = null;
		TopPriValue = null;
		TopMajIndex = null;
		TopMajValue = null;
		BottomPriIndex = null;
		BottomPriValue = null;
		BottomMajIndex = null;
		BottomMajValue = null;

		if (DrawTrendLines) drawPivotRays(LineThickness, TopColor, BottomColor, DrawPriExtensions, DrawMajExtensions);

		if (DrawPriExtensions || DrawMajExtensions)
		{
			findAndDrawPriMajPivotExtensions(LineThickness, TopColor, BottomColor, DrawPriExtensions, DrawMajExtensions, DrawLabels);
		}
	}
}


// Find the last two top and bottom pivots and draw trend lines from them
//
function drawPivotRays(LineThickness, TopColor, BottomColor, DrawPriExtensions, DrawMajExtensions)
{
	var bFoundT1 = false;
	var bFoundT2 = false;
	var bFoundB1 = false;
	var bFoundB2 = false;

	// Search for the pivots
	for (var i=0;i >= (0-BarLimitForPivotSearch); i--)
	{
		var Pivot = studyPivots.getValue(GetPivotsStudy.PIVOTS, i);

		// If it's not a pivot, just loop
		if (Pivot == null)
			continue;

		// Top pivot
		if (Pivot > 0 && (!bFoundT1 || !bFoundT2))
		{
			if (!bFoundT1)
			{
				TopPivot1Index = i + IndexOffset;
				TopPivot1Value = high(i);
				bFoundT1 = true;
			}
			else
			{
				TopPivot2Index = i + IndexOffset;
				TopPivot2Value = high(i);
				bFoundT2 = true;
			}

			// To help us later, if we have a Primary or Major Pivot, save the info
			// NOTE: INDEX IS NOT UPDATED WITH NEW BAR, THUS IDEA DOESN'T WORK
//			if (DrawPriExtensions && Pivot == neoLib.PIVOT_PRIMARY)
//			{
//				TopPriIndex = i;
//				TopPriValue = high(i);
//			}
//			else if (DrawMajExtensions && Pivot == neoLib.PIVOT_MAJOR)
//			{
//				TopMajIndex = i;
//				TopMajValue = high(i);
//			}
		}
		// Bottom Pivot
		if (Pivot < 0 && (!bFoundB1 || !bFoundB2))
		{
			if (!bFoundB1)
			{
				BottomPivot1Index = i + IndexOffset;
				BottomPivot1Value = low(i);
				bFoundB1 = true;
			}
			else
			{
				BottomPivot2Index = i + IndexOffset;
				BottomPivot2Value = low(i);
				bFoundB2 = true;
			}

			// To help us later, if we have a Primary or Major Pivot, save the info
			// NOTE: INDEX IS NOT UPDATED WITH NEW BAR, THUS IDEA DOESN'T WORK
//			if (DrawPriExtensions && Pivot == (0-neoLib.PIVOT_PRIMARY) )
//			{
//				BottomPriIndex = i;
//				BottomPriValue = low(i);
//			}
//			else if (DrawMajExtensions && Pivot == (0-neoLib.PIVOT_MAJOR) )
//			{
//				BottomMajIndex = i;
//				BottomMajValue = low(i);
//			}
		}

		if (bFoundT1 && bFoundT2 && bFoundB1 && bFoundB2)
		{
			break;
		}
	}

	// Draw the lines
	if (bFoundT1 && bFoundT2)
	{
		addLineTool(LineTool.RAY, TopPivot2Index, TopPivot2Value, TopPivot1Index, TopPivot1Value, LineThickness, TopColor, "topPivotRay");
	}
	if (bFoundB1 && bFoundB2)
	{
		addLineTool(LineTool.RAY, BottomPivot2Index, BottomPivot2Value, BottomPivot1Index, BottomPivot1Value, LineThickness, BottomColor, "bottomPivotRay");
	}
}



// Draw lines extending from the last Primary/Major pivot
//
function findAndDrawPriMajPivotExtensions(LineThickness, TopColor, BottomColor, DrawPriExtensions, DrawMajExtensions, DrawLabels)
{
	var bFoundTopPriPivot = (TopPriIndex != null && TopPriValue != null);
	var bFoundTopMajPivot = (TopMajIndex != null && TopMajValue != null);
	var bFoundBottomPriPivot = (BottomPriIndex != null && BottomPriValue != null);
	var bFoundBottomMajPivot = (BottomMajIndex != null && BottomMajValue != null);

	if (!bFoundTopPriPivot || !bFoundTopMajPivot || !bFoundBottomPriPivot || !bFoundBottomMajPivot)
	{
		// Find primary/major pivots
		for (var i=0;i >= (0-BarLimitForPivotSearch); i--)
		{
			var Pivot = studyPivots.getValue(GetPivotsStudy.PIVOTS, i);

			// If no pivot, just loop
			if (Pivot == null)
				continue;

			// We found a TOP Pivot?
			if (bFoundTopPriPivot && Pivot > 0)
			{
				continue;
			}
			else if (Pivot == neoLib.PIVOT_PRIMARY)
			{
				TopPriIndex = i + IndexOffset;
				TopPriValue = high(i);
				bFoundTopPriPivot = true;
			}
			else if (Pivot == neoLib.PIVOT_MAJOR)
			{
				TopMajIndex = i + IndexOffset;
				TopMajValue = high(i);
				bFoundTopMajPivot = true;
			}


			// We found a BOTTOM Pivot
			if (bFoundBottomPriPivot && Pivot < 0)
			{
				continue;
			}
			else if (Pivot == (0-neoLib.PIVOT_PRIMARY))
			{
				BottomPriIndex = i + IndexOffset;
				BottomPriValue = low(i);
				bFoundBottomPriPivot = true;
			}
			else if (Pivot == (0-neoLib.PIVOT_MAJOR))
			{
				BottomMajIndex = i + IndexOffset;
				BottomMajValue = low(i);
				bFoundBottomMajPivot = true;
			}


			if (bFoundTopPriPivot && bFoundTopMajPivot && bFoundBottomPriPivot && bFoundBottomMajPivot)
			{
				break;
			}
		}
	}


	//----------------------------------------------------------
	// Draw the Primary/Majorlevels

	var PaddingRight = 1;
	var CurrentIndex = -1;

	// Is the trendline horizontal?
	var bTopTrendLineFlat = TopPivot1Value == TopPivot2Value;
	var bBottomTrendLineFlat = BottomPivot1Value == BottomPivot2Value;

	// Are our Pri/Maj pivot levels on top of the trendline?  If so, we don't want to draw it due to overlapping lines (of the same color) disappear in eSignal
	var bTopPriOnTrendLine = bTopTrendLineFlat && TopPivot1Value == TopPriValue;
	var bTopMajOnTrendLine = bTopTrendLineFlat && TopPivot1Value == TopMajValue;
	var bBottomPriOnTrendLine = bBottomTrendLineFlat && BottomPivot1Value == BottomPriValue;
	var bBottomMajOnTrendLine = bBottomTrendLineFlat && BottomPivot1Value == BottomMajValue;

	// Draw the lines
	// If it is an old line (without a replacement), make sure we delete it

	// Top PRIMARY
	if (TopPriIndex != null && TopPriValue != null && !bTopPriOnTrendLine)
	{
		addLineTool(LineTool.SEGMENT, TopPriIndex, TopPriValue, CurrentIndex, TopPriValue, LineThickness, TopColor, "topPriRay");
		if (DrawLabels) drawTextAbsolute(PaddingRight, TopPriValue, "Pri " + formatPriceNumber(neoLib.Round(TopPriValue,4)), TopColor, null, Text.VCENTER | Text.LEFT | Text.bold, null, 8, "topPriRayLabel");
	}
	else
	{
		removeLineTool(LineTool.SEGMENT, "topPriRay");
		removeText("topPriRayLabel");
	}

	// Top MAJOR
	if (TopMajIndex != null && TopMajValue != null && !bTopMajOnTrendLine)
	{
		addLineTool(LineTool.SEGMENT, TopMajIndex, TopMajValue, CurrentIndex, TopMajValue, LineThickness, TopColor, "topMajRay");
		if (DrawLabels) drawTextAbsolute(PaddingRight, TopMajValue, "Maj " + formatPriceNumber(neoLib.Round(TopMajValue,4)), TopColor, null, Text.VCENTER | Text.LEFT | Text.bold, null, 8, "topMajRayLabel");
	}
	else
	{
		removeLineTool(LineTool.SEGMENT, "topMajRay");
		removeText("topMajRayLabel");
	}

	// Bottom PRIMARY
	if (BottomPriIndex != null && BottomPriValue != null && !bBottomPriOnTrendLine)
	{
		addLineTool(LineTool.SEGMENT, BottomPriIndex, BottomPriValue, CurrentIndex, BottomPriValue, LineThickness, BottomColor, "bottomPriRay");
		if (DrawLabels) drawTextAbsolute(PaddingRight, BottomPriValue, "Pri " + formatPriceNumber(neoLib.Round(BottomPriValue,4)), BottomColor, null, Text.VCENTER | Text.LEFT | Text.bold, null, 8, "bottomPriRayLabel");
	}
	else
	{
		removeLineTool(LineTool.SEGMENT, "bottomPriRay");
		removeText("bottomPriRayLabel");
	}

	// Bottom MAJOR
	if (BottomMajIndex != null && BottomMajValue != null && !bBottomMajOnTrendLine)
	{
		addLineTool(LineTool.SEGMENT, BottomMajIndex, BottomMajValue, CurrentIndex, BottomMajValue, LineThickness, BottomColor, "bottomMajRay");
		if (DrawLabels) drawTextAbsolute(PaddingRight, BottomMajValue, "Maj " + formatPriceNumber(neoLib.Round(BottomMajValue,4)), BottomColor, null, Text.VCENTER | Text.LEFT | Text.BOLD , null, 8, "bottomMajRayLabel");
	}
	else
	{
		removeLineTool(LineTool.SEGMENT, "bottomMajRay");
		removeText("bottomMajRayLabel");
	}
}
