/*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 "TextInputEnabler.hpp"
#include "GUI/Widget/TextInput.hpp"
#include "Graphics/Viewport.hpp"
#include "Structs/Vector.hpp"

#include <SDL2/SDL.h>
#include <cmath>
#include <limits>

namespace
{
    /// Rounds \p value to a positive integer
    int roundint(float value)
    {
        if (value < 0.f)
            return 0;

        const long rounded = std::lround(value);
        return (rounded <= std::numeric_limits<int>::max()) ?
            static_cast<int>(rounded) : std::numeric_limits<int>::max();
    }
}

TextInputEnabler::TextInputEnabler(const std::vector<TextInput*> &inputs,
                                   const Viewport &viewport) :
m_textInputs(inputs), m_viewport(viewport), m_currentInput(nullptr)
{

}

void TextInputEnabler::mouseRelease(const Vector &mouseCoords)
{
    //Check if a TextInput is focused
    const TextInput *focused = nullptr;
    for (TextInput *textInput : m_textInputs)
    {
        if (textInput->mouseRelease(mouseCoords))
            focused = textInput;
    }

    //Start or stop system text input
    if (m_currentInput == nullptr && focused != nullptr)
        SDL_StartTextInput();
    else if (m_currentInput != nullptr && focused == nullptr)
        SDL_StopTextInput();

    //Position the system text input rectangle
    if (focused != nullptr)
    {
        const Viewport toWindow(m_viewport.getTarget(), m_viewport.getSource());

        const Vector topLeft = toWindow.project(
            Vector(focused->getXPosition(),
                   focused->getYPosition()));

        const Vector bottomRight = toWindow.project(
            Vector(focused->getXPosition() + focused->getWidth(),
                   focused->getYPosition() + focused->getHeight()));

        SDL_Rect inputRect{roundint(topLeft.x),
                           roundint(topLeft.y),
                           roundint(bottomRight.x - topLeft.x),
                           roundint(bottomRight.y - topLeft.y)};

        SDL_SetTextInputRect(&inputRect);
    }

    m_currentInput = focused;
}
