/*
 * Copyright (C) Jan 2006 Mellanox Technologies Ltd. All rights reserved.
 * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
 * General Public License (GPL) Version 2, available from the file
 * COPYING in the main directory of this source tree, or the
 * OpenIB.org BSD license below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include "menu.h"
#include <algorithm>

BaseMenu::BaseMenu()
{
    _isPrev = false;
    _valid = false;
    _all = 0;
    _goBack = 0;
    _exit = 0;
    _maxChoice = 0;
}

BaseMenu::~BaseMenu() {}

FileTypeMenu::FileTypeMenu() : BaseMenu() {}

FileTypeMenu::~FileTypeMenu() {}
BaseMenu* FileTypeMenu::getNextMenu(CmdLineParams& cmd_params, filesOPtions& filterOPtions)
{
    BaseMenu* newMenu = NULL;

    if (!cmd_params.download_dev.length())
    {
        newMenu = new DevFamilyMenu;
        return newMenu;
    }
    else
    {
        DevFamilyMenu::setValuesDirectly(cmd_params, filterOPtions);
    }

    if (filterOPtions.file_type != "mfa" && !cmd_params.download_os.length())
    {
        newMenu = new OSMenu;
        return newMenu;
    }
    else
    {
        OSMenu::setValuesDirectly(cmd_params, filterOPtions);
    }

    // newMenu = new PickFilesMenu;
    return newMenu;
}

BaseMenu* FileTypeMenu::getPrevMenu(CmdLineParams& cmd_params, filesOPtions& filterOPtions)
{
    (void)cmd_params;
    (void)filterOPtions;
    BaseMenu* newMenu = NULL;
    return newMenu;
}

bool FileTypeMenu::isPrevious(CmdLineParams& cmd_params, filesOPtions& filterOPtions)
{
    (void)cmd_params;
    (void)filterOPtions;
    return _isPrev;
}

bool FileTypeMenu::isValid(CmdLineParams& cmd_params, filesOPtions& filterOPtions)
{
    (void)filterOPtions;
    return !cmd_params.download_type.length();
}

void FileTypeMenu::setValuesDirectly(CmdLineParams& cmd_params, filesOPtions& filterOPtions)
{
    if (cmd_params.download_type == "")
    {
        filterOPtions.file_type = "";
    }
    else
    {
        filterOPtions.file_type = cmd_params.download_type;
    }
}

void FileTypeMenu::generateMenu(CmdLineParams& cmd_params, filesOPtions& filterOPtions)
{
    _menuText = "";
    if (isValid(cmd_params, filterOPtions))
    {
        _menuText = "------ Download Type Selection ------\n";
        _menuText += "\t1- MFA            : (Contains FW images)\n";
        _menuText += "\t2- Self_Extractor : (Update Package for Mellanox Firmware)\n";
        _menuText += "\t3- All\n";
        _menuText += "\t4- Exit\n";
        _menuText += "\n-?- Select an option: ";
        _maxChoice = 4;
        printText();
    }
    else
    {
        setValuesDirectly(cmd_params, filterOPtions);
    }
}

bool FileTypeMenu::parseChoice(int choice, bool& isExit, bool& isPrev, filesOPtions& filterOPtions)
{
    isPrev = false;
    isExit = false;
    if (choice > _maxChoice || choice <= 0)
    {
        fprintf(stderr, "-E- Invalid choice!\n");
        return false;
    }

    switch (choice)
    {
        case 4:
            isExit = true;
            break;

        case 3:
            filterOPtions.file_type = "all";
            break;

        case 2:
            filterOPtions.file_type = "self_extractor";
            break;

        default:
            filterOPtions.file_type = "mfa";
    }
    return true;
}

BaseMenu* DevFamilyMenu::getNextMenu(CmdLineParams& cmd_params, filesOPtions& filterOPtions)
{
    BaseMenu* newMenu = NULL;

    if (filterOPtions.file_type != "mfa" && !cmd_params.download_os.length())
    {
        newMenu = new OSMenu;
        return newMenu;
    }
    else
    {
        OSMenu::setValuesDirectly(cmd_params, filterOPtions);
    }

    // newMenu = new PickFilesMenu;
    return newMenu;
}

DevFamilyMenu::DevFamilyMenu() : BaseMenu() {}

DevFamilyMenu::~DevFamilyMenu() {}

BaseMenu* DevFamilyMenu::getPrevMenu(CmdLineParams& cmd_params, filesOPtions& filterOPtions)
{
    (void)filterOPtions;
    BaseMenu* newMenu = NULL;
    if (!cmd_params.download_type.length())
    {
        newMenu = new FileTypeMenu;
    }
    return newMenu;
}

bool DevFamilyMenu::isPrevious(CmdLineParams& cmd_params, filesOPtions& filterOPtions)
{
    (void)filterOPtions;
    _isPrev = !cmd_params.download_type.length();
    return _isPrev;
}

bool DevFamilyMenu::isValid(CmdLineParams& cmd_params, filesOPtions& filterOPtions)
{
    unsigned int i = 0;
    vector<string> _availableFamilies;
    if (!cmd_params.download_dev.length())
    {
        for (i = 0; i < filterOPtions.files.size(); i++)
        {
            if (std::find(_availableFamilies.begin(), availableFamilies.end(), filterOPtions.files[i].family) ==
                  _availableFamilies.end() &&
                (filterOPtions.file_type == "all" || filterOPtions.file_type == filterOPtions.files[i].file_type))
            {
                _availableFamilies.push_back(filterOPtions.files[i].family);
            }
        }
    }
    else
    {
        return false;
    }
    if (_availableFamilies.size() == 1)
    {
        filterOPtions.family = _availableFamilies[0];
        return false;
    }
    else
    {
        return true;
    }
}

void DevFamilyMenu::setValuesDirectly(CmdLineParams& cmd_params, filesOPtions& filterOPtions)
{
    if (cmd_params.download_dev == "")
    {
        filterOPtions.family = "all";
    }
    else
    {
        filterOPtions.family = cmd_params.download_dev;
    }
}

string DevFamilyMenu::beautify(string family)
{
    return beautify_device_name(family);
}

void DevFamilyMenu::generateMenu(CmdLineParams& cmd_params, filesOPtions& filterOPtions)
{
    _menuText = "";
    if (isValid(cmd_params, filterOPtions))
    {
        _menuText = "------ Device Family Selection ------\n";
        unsigned int i = 0;

        for (i = 0; i < filterOPtions.files.size(); i++)
        {
            if (std::find(availableFamilies.begin(), availableFamilies.end(), filterOPtions.files[i].family) ==
                  availableFamilies.end() &&
                (filterOPtions.file_type == "all" || filterOPtions.file_type == filterOPtions.files[i].file_type))
            {
                availableFamilies.push_back(filterOPtions.files[i].family);
            }
        }

        for (i = 0; i < availableFamilies.size(); i++)
        {
            _menuText += "\t" + int_to_string(i + 1) + "- " + beautify(availableFamilies[i]) + "\n";
        }

        if (availableFamilies.size() > 1)
        {
            _menuText += "\t" + int_to_string(i + 1) + "- All\n";
            _all = i + 1;
            i++;
            _maxChoice = i;
        }
        if (isPrevious(cmd_params, filterOPtions))
        {
            _goBack = i + 1;
            _menuText += "\t" + int_to_string(_goBack) + "- Back\n";
            i++;
        }
        _maxChoice = i + 1;
        _exit = _maxChoice;
        _menuText += "\t" + int_to_string(_exit) + "- Exit\n";
        _menuText += "\n-?- Select an option: ";
        printText();
    }
}

bool DevFamilyMenu::parseChoice(int choice, bool& isExit, bool& isPrev, filesOPtions& filterOPtions)
{
    isPrev = false;
    isExit = false;
    if (choice > _maxChoice || choice <= 0)
    {
        fprintf(stderr, "-E- Invalid choice!\n");
        return false;
    }

    if (choice == _goBack)
    {
        isPrev = true;
        return true;
    }
    else if (choice == _exit)
    {
        isExit = true;
        return true;
    }
    else if (choice == _all)
    {
        filterOPtions.family = "all";
        return true;
    }
    else
    {
        filterOPtions.family = availableFamilies[choice - 1];
    }
    return true;
}

BaseMenu* OSMenu::getNextMenu(CmdLineParams& cmd_params, filesOPtions& filterOPtions)
{
    (void)filterOPtions;
    (void)cmd_params;
    // BaseMenu *newMenu =  new PickFilesMenu;
    return NULL;
}

BaseMenu* OSMenu::getPrevMenu(CmdLineParams& cmd_params, filesOPtions& filterOPtions)
{
    (void)filterOPtions;
    BaseMenu* newMenu = NULL;
    if (!cmd_params.download_dev.length())
    {
        newMenu = new DevFamilyMenu;
    }
    else if (!cmd_params.download_type.length())
    {
        newMenu = new FileTypeMenu;
    }
    return newMenu;
}

bool OSMenu::isPrevious(CmdLineParams& cmd_params, filesOPtions& filterOPtions)
{
    (void)filterOPtions;
    _isPrev = (!cmd_params.download_type.length() || !cmd_params.download_dev.length());
    return _isPrev;
}

bool OSMenu::isValid(CmdLineParams& cmd_params, filesOPtions& filterOPtions)
{
    (void)filterOPtions;
    return !cmd_params.download_os.length();
}

void OSMenu::setValuesDirectly(CmdLineParams& cmd_params, filesOPtions& filterOPtions)
{
    if (cmd_params.download_os == "")
    {
        filterOPtions.os = "all";
    }
    else
    {
        filterOPtions.os = cmd_params.download_os;
    }
}
string OSMenu::beautify(string os)
{
    if (os == "linux_ppc64")
    {
        os = "Linux_PPC64";
    }
    else if (os == "linux_ppc64le")
    {
        os = "Linux_PPC64le";
    }
    else if (os == "fbsd10_64")
    {
        os = "FBSD10_64";
    }
    else if (os == "fbsd10_32")
    {
        os = "FBSD10_32";
    }
    else if (os == "fbsd10_1_64")
    {
        os = "FBSD10_1_64";
    }
    else if (os == "fbsd11_64")
    {
        os = "FBSD11_64";
    }
    os[0] = toupper(os[0]);
    return os;
}
void OSMenu::generateMenu(CmdLineParams& cmd_params, filesOPtions& filterOPtions)
{
    _menuText = "";
    if (isValid(cmd_params, filterOPtions))
    {
        _menuText = "------ Operating System Selection ------\n";
        unsigned int i = 0;
        for (i = 0; i < filterOPtions.files.size(); i++)
        {
            if (filterOPtions.files[i].os != "all" &&
                std::find(availableOs.begin(), availableOs.end(), filterOPtions.files[i].os) == availableOs.end() &&
                (filterOPtions.family == "all" || filterOPtions.family == filterOPtions.files[i].family) &&
                (filterOPtions.file_type == "all" || filterOPtions.file_type == filterOPtions.files[i].file_type))
            {
                availableOs.push_back(filterOPtions.files[i].os);
            }
        }

        for (i = 0; i < availableOs.size(); i++)
        {
            _menuText += "\t" + int_to_string(i + 1) + "- " + beautify(availableOs[i]) + "\n";
        }

        if (availableOs.size() > 1)
        {
            _menuText += "\t" + int_to_string(i + 1) + "- All\n";
            _all = i + 1;
            i++;
        }

        if (isPrevious(cmd_params, filterOPtions))
        {
            _goBack = i + 1;
            _menuText += "\t" + int_to_string(_goBack) + "- Back\n";
            _maxChoice = _goBack;
            i++;
        }
        _exit = i + 1;
        _maxChoice = _exit;
        _menuText += "\t" + int_to_string(_exit) + "- Exit\n";
        _menuText += "\n-?- Select an option: ";
        printText();
    }
}

OSMenu::OSMenu() : BaseMenu()
{
    ;
    ;
}

OSMenu::~OSMenu()
{
    ;
    ;
}

bool OSMenu::parseChoice(int choice, bool& isExit, bool& isPrev, filesOPtions& filterOPtions)
{
    isPrev = false;
    isExit = false;
    if (choice > _maxChoice || choice <= 0)
    {
        fprintf(stderr, "-E- Invalid choice!\n");
        return false;
    }

    if (choice == _goBack)
    {
        isPrev = true;
        return true;
    }
    else if (choice == _exit)
    {
        isExit = true;
        return true;
    }
    else if (choice == _all)
    {
        filterOPtions.os = "all";
        return true;
    }
    else
    {
        filterOPtions.os = availableOs[choice - 1];
    }
    return true;
}
