#include "sierrachart.h"
#include <vector>
SCDLLName("Study Collection vs. Timeframe")

// Persistent variable to store the last applied study collection name
SCString LastCollectionName;

// Function to convert bar period string to milliseconds
long long ParseBarPeriodToMs(SCString period_str)
{
    std::vector<char*> parts;
    int num_tokens = period_str.Tokenize("-", parts);
    if (num_tokens < 3 || num_tokens > 4)
        return -1;

    int days = atoi(parts[0]);
    int mins = atoi(parts[1]);
    int secs = atoi(parts[2]);
    int ms_val = (num_tokens == 4) ? atoi(parts[3]) : 0;

    long long user_seconds = (long long)days * 86400LL + (long long)mins * 60LL + secs;
    return user_seconds * 1000LL + ms_val;
}

/*==========================================================================*/
SCSFExport scsf_StudyCollectionVsTimeframe(SCStudyInterfaceRef sc)
{
    // Persistent variable to store the last applied bar period in milliseconds
    SCSubgraphRef LastBarPeriodMs = sc.Subgraph[0];

    if (sc.SetDefaults)
    {
        // Set the configuration and defaults
        sc.GraphName = "Study Collection vs. Timeframe";
        sc.StudyDescription = "Applies a study collection based on the bar period value for the chart. Supports up to 10 mappings. NOTE: Previous study collections are not automatically removed due to API limitations. To avoid overlap, manually remove prior studies (Analysis > Studies > Remove All Studies) before changing the bar period.";

        sc.AutoLoop = 0;  // No automatic looping needed
        sc.FreeDLL = 1;   // Set to 1 if compiling for release

        // Define at least 10 bar period and study collection pairs
        for (int i = 0; i < 10; ++i)
        {
            sc.Input[2 * i].Name.Format("Bar Period %d (D-M-S[-MS])", i + 1);
            sc.Input[2 * i].SetDescription("Enter in format like 0-5-0 or 0-5-0-0");
            sc.Input[2 * i].SetString("");

            sc.Input[2 * i + 1].Name.Format("Study Collection %d", i + 1);
            sc.Input[2 * i + 1].SetDescription("Name of the study collection without extension");
            sc.Input[2 * i + 1].SetString("");
        }

        // Initialize persistent variable for tracking last bar period
        LastBarPeriodMs.Name = "Last Bar Period (ms)";
        LastBarPeriodMs[0] = 0.0f;

        return;
    }

    // Get current bar period parameters
    n_ACSIL::s_BarPeriod BarPeriod;
    sc.GetBarPeriodParameters(BarPeriod);

    // Only support intraday time-based bars
    if (BarPeriod.ChartDataType != INTRADAY_DATA || BarPeriod.IntradayChartBarPeriodType != IBPT_DAYS_MINS_SECS)
        return;

    // Calculate current total milliseconds
    long long total_seconds = (long long)BarPeriod.IntradayChartBarPeriodParameter1;
    int ms = BarPeriod.IntradayChartBarPeriodParameter2;
    long long current_ms = total_seconds * 1000LL + ms;

    // Check if bar period has changed
    bool bar_period_changed = (current_ms != (long long)LastBarPeriodMs[0]);

    // Update the stored bar period
    LastBarPeriodMs[0] = (float)current_ms;

    // If bar period changed, log a message to remind user to remove previous studies
    if (bar_period_changed && !LastCollectionName.IsEmpty())
    {
        SCString message;
        message.Format("Bar period changed to %lld ms. Please manually remove previous studies (Analysis > Studies > Remove All Studies) to avoid overlap before applying new study collection.", current_ms);
        sc.AddMessageToLog(message, 1);
    }

    // Loop through the 10 possible inputs
    for (int i = 0; i < 10; ++i)
    {
        SCString period_str = sc.Input[2 * i].GetString();
        if (period_str.IsEmpty())
            continue;

        long long user_ms = ParseBarPeriodToMs(period_str);
        if (user_ms == -1)
            continue;

        if (user_ms == current_ms)
        {
            SCString collection_name = sc.Input[2 * i + 1].GetString();
            if (!collection_name.IsEmpty())
            {
                // Only apply the new collection if it’s different or if the bar period changed
                if (bar_period_changed || collection_name.CompareNoCase(LastCollectionName) != 0)
                {
                    // Apply the study collection to the current chart
                    sc.ApplyStudyCollection(sc.ChartNumber, collection_name, 0);
                    LastCollectionName = collection_name; // Update the last applied collection
                    SCString message;
                    message.Format("Applied study collection '%s' for bar period %lld ms.", collection_name.GetChars(), current_ms);
                    sc.AddMessageToLog(message, 1);
                }
            }
            // Apply only the first matching one
            return;
        }
    }
}