/*****************************************************************************
	can't get the sc.DeleteLineUntilFutureIntersection and the endIndex to work? 
*****************************************************************************/

#include "sierrachart.h"
#include "scstudyfunctions.h"

/****************************************************************************/

SCDLLName("linesExample")

/*==========================================================================*/
//{{{ helper functions for SC studys example 

/*==========================================================================*/
int IsSwingHighAllowEqual_S(SCStudyInterfaceRef sc, int AllowEqual, int Index, int Length)
{
  for(int i = 1; i <= Length; i++)
  {

    if (AllowEqual)
    {
      if (sc.FormattedEvaluate(sc.BaseData [SC_HIGH][Index] , sc.BasedOnGraphValueFormat, LESS_OPERATOR, sc.BaseData [SC_HIGH][Index-i], sc.BasedOnGraphValueFormat)
        ||
        sc.FormattedEvaluate(sc.BaseData [SC_HIGH][Index] , sc.BasedOnGraphValueFormat, LESS_OPERATOR, sc.BaseData [SC_HIGH][Index+i], sc.BasedOnGraphValueFormat)
        )
        return 0;


    }
    else
    {
      if (sc.FormattedEvaluate(sc.BaseData [SC_HIGH][Index] , sc.BasedOnGraphValueFormat, LESS_EQUAL_OPERATOR, sc.BaseData [SC_HIGH][Index-i], sc.BasedOnGraphValueFormat)
        ||
        sc.FormattedEvaluate(sc.BaseData [SC_HIGH][Index] , sc.BasedOnGraphValueFormat, LESS_EQUAL_OPERATOR, sc.BaseData [SC_HIGH][Index+i], sc.BasedOnGraphValueFormat)
        )
        return 0;


    }
  }

  return 1;
}

/*==========================================================================*/
int IsSwingLowAllowEqual_S(SCStudyInterfaceRef sc, int AllowEqual, int Index, int Length)
{
  for(int i = 1; i <= Length; i++)
  {

    if (AllowEqual)
    {
      if (sc.FormattedEvaluate(sc.BaseData [SC_LOW][Index] , sc.BasedOnGraphValueFormat, GREATER_OPERATOR, sc.BaseData [SC_LOW][Index-i], sc.BasedOnGraphValueFormat)
        ||
        sc.FormattedEvaluate(sc.BaseData [SC_LOW][Index] , sc.BasedOnGraphValueFormat, GREATER_OPERATOR, sc.BaseData [SC_LOW][Index+i], sc.BasedOnGraphValueFormat)
        )
        return 0;


    }
    else
    {
      if (sc.FormattedEvaluate(sc.BaseData [SC_LOW][Index] , sc.BasedOnGraphValueFormat, GREATER_EQUAL_OPERATOR, sc.BaseData [SC_LOW][Index-i], sc.BasedOnGraphValueFormat)
        ||
        sc.FormattedEvaluate(sc.BaseData [SC_LOW][Index] , sc.BasedOnGraphValueFormat, GREATER_EQUAL_OPERATOR, sc.BaseData [SC_LOW][Index+i], sc.BasedOnGraphValueFormat)
        )
        return 0;


    }
  }

  return 1;
}


/*============================================================================
  ----------------------------------------------------------------------------*/
//}}}

