/*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 "FightInterface.hpp"

#include "Tools/ScaledPixel.hpp"
#include <cstddef>

FightInterface::FightInterface(Font &namesFont, Font &weaponsFont,
                               Font &barsFont, float viewWidth) : Drawable(),
m_namesFont(&namesFont), m_weaponsFont(&weaponsFont), m_barsFont(&barsFont),
m_iconsScale(1.f), m_viewWidth(viewWidth)
{

}

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

    for (PlayerInfo &playerInfo : m_playerInfos)
        playerInfo.draw();

    Drawable::popMatrix();
}

void FightInterface::update()
{
    for (PlayerInfo &playerInfo : m_playerInfos)
        playerInfo.update();
}

void FightInterface::setPlayers(const std::vector<const Player*> &players,
                                TextureManager &textureManager)
{
    m_playerInfos.clear();
    m_playerInfos.reserve(players.size());

    for (const Player *player : players)
    {
        if (player != nullptr)
        {
            m_playerInfos.emplace_back((*player), textureManager,
                (*m_namesFont), (*m_weaponsFont), (*m_barsFont), m_viewWidth);
            m_playerInfos.back().setIconScale(m_iconsScale);
        }
    }

    updatePositions();
}

void FightInterface::replaceNames(
    const std::vector<Utf8::utf8_string> &playerNames)
{
    if (playerNames.size() == m_playerInfos.size())
    {
        for (std::size_t i = 0; i < m_playerInfos.size(); i++)
            m_playerInfos[i].replaceName(playerNames[i]);
    }
}

void FightInterface::updatePlayerResults(std::uint8_t roundsToWin,
    const std::vector<std::uint8_t> &winsPerPlayer)
{
    if (winsPerPlayer.size() == m_playerInfos.size())
    {
        for (std::size_t i = 0; i < m_playerInfos.size(); i++)
        {
            //Show the result disks only for multiple-round games
            m_playerInfos[i].setResults(roundsToWin > 1 ? roundsToWin : 0,
                                        winsPerPlayer[i]);
        }
    }
}

void FightInterface::resetPlayerResults()
{
    for (PlayerInfo &playerInfo : m_playerInfos)
        playerInfo.setResults(0, 0);
}

void FightInterface::updatePositions()
{
    //Compute the space between each PlayerInfo
    float space = ScaledPixel{m_viewWidth}(50.f);
    if (m_viewWidth > 0.f)
    {
        //Compute content width
        float contentWidth = 0.f;
        for (const PlayerInfo &playerInfo : m_playerInfos)
            contentWidth += playerInfo.getWidth();

        //Reduce size of items if they overflow
        for (unsigned int resizeAttempts = 0;
             resizeAttempts < 2;
             resizeAttempts++)
        {
            //Break if size is sufficient
            if (contentWidth <= m_viewWidth)
                break;

            //Resize the player info items
            m_iconsScale *= .75f;
            for (PlayerInfo &playerInfo : m_playerInfos)
                playerInfo.setIconScale(m_iconsScale);

            //Recompute contentWidth
            contentWidth = 0.f;
            for (const PlayerInfo &playerInfo : m_playerInfos)
                contentWidth += playerInfo.getWidth();
        }

        space = (m_viewWidth - contentWidth) /
            static_cast<float>(m_playerInfos.size() + 1);
    }

    //Position each PlayerInfo
    float currentPos = space;
    for (PlayerInfo &playerInfo : m_playerInfos)
    {
        playerInfo.setXPosition(currentPos);
        currentPos += playerInfo.getWidth() + space;
    }
}
