#include  <iterator>

#include "sierrachart.h"
//#include "scstudyfunctions.h"

SCDLLName("ZigZag2")
/*==========================================================================*/
void AccumulateZigZagVolume(SCStudyInterfaceRef sc, SCSubgraphRef AccumulatedVolume, SCFloatArrayRef ZigZagPeakType, int VolumeTypeToAccumulate, SCFloatArrayRef ZigZagReset)
{
	if (VolumeTypeToAccumulate == 0)
		return;

	//Accumulate the volume across the last two zigzags

	//Determine starting point
	int Count = 0;//To count the number of zigzag lines
	int StartingIndex = sc.UpdateStartIndex+1;
	while (StartingIndex > 0 && Count < 2)
	{
		StartingIndex--;
		if (ZigZagPeakType[StartingIndex] != 0.0f)
			Count ++;
	}

	double Volume = 0;
	int Direction = 0;

	for (int Index = StartingIndex+1; Index < sc.ArraySize; ++Index)
	{
		if(ZigZagPeakType[Index-1] != 0)
		{
			Volume = 0;
			Direction = (int)ZigZagPeakType[Index-1];
		}

		if (ZigZagReset[Index-1] != 0) // First index, pick up initial volume
		{
			if (VolumeTypeToAccumulate == 1)
				Volume = sc.Volume[Index-1];
			else if (VolumeTypeToAccumulate == 2)
				Volume = sc.BidVolume[Index-1];
			else if (VolumeTypeToAccumulate == 3)
				Volume = sc.AskVolume[Index-1];
			else if (VolumeTypeToAccumulate == 4)
				Volume = sc.AskVolume[Index-1] - sc.BidVolume[Index-1];

			AccumulatedVolume[Index-1] = (float)Volume;
			Direction = (int)ZigZagPeakType[Index-1];
		}

		if (Direction == 1)
			AccumulatedVolume.DataColor[Index]= AccumulatedVolume.PrimaryColor;
		else if (Direction == -1)
			AccumulatedVolume.DataColor[Index]= AccumulatedVolume.SecondaryColor;

		if (VolumeTypeToAccumulate == 1)
			Volume += sc.Volume[Index];
		else if (VolumeTypeToAccumulate == 2)
			Volume += sc.BidVolume[Index];
		else if (VolumeTypeToAccumulate == 3)
			Volume += sc.AskVolume[Index];
		else if (VolumeTypeToAccumulate == 4)
			Volume += sc.AskVolume[Index] - sc.BidVolume[Index];

		AccumulatedVolume[Index] = (float)Volume;
	}
}
/*==========================================================================*/
void CreateZigZagLineLabel(SCString &BarLabelText, SCFloatArrayRef ZigZagPeakType, const int ZigZagIndex, SCFloatArrayRef ZigZagPeakIndex, SCInputRef ShowRevPrice, SCInputRef UseMultiLineLabels, SCStudyInterfaceRef sc, SCSubgraphRef ZigZagLine, SCInputRef ShowLength, bool ShowLabelPrefixes, SCInputRef ShowTime, SCInputRef IncludeSecondsInTimeDisplay, SCInputRef ShowZigZagVolume, SCSubgraphRef AccumulatedVolume, SCInputRef FormatVolumeWithLargeNumberSuffix, SCInputRef ShowZigZagDuration, SCInputRef ShowZigZagNumBars, SCInputRef DisplayZigZagVolumeDividedByLengthInTicks, SCFloatArrayRef ZigZagReset, SCInputRef DisplayHHHLLLLHLabels, SCSubgraphRef TextLabels, double& ZigzagLineLength, int& CurrentZigZagNumBars, SCInputRef Input_Divisor)
{


	int BackRefIndex = (int)ZigZagPeakIndex[ZigZagIndex - 1];

	if (ZigZagPeakType[BackRefIndex] == -1 * ZigZagPeakType[ZigZagIndex])
	{
		if (ShowRevPrice.GetYesNo())
		{
			if (BarLabelText.GetLength() != 0)
			{
				if (UseMultiLineLabels.GetYesNo())
					BarLabelText += "\n";
				else
					BarLabelText += " ";
			}

			SCString ReversalPrice;
			ReversalPrice = sc.FormatGraphValue(ZigZagLine[ZigZagIndex], sc.GetValueFormat());
			BarLabelText += ReversalPrice;
		}

		ZigzagLineLength = ZigZagLine[ZigZagIndex] - ZigZagLine[BackRefIndex];
		if (ShowLength.GetIndex() != 0)
		{
			if (BarLabelText.GetLength() != 0)
			{
				if (UseMultiLineLabels.GetYesNo())
					BarLabelText += "\n";
				else
					BarLabelText += " ";
			}

			SCString LengthStr;
			if (ShowLabelPrefixes)
				LengthStr = "L:";

			if (ShowLength.GetIndex() == 1)//Points
				LengthStr += sc.FormatGraphValue(ZigzagLineLength, sc.GetValueFormat());
			else if (ShowLength.GetIndex() == 2)// Ticks
			{
				double Ticks = sc.TickSize == 0 ? 0 : ZigzagLineLength / sc.TickSize;
				LengthStr += sc.FormatGraphValue(Ticks, 0);
				LengthStr += "T";
			}
			else if (ShowLength.GetIndex() == 3)//Percent
			{
				float CurrentBarValue = sc.Close[ZigZagIndex];
				float Percent = static_cast<float>((ZigzagLineLength / CurrentBarValue) * 100);
				LengthStr += sc.FormatGraphValue(Percent, 2);
			}

			BarLabelText += LengthStr;
		}

		if (ShowTime.GetYesNo())
		{
			if (BarLabelText.GetLength() != 0)
			{
				if (UseMultiLineLabels.GetYesNo())
					BarLabelText += "\n";
				else
					BarLabelText += " ";
			}

			SCDateTime DT = sc.BaseDateTimeIn[ZigZagIndex];
			SCString TimeStr;
			if (IncludeSecondsInTimeDisplay.GetYesNo())
				TimeStr.Format("%i:%02i:%02i", DT.GetHour(), DT.GetMinute(), DT.GetSecond());
			else
				TimeStr.Format("%i:%02i", DT.GetHour(), DT.GetMinute());

			BarLabelText += TimeStr;
		}

		if (ShowZigZagVolume.GetYesNo())
		{
			if (BarLabelText.GetLength() != 0)
			{
				if (UseMultiLineLabels.GetYesNo())
					BarLabelText += "\n";
				else
					BarLabelText += " ";
			}

			SCString LengthStr;
			if (ShowLabelPrefixes)
				LengthStr = "V:";

			LengthStr += sc.FormatVolumeValue((int64_t)(AccumulatedVolume[ZigZagIndex] / Input_Divisor.GetInt()), 0, FormatVolumeWithLargeNumberSuffix.GetYesNo());

			BarLabelText += LengthStr;
		}

		if (ShowZigZagDuration.GetYesNo())
		{
			if (BarLabelText.GetLength() != 0)
			{
				if (UseMultiLineLabels.GetYesNo())
					BarLabelText += "\n";
				else
					BarLabelText += " ";
			}

			double ZigZagTimeSpan = 0;
			if (sc.ChartDataType == INTRADAY_DATA)
			{
				if (ZigZagIndex < sc.ArraySize - 1)
					ZigZagTimeSpan = (sc.BaseDateTimeIn[ZigZagIndex + 1] - sc.BaseDateTimeIn[BackRefIndex + 1]).GetAsDouble();
				else
					ZigZagTimeSpan = (sc.LatestDateTimeForLastBar - sc.BaseDateTimeIn[BackRefIndex + 1]).GetAsDouble();
			}
			else
			{
				ZigZagTimeSpan = (sc.BaseDateTimeIn[ZigZagIndex] - sc.BaseDateTimeIn[BackRefIndex + 1]).GetAsDouble();
			}

			SCString TimeDurationStr;
			if (sc.ChartDataType == INTRADAY_DATA)
			{
				TimeDurationStr = sc.FormatGraphValue(ZigZagTimeSpan, 20);

				if (TimeDurationStr.GetLength() >= 3 && TimeDurationStr[0] == '0' && TimeDurationStr[1] == '0' && TimeDurationStr[2] == ':')
					TimeDurationStr = TimeDurationStr.GetSubString(TimeDurationStr.GetLength() - 3, 3);
			}

			SCString LengthStr;
			if (ShowLabelPrefixes)
				LengthStr = "D:";
			if (ZigZagTimeSpan >= 1.0)
			{
				SCString DaysStr;
				if (sc.ChartDataType == INTRADAY_DATA)
					DaysStr.Format("%iD ", (int)ZigZagTimeSpan);
				else
					DaysStr.Format("%i ", (int)ZigZagTimeSpan);

				LengthStr += DaysStr;
			}
			LengthStr += TimeDurationStr;

			BarLabelText += LengthStr;
		}

		CurrentZigZagNumBars = ZigZagIndex - BackRefIndex;

		if (ShowZigZagNumBars.GetYesNo())
		{
			if (BarLabelText.GetLength() != 0)
			{
				if (UseMultiLineLabels.GetYesNo())
					BarLabelText += "\n";
				else
					BarLabelText += " ";
			}

			SCString LengthStr;
			if (ShowLabelPrefixes)
				LengthStr = "B:";

			SCString NumStr;
			NumStr.Format("%i ", CurrentZigZagNumBars);
			LengthStr += NumStr;

			BarLabelText += LengthStr;
		}

		if (DisplayZigZagVolumeDividedByLengthInTicks.GetYesNo())
		{
			if (BarLabelText.GetLength() != 0)
			{
				if (UseMultiLineLabels.GetYesNo())
					BarLabelText += "\n";
				else
					BarLabelText += " ";
			}

			if (ShowLabelPrefixes)
				BarLabelText += "V/L:";

			int64_t VolumeDividedByLengthInTicks = static_cast <int64_t>(AccumulatedVolume[ZigZagIndex] / Input_Divisor.GetInt() / (ZigzagLineLength / sc.TickSize));

			BarLabelText += sc.FormatVolumeValue(VolumeDividedByLengthInTicks, 0, FormatVolumeWithLargeNumberSuffix.GetYesNo());

		}
	}

	// now go back one more swing
	if (ZigZagReset[BackRefIndex] == 0)
	{
		BackRefIndex = (int)ZigZagPeakIndex[BackRefIndex - 1];

		if (ZigZagPeakType[BackRefIndex] == ZigZagPeakType[ZigZagIndex])
		{
			if (DisplayHHHLLLLHLabels.GetYesNo())
			{
				if (BarLabelText.GetLength() != 0)
				{
					if (UseMultiLineLabels.GetYesNo())
						BarLabelText += "\n";
					else
						BarLabelText += " ";
				}

				if (ZigZagPeakType[BackRefIndex] == 1.0f)//High
				{
					if (ZigZagLine[BackRefIndex] > ZigZagLine[ZigZagIndex]) //LowerHigh
					{
						BarLabelText += "LH";
						TextLabels.Data[ZigZagIndex] = 1;
					}
					else //HigherHigh
					{
						BarLabelText += "HH";
						TextLabels.Data[ZigZagIndex] = 2;
					}
				}
				else //Low
				{
					if (ZigZagLine[BackRefIndex] < ZigZagLine[ZigZagIndex]) //HigherLow
					{
						BarLabelText += "HL";
						TextLabels.Data[ZigZagIndex] = 3;
					}
					else //LowerLow
					{
						BarLabelText += "LL";
						TextLabels.Data[ZigZagIndex] = 4;
					}
				}
			}
		}
	}
	else
	{
		if (ZigZagLine[BackRefIndex] > ZigZagLine[ZigZagIndex])
			TextLabels.Data[ZigZagIndex] = 11;  // first pivot low
		else
			TextLabels.Data[ZigZagIndex] = 12;  // first pivot high
	}
}

