#include "Selection.h"

// Allows for selections that return a string when selected, ideal for the shop
std::string Selection(std::vector<std::pair<std::string, std::string>> selections)
{
    int value = 0;
    bool bSetup = true;
    
    do
    {
        if (!bSetup)
        {
            // Initialization in an if statement, this is allowed from C++17. This makes it so the ch is only used in this if statement, including else if
            // It gets the character and then checks if it is the upper or lower version of s
            if (const int ch = _getch(); ch == 'S' || ch == 's')
            {
                // If it is "s" then it will check if adding 1 would make it over the limit of the selection sizes if so it will not add one, but if it can, it will
                if (value + 1 <= static_cast<int>(selections.size()) - 1)
                {
                    value++;
                }
            }
            // Checks for the character w
            else if (ch == 'W' || ch == 'w')
            {
                // If going down 1 is below 0 it will not do this as it is not valid else it will minus 1
                if (value - 1 >= 0)
                {
                    value--;
                }
            }
            // If the character is 13 which is ASCII for the return key then it will clear the console and return the value from the selection's array and the second element in the pair
            else if (ch == 13)
            {
                Utilities::ClearConsole();
                return selections[value].second;
            }
        }

        // If it is not on the first setup it will clear the lines before remaking them, this is, so I don't need to clear the whole console each time the user goes up or down
        if (!bSetup)
            Utilities::ClearLine(static_cast<int>(selections.size()));

        // Starts an index at 0, I need this index because the iterator is not able to be converted to an int
        int index = 0;

        // If the iterator is not equal to the end add one to it, also add one to the index value. I am using the prefix operators because it will add these values first before checking the condition
        // rather than i++ which checks the condition then adds the value
        for (auto i = selections.begin(); i != selections.end(); ++i, ++index)
        {
            // If index == the value that has been set before it will print out a ">" in front of the items first element in the pair
            if (index == value)
            {
                std::cout << "> " << i->first << "\n";
            }
            // Else it will print out two spaces to make everything inline
            else
            {
                std::cout << "  " << i->first << "\n";
            }
        }

        // If it is the first setup of this selection it will change the setup to be false as it has generated once
        if (bSetup)
            bSetup = !bSetup;
        
    } while(true);
    
}

// Allows for selections that run functions to each selection, ideal for menus
// Using overloading functions to allow for multiple versions and for the IDE to infer which one I am using
std::string Selection(std::vector<std::pair<std::string, std::function<void()>>> selections)
{
    int value = 0;
    bool bSetup = true;

    do
    {
        if (!bSetup)
        {
            // Initialization in an if statement, this is allowed from C++17. This makes it so the ch is only used in this if statement, including else if
            // It gets the character and then checks if it is the upper or lower version of s
            if (const int ch = _getch(); ch == 'S' || ch == 's')
            {
                // If it is "s" then it will check if adding 1 would make it over the limit of the selection sizes if so it will not add one, but if it can, it will
                if (value + 1 <= static_cast<int>(selections.size()) - 1)
                {
                    value++;
                }
            }
            // Checks for the character w
            else if (ch == 'W' || ch == 'w')
            {
                // If going down 1 is below 0 it will not do this as it is not valid else it will minus 1
                if (value - 1 >= 0)
                {
                    value--;
                }
            }
            // If the character is 13 which is ASCII for the return key then it will clear the console and return the value from the selection's array and the second element in the pair
            else if (ch == 13)
            {
                Utilities::ClearConsole();
                if (selections[value].first == "Quit")
                {
                    selections[value].second();
                    return selections[value].first;
                }
                    
                selections[value].second();
                break;
            }
        }

        // If it is not on the first setup it will clear the lines before remaking them, this is, so I don't need to clear the whole console each time the user goes up or down
        if (!bSetup)
            Utilities::ClearLine(static_cast<int>(selections.size()));

        // Starts an index at 0, I need this index because the iterator is not able to be converted to an int
        int index = 0;
        
        // If the iterator is not equal to the end add one to it, also add one to the index value. I am using the prefix operators because it will add these values first before checking the condition
        // rather than i++ which checks the condition then adds the value
        for (auto i = selections.begin(); i != selections.end(); ++i, ++index)
        {
            // If index == the value that has been set before it will print out a ">" in front of the items first element in the pair
            if (index == value)
            {
                std::cout << "> " << i->first << "\n";
            }
            // Else it will print out two spaces to make everything inline
            else
            {
                std::cout << "  " << i->first << "\n";
            }
        }
        
        // If it is the first setup of this selection it will change the setup to be false as it has generated once
        if (bSetup)
            bSetup = !bSetup;
        
    } while(true);

    return "Other";
}