/*==========================================================================*/
SCSFExport scsf_SwingHighAndLow(SCStudyInterfaceRef sc)
{
// {{{  
  SCSubgraphRef Subgraph_SwingHigh = sc.Subgraph[0];
  SCSubgraphRef Subgraph_SwingLow = sc.Subgraph[1];
  SCSubgraphRef Subgraph_LineProperties = sc.Subgraph[2];
  SCSubgraphRef Subgraph_LinePropertiesIntersected = sc.Subgraph[3];

  SCInputRef Input_ArrowOffsetValue = sc.Input[0];
  SCInputRef Input_Length = sc.Input[1];
  SCInputRef Input_AllowEqualBars = sc.Input[2];
  SCInputRef Input_ExtendSwings = sc.Input[3];
  SCInputRef Input_IntersectAction = sc.Input[5];
  // {{{  Input_How_ManyBars
  // calculate on this many bars only, not the whole chart
  SCInputRef Input_How_ManyBars = sc.Input[4];
  

  if(sc.SetDefaults){
  Input_How_ManyBars.Name.Format("Input_How_ManyBars: calculate only on the last x bars (i.e. 100-5000+) ");
  Input_How_ManyBars.SetInt(2000);
  Input_How_ManyBars.SetIntLimits(1, 60000);
  }
  // }}}

  if (sc.SetDefaults)
  {
    sc.GraphName = "Swing High And Low";

    sc.AutoLoop = true;
    sc.GraphRegion = 0;
    sc.ValueFormat= VALUEFORMAT_INHERITED;

    Subgraph_SwingHigh.Name = "Swing High";
    Subgraph_SwingHigh.DrawStyle = DRAWSTYLE_ARROW_DOWN;
    Subgraph_SwingHigh.PrimaryColor = RGB(0,255,0);
    Subgraph_SwingHigh.DrawZeros = false;
    Subgraph_SwingHigh.PrimaryColor = RGB(255,0,0);
    Subgraph_SwingHigh.LineWidth = 3;

    Subgraph_SwingLow.Name = "Swing Low";
    Subgraph_SwingLow.DrawStyle = DRAWSTYLE_ARROW_UP;
    Subgraph_SwingLow.PrimaryColor = RGB(255,0,255);
    Subgraph_SwingLow.DrawZeros = false;
    Subgraph_SwingLow.LineWidth = 3;
    Subgraph_SwingLow.PrimaryColor = RGB(0,255,0);


    Subgraph_LineProperties.Name = "Line Properties";
    Subgraph_LineProperties.DrawStyle = DRAWSTYLE_SUBGRAPH_NAME_AND_VALUE_LABELS_ONLY;
    Subgraph_LineProperties.LineWidth = 1;
    Subgraph_LineProperties.PrimaryColor = RGB(255, 0, 0);
    Subgraph_LineProperties.SecondaryColor = RGB(0, 255, 0);
    Subgraph_LineProperties.SecondaryColorUsed = true;
    Subgraph_LineProperties.DrawZeros = false;

    Subgraph_LinePropertiesIntersected.Name = "Line Properties Intersected";
    Subgraph_LinePropertiesIntersected.DrawStyle = DRAWSTYLE_SUBGRAPH_NAME_AND_VALUE_LABELS_ONLY;
    Subgraph_LinePropertiesIntersected.LineWidth = 1;
    Subgraph_LinePropertiesIntersected.PrimaryColor = RGB(255, 128, 0);
    Subgraph_LinePropertiesIntersected.SecondaryColor = RGB(255, 255, 0);
    Subgraph_LinePropertiesIntersected.SecondaryColorUsed = true;
    Subgraph_LinePropertiesIntersected.DrawZeros = false;

    Input_ArrowOffsetValue.Name = "Arrow Offset as Percentage";
    Input_ArrowOffsetValue.SetFloat(3);

    Input_Length.Name = "Length";
    Input_Length.SetInt(1);
    Input_Length.SetIntLimits(1,MAX_STUDY_LENGTH);

    Input_AllowEqualBars.Name = "Allow Equal High/Low Bars";
    Input_AllowEqualBars.SetYesNo(false);

    Input_ExtendSwings.Name = "Extend Swings Until Future Intersection";
    Input_ExtendSwings.SetYesNo(true);

    Input_IntersectAction.Name = "Intersect Action";
    Input_IntersectAction.SetCustomInputStrings("Delete;Change Color");
    Input_IntersectAction.SetCustomInputIndex(0);

    return;
  }

  auto& r_InitialCalculation = sc.GetPersistentIntFast(0);

  if (sc.Index == 0)
      r_InitialCalculation = 1;

  // Limit calculation to last 100? bars
  if (sc.Index >= sc.ArraySize - Input_How_ManyBars.GetInt()-1) {

    int IndexToEvaluate = sc.Index - Input_Length.GetInt();

    if(IndexToEvaluate - Input_Length.GetInt() < 0)
    {
      return;
    }

    sc.EarliestUpdateSubgraphDataArrayIndex = IndexToEvaluate;

    float ArrowOffset=(sc.High[IndexToEvaluate] - sc.Low[IndexToEvaluate] )*(Input_ArrowOffsetValue.GetFloat() * 0.01f);

    Subgraph_SwingHigh[IndexToEvaluate] = 0;
    Subgraph_SwingLow[IndexToEvaluate] = 0;

    // check for Swing High
    if (!Input_AllowEqualBars.GetYesNo())
    {
      if (sc.IsSwingHigh(sc.High, IndexToEvaluate, Input_Length.GetInt()))
        Subgraph_SwingHigh[IndexToEvaluate] = sc.High[IndexToEvaluate] + ArrowOffset;
    }
    else if (IsSwingHighAllowEqual_S( sc, true , IndexToEvaluate, Input_Length.GetInt()))
      Subgraph_SwingHigh[IndexToEvaluate] = sc.High[IndexToEvaluate] + ArrowOffset;


    // check for Swing Low
    if (!Input_AllowEqualBars.GetYesNo())
    {
      if (sc.IsSwingLow(sc.Low, IndexToEvaluate, Input_Length.GetInt()))
        Subgraph_SwingLow[IndexToEvaluate] = sc.Low[IndexToEvaluate] - ArrowOffset;
    }
    else if (IsSwingLowAllowEqual_S(sc, true , IndexToEvaluate,  Input_Length.GetInt()))
      Subgraph_SwingLow[IndexToEvaluate] = sc.Low[IndexToEvaluate] - ArrowOffset;

    if (Input_ExtendSwings.GetYesNo())
    {
      if (Subgraph_SwingHigh[IndexToEvaluate] != 0)
      {
        sc.AddLineUntilFutureIntersection
          (IndexToEvaluate
           , 1  // LineIDForBar
           , Subgraph_SwingHigh[IndexToEvaluate]
           , Subgraph_LineProperties.PrimaryColor
           , Subgraph_LineProperties.LineWidth
           , Subgraph_LineProperties.LineStyle
           , false
           , false
           , ""
          );
      }
      else
      {
        sc.DeleteLineUntilFutureIntersection(IndexToEvaluate, 1);
      }
    }

    if (Input_ExtendSwings.GetYesNo())
    {
      if (Subgraph_SwingLow[IndexToEvaluate] != 0)
      {
        sc.AddLineUntilFutureIntersection
          (IndexToEvaluate
           , 2  // LineIDForBar
           , Subgraph_SwingLow[IndexToEvaluate]
           , Subgraph_LineProperties.SecondaryColor
           , Subgraph_LineProperties.LineWidth
           , Subgraph_LineProperties.LineStyle
           , false
           , false
           , ""
          );
      }
      else
      {
        sc.DeleteLineUntilFutureIntersection(IndexToEvaluate, 2);
      }
    }

//{{{ delete line working? 
    //if (!sc.IsFullRecalculation
    //    && sc.GetBarHasClosedStatus() == BHCS_BAR_HAS_CLOSED){
    //  const auto numLines = sc.GetNumLinesUntilFutureIntersection(sc.ChartNumber, sc.StudyGraphInstanceID) - 1;

    //  for (auto lineIndex = 0; lineIndex < numLines; ++lineIndex)
    //  {
    //    auto lineID{ 0 };
    //    auto startIndex{ 0 };
    //    auto endIndex{ 0 };
    //    auto lineValue{ 0.0f };
    //    if (sc.GetStudyLineUntilFutureIntersectionByIndex(sc.ChartNumber
    //          , sc.StudyGraphInstanceID
    //          , lineIndex
    //          , lineID
    //          , startIndex
    //          , lineValue
    //          , endIndex))

    //    {
    //      if (endIndex > 0)
    //        sc.DeleteLineUntilFutureIntersection(startIndex, lineID);
    //    }
    //  }
    //}
    // 

    if (!sc.IsFullRecalculation
        && (sc.GetBarHasClosedStatus() == BHCS_BAR_HAS_CLOSED
            || r_InitialCalculation != 0))
    {
        r_InitialCalculation = 0;
        
        if (Input_IntersectAction.GetIndex() == 0) // delete
        {
            auto lineIndex{ 0 };
            auto lineID{ 0 };
            auto startIndex{ 0 };
            auto endIndex{ 0 };
            auto lineValue{ 0.0f };

            while (sc.GetStudyLineUntilFutureIntersectionByIndex(sc.ChartNumber
                , sc.StudyGraphInstanceID
                , lineIndex
                , lineID
                , startIndex
                , lineValue
                , endIndex))
            {
                if (endIndex > 0)
                    sc.DeleteLineUntilFutureIntersection(startIndex, lineID);
                else
                    lineIndex++;
            }
        }
        else // change color
        {
            const auto numLines = sc.GetNumLinesUntilFutureIntersection(sc.ChartNumber, sc.StudyGraphInstanceID) - 1;

            for (auto lineIndex = 0; lineIndex < numLines; ++lineIndex)
            {
                auto lineID{ 0 };
                auto startIndex{ 0 };
                auto endIndex{ 0 };
                auto lineValue{ 0.0f };
                if (sc.GetStudyLineUntilFutureIntersectionByIndex(sc.ChartNumber
                    , sc.StudyGraphInstanceID
                    , lineIndex
                    , lineID
                    , startIndex
                    , lineValue
                    , endIndex))

                {
                    if (endIndex <= 0)
                        continue;
                    
                    auto lineColor = lineID == 1 ? Subgraph_LinePropertiesIntersected.PrimaryColor : Subgraph_LinePropertiesIntersected.SecondaryColor;

                    sc.AddLineUntilFutureIntersection
                    (startIndex
                        , lineID
                        , lineValue
                        , lineColor
                        , Subgraph_LinePropertiesIntersected.LineWidth
                        , Subgraph_LinePropertiesIntersected.LineStyle
                        , false
                        , false
                        , ""
                    );
                }
            }
        }
    }
//}}}
  }
// }}}
}

