// Sierra Chart 2962+ source rebuild. Keep DLL names, exported study names,
// subgraph indexes and input indexes unchanged for chartbook compatibility.
// ACSIL source refreshed for Sierra Chart 2962+; rebuild against installed Sierra Chart headers.
#include "sierrachart.h"
#include <vector>
#include <string>
#include <sstream>
#include <cstdlib>

SCDLLName("Custom Target Lines Same Scale")

#define MAX_TARGET_LINES 50

SCSFExport scsf_CustomTargetLinesSameScale(SCStudyInterfaceRef sc)
{
    SCInputRef TargetPricesInput = sc.Input[0];
    SCInputRef LineColorInput    = sc.Input[1];
    SCInputRef LineWidthInput    = sc.Input[2];
    SCInputRef LineStyleInput    = sc.Input[3];

    if (sc.SetDefaults)
    {
        sc.GraphName = "Custom Target Lines Same Scale";
        sc.StudyDescription = "Enter comma-separated target prices and plot continuous horizontal lines across the chart with right-side price labels, without using an independent study scale.";
        sc.AutoLoop = 0;
        sc.GraphRegion = 0;
        sc.ValueFormat = VALUEFORMAT_INHERITED;

        // Keep this study on the same scale as the main price graph so it does not
        // create its own scale and crunch the right-side price scale.
        sc.ScaleRangeType = SCALE_SAMEASREGION;

        TargetPricesInput.Name = "Target Prices (comma separated)";
        TargetPricesInput.SetString("");

        LineColorInput.Name = "Line Color";
        LineColorInput.SetColor(RGB(0, 255, 0));

        LineWidthInput.Name = "Line Width";
        LineWidthInput.SetInt(2);
        LineWidthInput.SetIntLimits(1, 10);

        LineStyleInput.Name = "Line Style";
        LineStyleInput.SetCustomInputStrings("Solid;Dash;Dot;DashDot;DashDotDot");
        LineStyleInput.SetCustomInputIndex(0);

        for (int i = 0; i < MAX_TARGET_LINES; ++i)
        {
            SCSubgraphRef sg = sc.Subgraph[i];
            sg.Name = " ";
            sg.DrawStyle = DRAWSTYLE_LINE;
            sg.PrimaryColor = RGB(0, 255, 0);
            sg.LineWidth = 2;
            sg.DrawZeros = false;
            sg.LineLabel = LL_DISPLAY_VALUE | LL_VALUE_ALIGN_VALUES_SCALE;
        }

        return;
    }

    COLORREF lineColor = LineColorInput.GetColor();
    int lineWidth = LineWidthInput.GetInt();
    int styleIndex = LineStyleInput.GetIndex();

    SubgraphLineStyles lineStyle = LINESTYLE_SOLID;
    switch (styleIndex)
    {
        case 1: lineStyle = LINESTYLE_DASH; break;
        case 2: lineStyle = LINESTYLE_DOT; break;
        case 3: lineStyle = LINESTYLE_DASHDOT; break;
        case 4: lineStyle = LINESTYLE_DASHDOTDOT; break;
        default: lineStyle = LINESTYLE_SOLID; break;
    }

    for (int i = 0; i < MAX_TARGET_LINES; ++i)
    {
        SCSubgraphRef sg = sc.Subgraph[i];
        sg.Name = " ";
        sg.DrawStyle = DRAWSTYLE_LINE;
        sg.PrimaryColor = lineColor;
        sg.LineWidth = lineWidth;
        sg.LineStyle = lineStyle;
        sg.DrawZeros = false;
        sg.LineLabel = LL_DISPLAY_VALUE | LL_VALUE_ALIGN_VALUES_SCALE;
    }

    std::vector<double> targetPrices;
    const char* rawText = TargetPricesInput.GetString();
    std::string targetText = (rawText != nullptr) ? rawText : "";

    std::stringstream ss(targetText);
    std::string token;

    while (std::getline(ss, token, ','))
    {
        if (token.empty())
            continue;

        char* endPtr = nullptr;
        double value = std::strtod(token.c_str(), &endPtr);

        if (endPtr != token.c_str())
            targetPrices.push_back(value);

        if ((int)targetPrices.size() >= MAX_TARGET_LINES)
            break;
    }

    // Only rewrite bars Sierra Chart says need updating. A full recalculation
    // starts at zero and still refreshes every historical bar.
    const int arraySize = sc.ArraySize;
    const int firstBar = sc.IsFullRecalculation ? 0 : sc.UpdateStartIndex;
    if (firstBar >= arraySize)
        return;

    for (int lineIndex = 0; lineIndex < MAX_TARGET_LINES; ++lineIndex)
    {
        SCSubgraphRef sg = sc.Subgraph[lineIndex];

        if (lineIndex < (int)targetPrices.size())
        {
            const double targetPrice = targetPrices[lineIndex];

            for (int barIndex = firstBar; barIndex < arraySize; ++barIndex)
                sg[barIndex] = targetPrice;
        }
        else
        {
            for (int barIndex = firstBar; barIndex < arraySize; ++barIndex)
                sg[barIndex] = 0.0;
        }
    }
}