/*==========================================================================*/
SCSFExport scsf_ZigZagStudy2(SCStudyInterfaceRef sc)
{
	SCSubgraphRef Subgraph_ZigZagLine        = sc.Subgraph[0];
	SCSubgraphRef Subgraph_TextLabels        = sc.Subgraph[1];
	SCSubgraphRef Subgraph_ReversalPrice     = sc.Subgraph[2];
	SCSubgraphRef Subgraph_ZigzagLength      = sc.Subgraph[3];
	SCSubgraphRef Subgraph_AccumulatedVolume = sc.Subgraph[4];
	SCSubgraphRef Subgraph_ZigzagNumBars     = sc.Subgraph[5];
	SCSubgraphRef Subgraph_ZigzagMidPoint    = sc.Subgraph[6];
	SCSubgraphRef Subgraph_ExtensionLinesSubgraph = sc.Subgraph[7];
	SCSubgraphRef Subgraph_ZigZagOscillator = sc.Subgraph[8];
	SCSubgraphRef Subgraph_ZigZagLineDuration = sc.Subgraph[9];

	SCInputRef Input_VolumeToAccumulate = sc.Input[0];
	SCInputRef Input_LabelOffsetType = sc.Input[1];
	SCInputRef Input_FormatVolumeWithLargeNumberSuffix = sc.Input[2];
	SCInputRef Input_ColorZigZagLine = sc.Input[3];
	SCInputRef Input_VersionUpdate = sc.Input[14];
	SCInputRef Input_DataHigh = sc.Input[15];
	SCInputRef Input_DataLow = sc.Input[16];
	SCInputRef Input_CalculationMode = sc.Input[17];
	SCInputRef Input_ReversalPercent = sc.Input[18];
	SCInputRef Input_ReversalAmount = sc.Input[19];
	SCInputRef Input_NumberBarsForReversal = sc.Input[20];
	SCInputRef Input_ShowRevPrice = sc.Input[21];
	SCInputRef Input_DisplayHHHLLLLHLabels = sc.Input[22];
	SCInputRef Input_LabelsOffset = sc.Input[23];
	SCInputRef Input_AdditionalOutputForSpreadsheets = sc.Input[24];
	SCInputRef Input_ShowTime = sc.Input[25];
	SCInputRef Input_ShowLength = sc.Input[26];
	SCInputRef Input_CalcOnBarClose = sc.Input[27];
	SCInputRef Input_CalculateZigZagVolume_UpgradeOnly = sc.Input[28];
	SCInputRef Input_ShowZigZagVolume = sc.Input[29];
	SCInputRef Input_ShowZigZagDuration = sc.Input[30];
	SCInputRef Input_UseMultiLineLabels = sc.Input[31];
	SCInputRef Input_OmitLabelPrefixes = sc.Input[32];
	SCInputRef Input_ShowZigZagNumBars = sc.Input[33];
	SCInputRef Input_ResetAtStartOfSession = sc.Input[34];
	SCInputRef Input_DisplayZigZagVolumeDividedByLengthInTicks = sc.Input[35];
	SCInputRef Input_ExtendEndPointsUntilFutureIntersection = sc.Input[36];
	SCInputRef Input_IncludeSecondsInTimeDisplay = sc.Input[37];
	SCInputRef Input_DisplayValueLabel = sc.Input[38];
	SCInputRef Input_SingleLineTextHorizontalAlignment = sc.Input[39];
	SCInputRef Input_MultiLineTextHorizontalAlignment = sc.Input[40];
	SCInputRef Input_Divisor = sc.Input[41];


	if(sc.SetDefaults)
	{
		sc.GraphName="Zig Zag2";

		//Manual looping
		sc.AutoLoop = 0;

		sc.GraphRegion = 0;

		sc.ValueFormat = VALUEFORMAT_INHERITED;

		Subgraph_ZigZagLine.Name = "Zig Zag2";
		Subgraph_ZigZagLine.DrawStyle = DRAWSTYLE_LINE;
		Subgraph_ZigZagLine.LineStyle = LINESTYLE_DOT;
		Subgraph_ZigZagLine.PrimaryColor = RGB(255,0,255);
		Subgraph_ZigZagLine.SecondaryColorUsed = 1;
		Subgraph_ZigZagLine.SecondaryColor = RGB(255,0,0);
		Subgraph_ZigZagLine.LineWidth = 3;
		Subgraph_ZigZagLine.DrawZeros = false;

		Subgraph_TextLabels.Name = "Text Labels";
		Subgraph_TextLabels.SecondaryColorUsed = 1;
		Subgraph_TextLabels.PrimaryColor = RGB(0,255,0);
		Subgraph_TextLabels.SecondaryColor = RGB(255,0,0);
		Subgraph_TextLabels.LineWidth = 10;
		Subgraph_TextLabels.DrawStyle = DRAWSTYLE_CUSTOM_TEXT;
		
		Subgraph_ReversalPrice.DrawStyle = DRAWSTYLE_IGNORE;
		Subgraph_ZigzagLength.DrawStyle = DRAWSTYLE_IGNORE;
		Subgraph_ZigzagNumBars.DrawStyle = DRAWSTYLE_IGNORE;
		Subgraph_AccumulatedVolume.DrawStyle = DRAWSTYLE_IGNORE;
		Subgraph_AccumulatedVolume.SecondaryColorUsed = 1;

		Subgraph_ZigzagMidPoint.Name = "Zig Zag Mid-Point";
		Subgraph_ZigzagMidPoint.DrawStyle = DRAWSTYLE_IGNORE;
		Subgraph_ZigzagMidPoint.PrimaryColor = RGB(128,128,255);
		Subgraph_ZigzagMidPoint.LineWidth = 1;
		Subgraph_ZigzagMidPoint.DrawZeros = false;

		Subgraph_ExtensionLinesSubgraph.Name = "Extension Lines";
		Subgraph_ExtensionLinesSubgraph.DrawStyle = DRAWSTYLE_LINE;
		Subgraph_ExtensionLinesSubgraph.PrimaryColor = RGB(128, 128, 255);
		Subgraph_ExtensionLinesSubgraph.SecondaryColorUsed = true;
		Subgraph_ExtensionLinesSubgraph.SecondaryColor = RGB(128, 0, 255);
		Subgraph_ExtensionLinesSubgraph.LineWidth = 1;
		Subgraph_ExtensionLinesSubgraph.DrawZeros = false;

		Subgraph_ZigZagOscillator.Name = "Zig Zag Oscillator";
		Subgraph_ZigZagOscillator.DrawStyle = DRAWSTYLE_IGNORE;
		Subgraph_ZigZagOscillator.PrimaryColor = RGB(0, 200, 0);
		Subgraph_ZigZagOscillator.SecondaryColor = RGB(200, 0, 0);
		Subgraph_ZigZagOscillator.AutoColoring = AUTOCOLOR_POSNEG;
		Subgraph_ZigZagOscillator.LineWidth = 3;
		Subgraph_ZigZagOscillator.DrawZeros = false;

		Input_VersionUpdate.SetInt(4);

		unsigned short DisplayOrder = 1;

		Input_DataHigh.Name = "Input Data for High";
		Input_DataHigh.SetInputDataIndex(SC_HIGH);
		Input_DataHigh.DisplayOrder = DisplayOrder++;

		Input_DataLow.Name = "Input Data for Low";
		Input_DataLow.SetInputDataIndex(SC_LOW);
		Input_DataLow.DisplayOrder = DisplayOrder++;

		Input_CalculationMode.Name = "Calculation Mode (1,2,3)";
		Input_CalculationMode.SetInt(1);
		Input_CalculationMode.SetIntLimits(1, 3);
		Input_CalculationMode.DisplayOrder = DisplayOrder++;

		Input_ReversalPercent.Name = "Reversal % for Calculation Mode 1";
		Input_ReversalPercent.SetFloat(.5f);
		Input_ReversalPercent.DisplayOrder = DisplayOrder++;

		Input_ReversalAmount.Name = "Reversal Amount for Calculation Mode 2,3";
		Input_ReversalAmount.SetFloat(0.01f);
		Input_ReversalAmount.DisplayOrder = DisplayOrder++;

		Input_NumberBarsForReversal.Name = "Number of Bars Required for Reversal (Calculation Mode 2)";
		Input_NumberBarsForReversal.SetInt(5);
		Input_NumberBarsForReversal.DisplayOrder = DisplayOrder++;

		Input_VolumeToAccumulate.Name = "Volume To Accumulate";
		Input_VolumeToAccumulate.SetCustomInputStrings("None;Total Volume;Bid Volume;Ask Volume;Ask Bid Volume Difference");
		Input_VolumeToAccumulate.SetCustomInputIndex(0);
		Input_VolumeToAccumulate.DisplayOrder = DisplayOrder++;

		Input_ResetAtStartOfSession.Name = "Reset ZigZag At Start Of Trading Day";
		Input_ResetAtStartOfSession.SetYesNo(0);
		Input_ResetAtStartOfSession.DisplayOrder = DisplayOrder++;

		Input_CalcOnBarClose.Name = "Calculate New Values On Bar Close";
		Input_CalcOnBarClose.SetYesNo(0);
		Input_CalcOnBarClose.DisplayOrder = DisplayOrder++;

		Input_AdditionalOutputForSpreadsheets.Name = "Additional Output for Spreadsheets";
		Input_AdditionalOutputForSpreadsheets.SetYesNo(false);
		Input_AdditionalOutputForSpreadsheets.DisplayOrder = DisplayOrder++;

		Input_DisplayHHHLLLLHLabels.Name = "Display HH,HL,LL,LH Labels";
		Input_DisplayHHHLLLLHLabels.SetYesNo(0);
		Input_DisplayHHHLLLLHLabels.DisplayOrder = DisplayOrder++;

		Input_ShowRevPrice.Name = "Display Reversal Price";
		Input_ShowRevPrice.SetYesNo(0);
		Input_ShowRevPrice.DisplayOrder = DisplayOrder++;

		Input_ShowLength.Name = "Display Length of Zig Zag Line";
		Input_ShowLength.SetCustomInputStrings("None;Points;Ticks;Percent");
		Input_ShowLength.SetCustomInputIndex(0);
		Input_ShowLength.DisplayOrder = DisplayOrder++;
		
		Input_ShowZigZagVolume.Name = "Display ZigZag Volume";
		Input_ShowZigZagVolume.SetYesNo(0);
		Input_ShowZigZagVolume.DisplayOrder = DisplayOrder++;

		Input_FormatVolumeWithLargeNumberSuffix.Name = "Format Volume Using Large Number Suffix (K/M)";
		Input_FormatVolumeWithLargeNumberSuffix.SetYesNo(0);
		Input_FormatVolumeWithLargeNumberSuffix.DisplayOrder = DisplayOrder++;

		Input_ShowTime.Name = "Display Time Labels";
		Input_ShowTime.SetYesNo(0);
		Input_ShowTime.DisplayOrder = DisplayOrder++;

		Input_IncludeSecondsInTimeDisplay.Name = "Include Seconds in Time Display";
		Input_IncludeSecondsInTimeDisplay.SetYesNo(1);
		Input_IncludeSecondsInTimeDisplay.DisplayOrder = DisplayOrder++;

		Input_ShowZigZagDuration.Name = "Display ZigZag Time Duration";
		Input_ShowZigZagDuration.SetYesNo(0);
		Input_ShowZigZagDuration.DisplayOrder = DisplayOrder++;

		Input_ShowZigZagNumBars.Name = "Display ZigZag Number Of Bars";
		Input_ShowZigZagNumBars.SetYesNo(0);
		Input_ShowZigZagNumBars.DisplayOrder = DisplayOrder++;

		Input_DisplayZigZagVolumeDividedByLengthInTicks.Name = "Display ZigZag Volume / Length in Ticks";
		Input_DisplayZigZagVolumeDividedByLengthInTicks.SetYesNo(0);
		Input_DisplayZigZagVolumeDividedByLengthInTicks.DisplayOrder = DisplayOrder++;

		Input_UseMultiLineLabels.Name = "Use Multi-Line Labels";
		Input_UseMultiLineLabels.SetYesNo(0);
		Input_UseMultiLineLabels.DisplayOrder = DisplayOrder++;

		Input_OmitLabelPrefixes.Name = "Omit Label Prefixes";
		Input_OmitLabelPrefixes.SetYesNo(0);
		Input_OmitLabelPrefixes.DisplayOrder = DisplayOrder++;

		Input_LabelOffsetType.Name = "Text Label Offset Specified As";
		Input_LabelOffsetType.SetCustomInputStrings("Percentage Of Bar;Tick Offset");
		Input_LabelOffsetType.SetCustomInputIndex(1);
		Input_LabelOffsetType.DisplayOrder = DisplayOrder++;

		Input_LabelsOffset.Name = "Text Label Offset";
		Input_LabelsOffset.SetFloat(1.0f);
		Input_LabelsOffset.DisplayOrder = DisplayOrder++;

		Input_ColorZigZagLine.Name = "Color ZigZag Line Using";
		Input_ColorZigZagLine.SetCustomInputStrings("None;Slope;Trend Confirmed Volume;Confirmed Volume");
		Input_ColorZigZagLine.SetCustomInputIndex(0);
		Input_ColorZigZagLine.DisplayOrder = DisplayOrder++;

		Input_ExtendEndPointsUntilFutureIntersection.Name = "Extend End Points Until Future Intersection";
		Input_ExtendEndPointsUntilFutureIntersection.SetYesNo(false);
		Input_ExtendEndPointsUntilFutureIntersection.DisplayOrder = DisplayOrder++;

		Input_DisplayValueLabel.Name = "Display Value Label for Extension Lines";
		Input_DisplayValueLabel.SetYesNo(false);
		Input_DisplayValueLabel.DisplayOrder = DisplayOrder++;

		Input_SingleLineTextHorizontalAlignment.Name = "Single Line Text Horizontal Alignment";
		Input_SingleLineTextHorizontalAlignment.SetCustomInputStrings("Left;Center;Right");
		Input_SingleLineTextHorizontalAlignment.SetCustomInputIndex(1);
		Input_SingleLineTextHorizontalAlignment.DisplayOrder = DisplayOrder++;

		Input_MultiLineTextHorizontalAlignment.Name = "Multi-Line Text Horizontal Alignment";
		Input_MultiLineTextHorizontalAlignment.SetCustomInputStrings("Left;Center;Right");
		Input_MultiLineTextHorizontalAlignment.SetCustomInputIndex(0);
		Input_MultiLineTextHorizontalAlignment.DisplayOrder = DisplayOrder++;

		Input_Divisor.Name = "Divisor";
		Input_Divisor.SetInt(1000);
		Input_Divisor.SetIntLimits(1, 10000);
		Input_Divisor.DisplayOrder = DisplayOrder++;

		return;
	}

	SCFloatArrayRef ZigZagPeakType  = Subgraph_ZigZagLine.Arrays[0];  // ZigZagPeakType : +1=high peak, -1=low peak, 0=not peak
	SCFloatArrayRef ZigZagPeakIndex = Subgraph_ZigZagLine.Arrays[1];  // ZigZagPeakIndex: index of current peak, -1=no peak yet
	SCFloatArrayRef ZigZagReset     = Subgraph_ZigZagLine.Arrays[2];  // ZigZagReset: 0=no reset, 1=reset
	SCFloatArrayRef ZigZagTrend     = Subgraph_ZigZagLine.Arrays[3];  // ZigZagTrend: 0=none, 1=confirmed up, -1=confirmed down

	int& LastCalcIndex	          = sc.GetPersistentInt(1);
	int& PriorLastZZEndpointIndex = sc.GetPersistentInt(2);
	int& ZigZagStartIndex         = sc.GetPersistentInt(3);
	int& LastUsedLabelDrawingNumber		  = sc.GetPersistentInt(4);
	int& LastUsedBarIndexForExtensionLine = sc.GetPersistentInt(5);

	if(sc.UpdateStartIndex == 0)
	{
		LastCalcIndex = -1;
		LastUsedLabelDrawingNumber = -1;
		LastUsedBarIndexForExtensionLine = -1;
		PriorLastZZEndpointIndex = -1;
		ZigZagStartIndex = 0;
		ZigZagReset[0] = 1.0f;
		Subgraph_TextLabels[0] = 10;  // first point

		if (Input_VersionUpdate.GetInt() < 2)
		{
			Input_ResetAtStartOfSession.SetYesNo(0);
			Input_VersionUpdate.SetInt(2);
		}
		
		if (Input_VersionUpdate.GetInt() < 3)
		{
			Input_LabelOffsetType.SetCustomInputIndex(0);
			Input_FormatVolumeWithLargeNumberSuffix.SetYesNo(0);
			Subgraph_ZigZagLine.SecondaryColorUsed = 1;
			Subgraph_ZigZagLine.SecondaryColor = RGB(255,0,0);
			Input_ColorZigZagLine.SetCustomInputIndex(0);
			Input_VolumeToAccumulate.SetCustomInputIndex(Input_VolumeToAccumulate.GetIndex()+1);
			if (Input_CalculateZigZagVolume_UpgradeOnly.GetYesNo() == 0)
				Input_VolumeToAccumulate.SetCustomInputIndex(0);

			Input_VersionUpdate.SetInt(3);
			Input_Divisor.SetInt(1000);
		}

		if (Input_VersionUpdate.GetInt() < 4)
		{
			Input_SingleLineTextHorizontalAlignment.SetCustomInputIndex(1);
			Input_MultiLineTextHorizontalAlignment.SetCustomInputIndex(0);
			Input_VersionUpdate.SetInt(4);
		}

		if (Input_AdditionalOutputForSpreadsheets.GetYesNo())
		{
			Subgraph_ReversalPrice.Name = "Reversal Price";
			Subgraph_ZigzagLength.Name = "Zig Zag Line Length";
			Subgraph_ZigzagNumBars.Name = "Zig Zag Num Bars";
		}
		else
		{
			Subgraph_ReversalPrice.Name = "";
			Subgraph_ZigzagLength.Name = "";
			Subgraph_ZigzagNumBars.Name = "";
		}

		if (Input_ShowZigZagVolume.GetYesNo() && Input_VolumeToAccumulate.GetIndex() == 0)
			Input_VolumeToAccumulate.SetCustomInputIndex(1);

		if(Input_VolumeToAccumulate.GetIndex() != 0)
			Subgraph_AccumulatedVolume.Name= "AccumulatedVolume";
		else
			Subgraph_AccumulatedVolume.Name= "";
	}
	else
	{
		if (LastUsedLabelDrawingNumber != -1)
		{
			sc.DeleteACSChartDrawing(sc.ChartNumber, TOOL_DELETE_CHARTDRAWING, LastUsedLabelDrawingNumber);

			LastUsedLabelDrawingNumber = -1;
		}

		if (LastUsedBarIndexForExtensionLine != -1)
		{
			sc.DeleteLineUntilFutureIntersection(LastUsedBarIndexForExtensionLine, 0);

			LastUsedBarIndexForExtensionLine = -1;
		}

	}
	

	bool ShowLabelPrefixes = Input_OmitLabelPrefixes.GetYesNo() == 0;

	SCDateTime NextSessionStart = 0;
	if (sc.UpdateStartIndex > 0)
		NextSessionStart = SCDateTime(sc.GetTradingDayStartDateTimeOfBar(sc.BaseDateTimeIn[sc.UpdateStartIndex - 1])) + SCDateTime::DAYS(1);

	sc.EarliestUpdateSubgraphDataArrayIndex = sc.UpdateStartIndex;

	// Standard Manual Looping loop
	for (int Index = sc.UpdateStartIndex; Index < sc.ArraySize; ++Index)
	{
		if (Input_ResetAtStartOfSession.GetYesNo() != 0)
		{
			SCDateTime IndexDateTime = sc.BaseDateTimeIn[Index];
		
			if (IndexDateTime >= NextSessionStart)
			{
				ZigZagStartIndex = Index;
				ZigZagReset[Index] = 1.0f;
				Subgraph_TextLabels[Index] = 10;  // first point

				NextSessionStart = SCDateTime(sc.GetTradingDayStartDateTimeOfBar(IndexDateTime)) + SCDateTime::DAYS(1);
			}
		}

		int CalcIndex = Index;

		if (Input_CalcOnBarClose.GetYesNo())
		{
			CalcIndex--;
			if (CalcIndex <= LastCalcIndex)
				continue;
			LastCalcIndex = CalcIndex;
		}

		//Calculate and set the zigzag lines
		switch (Input_CalculationMode.GetInt())
		{
		case 1:
			sc.ZigZag(
				sc.BaseData[Input_DataHigh.GetInputDataIndex()],
				sc.BaseData[Input_DataLow.GetInputDataIndex()],
				Subgraph_ZigZagLine,
				CalcIndex,
				Input_ReversalPercent.GetFloat() * 0.01f,
				ZigZagStartIndex);
			break;
		case 2:
			sc.ZigZag2(
				sc.BaseData[Input_DataHigh.GetInputDataIndex()],
				sc.BaseData[Input_DataLow.GetInputDataIndex()],
				Subgraph_ZigZagLine,
				CalcIndex,
				Input_NumberBarsForReversal.GetInt(),
				Input_ReversalAmount.GetFloat(),
				ZigZagStartIndex);
			break;
		case 3:
			sc.ZigZag(
				sc.BaseData[Input_DataHigh.GetInputDataIndex()],
				sc.BaseData[Input_DataLow.GetInputDataIndex()],
				Subgraph_ZigZagLine,
				CalcIndex,
				0.0f,
				Input_ReversalAmount.GetFloat(),
				ZigZagStartIndex);
			break;
		}
	}
	
	AccumulateZigZagVolume(sc, Subgraph_AccumulatedVolume, ZigZagPeakType, Input_VolumeToAccumulate.GetIndex(), ZigZagReset);

	if (PriorLastZZEndpointIndex != -1)
	{
		for (int ZeroIndex = PriorLastZZEndpointIndex; ZeroIndex < sc.ArraySize; ZeroIndex++)
		{
			Subgraph_TextLabels[ZeroIndex] = 0;
			Subgraph_ReversalPrice[ZeroIndex] = 0;
			Subgraph_ZigzagLength[ZeroIndex] = 0;
			Subgraph_ZigzagNumBars[ZeroIndex] = 0;
		}
	}

	if (PriorLastZZEndpointIndex == -1)
		PriorLastZZEndpointIndex = 0;

	// Get the index of the last endpoint
	int IndexOfLastEndPoint = 0;
	if (Input_CalcOnBarClose.GetYesNo() && sc.ArraySize > 1)
		IndexOfLastEndPoint = (int)ZigZagPeakIndex[sc.ArraySize-2];
	else
		IndexOfLastEndPoint = (int)ZigZagPeakIndex[sc.ArraySize-1];


	for (int ZigZagIndex = PriorLastZZEndpointIndex; ZigZagIndex < sc.ArraySize; ZigZagIndex++)
	{
		if (Subgraph_ZigZagLine[ZigZagIndex] != 0 && Input_ColorZigZagLine.GetIndex() != 0)
		{
			if (Input_ColorZigZagLine.GetIndex() == 1 && ZigZagIndex > 0)
			{
				if (Subgraph_ZigZagLine[ZigZagIndex] > Subgraph_ZigZagLine[ZigZagIndex-1])
					Subgraph_ZigZagLine.DataColor[ZigZagIndex] = Subgraph_ZigZagLine.PrimaryColor;
				else
					Subgraph_ZigZagLine.DataColor[ZigZagIndex] = Subgraph_ZigZagLine.SecondaryColor;
			}
			else if (Input_ColorZigZagLine.GetIndex() == 2 || Input_ColorZigZagLine.GetIndex() == 3)
			{
				if (ZigZagTrend[ZigZagIndex] > 0)
					Subgraph_ZigZagLine.DataColor[ZigZagIndex] = Subgraph_ZigZagLine.PrimaryColor;
				else if (ZigZagTrend[ZigZagIndex] < 0)
					Subgraph_ZigZagLine.DataColor[ZigZagIndex] = Subgraph_ZigZagLine.SecondaryColor;
			}
		}

		int CurrentPeakIndex = (int)ZigZagPeakIndex[ZigZagIndex];

		Subgraph_ZigZagOscillator[ZigZagIndex] = sc.Close[ZigZagIndex] - Subgraph_ZigZagLine[CurrentPeakIndex];

		if (ZigZagPeakType[ZigZagIndex] == 0.0f) //not a peak, nothing to be drawn
			continue;

		if (ZigZagReset[ZigZagIndex] != 0)//Continue processing if this is a reset index
		{			
			continue;
		}

		int PrevEndPointIndex = -1;
		if (ZigZagIndex > 0)
			PrevEndPointIndex = (int)ZigZagPeakIndex[ZigZagIndex-1];

		if (PrevEndPointIndex >= 0)
		{
			float MidPoint = (Subgraph_ZigZagLine[ZigZagIndex] + Subgraph_ZigZagLine[PrevEndPointIndex]) / 2.0f;
			if (Subgraph_ZigzagMidPoint[ZigZagIndex] != MidPoint)
			{
				for (int UpdateIndex=PrevEndPointIndex+1; UpdateIndex<=ZigZagIndex; UpdateIndex++)
					Subgraph_ZigzagMidPoint[UpdateIndex] = MidPoint;
			}
		}

		if (Input_ColorZigZagLine.GetIndex() == 2 || Input_ColorZigZagLine.GetIndex() == 3) // determine zig zag trend color with confirmed volume
		{
			if (PrevEndPointIndex >= 0)
			{
				float Trend = ZigZagPeakType[ZigZagIndex];  // default trend is current direction

				if (PrevEndPointIndex > 0 && ZigZagReset[PrevEndPointIndex] == 0)	// have more than one swing
				{
					if (((Input_ColorZigZagLine.GetIndex() == 2 && Trend != ZigZagTrend[PrevEndPointIndex]) || // use current trend and volume
						Input_ColorZigZagLine.GetIndex() == 3)  // only use volume
						&& Subgraph_AccumulatedVolume[ZigZagIndex] < Subgraph_AccumulatedVolume[PrevEndPointIndex])
					{
						Trend = -Trend;
					}
				}

				if (ZigZagTrend[ZigZagIndex] != Trend)
				{
					for (int UpdateIndex=PrevEndPointIndex+1; UpdateIndex<=ZigZagIndex; UpdateIndex++)
					{
						ZigZagTrend[UpdateIndex] = Trend;

						if (Trend > 0)
							Subgraph_ZigZagLine.DataColor[UpdateIndex] = Subgraph_ZigZagLine.PrimaryColor;
						else
							Subgraph_ZigZagLine.DataColor[UpdateIndex] = Subgraph_ZigZagLine.SecondaryColor;
					}
				}
			}
		}

		//At this point we have a label to draw

		PriorLastZZEndpointIndex = ZigZagIndex;

		SCString BarLabelText;

		int VerticalTextAlignment = ZigZagPeakType[ZigZagIndex] == 1.0 ? DT_BOTTOM : DT_TOP;

		double ZigzagLineLength = 0;
		int CurrentZigZagNumBars = 0;

		CreateZigZagLineLabel(BarLabelText, ZigZagPeakType, ZigZagIndex, ZigZagPeakIndex, Input_ShowRevPrice, Input_UseMultiLineLabels, sc, Subgraph_ZigZagLine, Input_ShowLength, ShowLabelPrefixes, Input_ShowTime, Input_IncludeSecondsInTimeDisplay, Input_ShowZigZagVolume, Subgraph_AccumulatedVolume, Input_FormatVolumeWithLargeNumberSuffix, Input_ShowZigZagDuration, Input_ShowZigZagNumBars, Input_DisplayZigZagVolumeDividedByLengthInTicks, ZigZagReset, Input_DisplayHHHLLLLHLabels, Subgraph_TextLabels, ZigzagLineLength, CurrentZigZagNumBars, Input_Divisor);

		if (BarLabelText.GetLength() > 0 && !sc.HideStudy)
		{
			s_UseTool Tool; 
			Tool.Clear();
			Tool.ChartNumber = sc.ChartNumber;
			Tool.Region = sc.GraphRegion;
			Tool.DrawingType = DRAWING_TEXT;
			Tool.ReverseTextColor = 0;
			Tool.BeginIndex = ZigZagIndex;
	
			float Offset;
			if (Input_LabelOffsetType.GetIndex() == 0)
				Offset = Input_LabelsOffset.GetFloat()*0.01f*(sc.High[ZigZagIndex]-sc.Low[ZigZagIndex]);
			else
				Offset = Input_LabelsOffset.GetFloat()*sc.TickSize;

			if(ZigZagPeakType[ZigZagIndex] == 1.0f)
				Tool.BeginValue = Subgraph_ZigZagLine[ZigZagIndex] + Offset;
			else
				Tool.BeginValue = Subgraph_ZigZagLine[ZigZagIndex] - Offset;				

			if (ZigZagPeakType[ZigZagIndex] == 1.0f)
				Tool.Color =  Subgraph_TextLabels.PrimaryColor;
			else
				Tool.Color = Subgraph_TextLabels.SecondaryColor;

			//Tool.FontFace = sc.GetChartTextFontFaceName();
			Tool.FontSize = Subgraph_TextLabels.LineWidth;
			Tool.FontBold = true;
			Tool.Text = BarLabelText;
			Tool.AddMethod = UTAM_ADD_ALWAYS;
			Tool.LineNumber = -1;

			if (Input_UseMultiLineLabels.GetYesNo())
			{
				if (Input_MultiLineTextHorizontalAlignment.GetIndex() == 0)
				{
					Tool.TextAlignment = DT_LEFT | VerticalTextAlignment;
				}
				else if (Input_MultiLineTextHorizontalAlignment.GetIndex() == 1)
				{
					Tool.TextAlignment = DT_CENTER | VerticalTextAlignment;
				}
				else
				{
					Tool.TextAlignment = DT_RIGHT | VerticalTextAlignment;
				}
			}
			else
			{
				if (Input_SingleLineTextHorizontalAlignment.GetIndex() == 0)
				{
					Tool.TextAlignment = DT_LEFT | VerticalTextAlignment;
				}
				else if (Input_SingleLineTextHorizontalAlignment.GetIndex() == 1)
				{
					Tool.TextAlignment = DT_CENTER | VerticalTextAlignment;
				}
				else
				{
					Tool.TextAlignment = DT_RIGHT | VerticalTextAlignment;
				}
			}

			sc.UseTool(Tool);
			LastUsedLabelDrawingNumber = Tool.LineNumber;
		}

		if (Input_ExtendEndPointsUntilFutureIntersection.GetYesNo())
		{
			sc.AddLineUntilFutureIntersection
			(ZigZagIndex
				, 0  // LineIDForBar
				, Subgraph_ZigZagLine[ZigZagIndex]
				, ZigZagPeakType[ZigZagIndex] == 1.0f ? Subgraph_ExtensionLinesSubgraph.PrimaryColor : Subgraph_ExtensionLinesSubgraph.SecondaryColor
				, Subgraph_ExtensionLinesSubgraph.LineWidth
				, Subgraph_ExtensionLinesSubgraph.LineStyle
				, Input_DisplayValueLabel.GetBoolean()
				, false
				, ""
			);

			LastUsedBarIndexForExtensionLine = ZigZagIndex;
		}

		Subgraph_ReversalPrice[ZigZagIndex] = Subgraph_ZigZagLine[ZigZagIndex];
		Subgraph_ZigzagLength[ZigZagIndex] = (float)ZigzagLineLength;
		Subgraph_ZigzagNumBars[ZigZagIndex] = (float)CurrentZigZagNumBars;
	}

	//Determine the beginning of the last line
	int Count = 0; //To count the number of zigzag pivots
	int StartingIndex = sc.ArraySize;
	while (StartingIndex > 0 && Count < 2)
	{
		StartingIndex--;
		if (ZigZagPeakType[StartingIndex] != 0.0f)
			Count ++;
	}

	sc.EarliestUpdateSubgraphDataArrayIndex = StartingIndex;
}
