/*Copyright (C) 2010-2023 Duncan Deveaux

This file is part of Hikou no mizu.

Hikou no mizu is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Hikou no mizu is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Hikou no mizu.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "OptionsTab.hpp"
#include "Configuration/Configuration.hpp"
#include "Engines/Resources/FontManager.hpp"
#include "Engines/Resources/TextureManager.hpp"
#include "Engines/Sound/SoundEngine.hpp"
#include "Structs/JoystickData.hpp"

#include "Tools/ScaledPixel.hpp"
#include "Tools/I18n.hpp" ///< _ macro for i18n

OptionsTab::OptionsTab(Configuration &configuration, FontManager &fontManager,
                       TextureManager &textureManager, SoundEngine &soundEngine,
                       const Display::DisplayMode &activeMode,
                       float viewWidth) :
Tab(ScaledPixel{viewWidth}(1120.f),
    ScaledPixel{viewWidth}(430.f),
    Color(85, 126, 182)),
m_general(configuration, fontManager, textureManager,
          soundEngine, activeMode, viewWidth),
m_controls(configuration, fontManager, textureManager, soundEngine, viewWidth),
m_currentCategory(OptionsTab::Category::General)
{
    const ScaledPixel sp(viewWidth);

    m_general.setYPosition(sp(50.f));
    m_controls.setYPosition(sp(50.f));

    //Header buttons
    SkinBox button_skin(sp(240.f), sp(50.f));
    button_skin.inactive = Sprite(textureManager.getTexture("gfx/ui/ui.png"),
        Box(0.f, 0.f, 240.f / 512.f, 60.f / 512.f));
    button_skin.focused = Sprite(textureManager.getTexture("gfx/ui/ui.png"),
        Box(0.f, 64.f / 512.f, 240.f / 512.f, 60.f / 512.f));
    button_skin.selected = Sprite(textureManager.getTexture("gfx/ui/ui.png"),
        Box(0.f, 64.f / 512.f, 240.f / 512.f, 60.f / 512.f));

    SkinSound button_sounds(soundEngine, "audio/ui/menuFocus.ogg",
                            "audio/ui/menuClick.ogg");

    Font &font = fontManager.getDisplay(sp(24));

    m_generalTab = TextButton(_(OptionsGeneral), button_skin, button_sounds);
    m_generalTab.setTextFont(font);
    m_generalTab.setTextColor(Color(255, 255, 255));
    m_generalTab.select(true);

    m_controlsTab = TextButton(_(OptionsControls), button_skin, button_sounds);
    m_controlsTab.setTextFont(font);
    m_controlsTab.setTextColor(Color(255, 255, 255));
    m_controlsTab.setPosition(m_generalTab.getXPosition() +
                              m_generalTab.getWidth(), 0.f);
}

void OptionsTab::draw()
{
    //Update matrix
    Drawable::pushMatrix();
    Drawable::updateMatrix();

    m_background.draw();

    m_generalTab.draw();
    m_controlsTab.draw();

    if (m_currentCategory == OptionsTab::Category::General)
        m_general.draw();
    else if (m_currentCategory == OptionsTab::Category::Controls)
        m_controls.draw();

    Drawable::popMatrix();
}

bool OptionsTab::mouseRelease(const Vector &mouseCoords)
{
    Vector localMouse = Widget::localCoords(mouseCoords);

    //Only forward the release to the tabs if it is not relevant to the options
    if ((m_currentCategory != OptionsTab::Category::General ||
            !m_general.mouseRelease(localMouse)) &&
        (m_currentCategory != OptionsTab::Category::Controls ||
            !m_controls.mouseRelease(localMouse)))
    {
        if (m_generalTab.mouseRelease(localMouse))
        {
            m_currentCategory = OptionsTab::Category::General;
            m_generalTab.select(true);
            m_controlsTab.select(false);
        }
        else if (m_controlsTab.mouseRelease(localMouse))
        {
            m_currentCategory = OptionsTab::Category::Controls;
            m_controlsTab.select(true);
            m_generalTab.select(false);
        }
    }

    return Widget::contains(localMouse);
}

bool OptionsTab::mouseClick(const Vector &mouseCoords)
{
    Vector localMouse = Widget::localCoords(mouseCoords);

    if (m_currentCategory == OptionsTab::Category::General)
        m_general.mouseClick(localMouse);
    else if (m_currentCategory == OptionsTab::Category::Controls)
        m_controls.mouseClick(localMouse);

    return Widget::contains(localMouse);
}

bool OptionsTab::mouseMove(const Vector &mouseCoords)
{
    Vector localMouse = Widget::localCoords(mouseCoords);

    //Only forward the move to the tabs if it is not relevant to the options
    if ((m_currentCategory != OptionsTab::Category::General ||
            !m_general.mouseMove(localMouse)) &&
        (m_currentCategory != OptionsTab::Category::Controls ||
            !m_controls.mouseMove(localMouse)))
    {
        m_generalTab.mouseMove(localMouse);
        m_controlsTab.mouseMove(localMouse);
    }
    else
    {
        m_generalTab.setFocus(false);
        m_controlsTab.setFocus(false);
    }

    return Widget::contains(localMouse);
}

void OptionsTab::keyEvent(const SDL_Event &event)
{
    if (m_currentCategory == OptionsTab::Category::Controls)
        m_controls.keyEvent(event);
}

void OptionsTab::setDisplaySizes(const std::vector<std::pair<int, int>> &sizes)
{
    m_general.setDisplaySizes(sizes);
}

void OptionsTab::addJoystickBinder(const JoystickData &joystickData)
{
    m_controls.addJoystickBinder(joystickData);
}

void OptionsTab::removeJoystickBinder(int joystickID)
{
    m_controls.removeJoystickBinder(joystickID);
}

bool OptionsTab::displayModeApplied() const
{
    return m_general.displayModeApplied();
}

bool OptionsTab::refreshRateUpdated() const
{
    return m_general.refreshRateUpdated();
}

bool OptionsTab::volumeUpdated() const
{
    return m_general.volumeUpdated();
}

bool OptionsTab::localeUpdated() const
{
    return m_general.localeUpdated();
}
