/*Copyright (C) 2010 Deveaux Duncan

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 "Fight.hpp"
#include "Engines/GameEngine.hpp"

Fight::Fight(GameEngine *gameEngine) :
m_gameEngine(gameEngine), m_renderWindow(gameEngine->getRenderWindow()),
m_configuration(gameEngine->getConfiguration())
{
    //Get view size
    sf::Vector2f viewSize = m_renderWindow->GetDefaultView().GetSize();
    
    //Game view
    m_gameView = sf::View(sf::FloatRect(0, 0, viewSize.x, viewSize.y));
    
    //Interface render
    m_interface.SetPosition(100, 20);
    
    m_fpsText.SetCharacterSize(45);
    m_fpsText.SetX(viewSize.x - 100);
    m_fpsText.SetColor(sf::Color(0, 0, 0, 255));
    
    //Physics
    m_physicsEngine.setPhysicsWorld(sf::FloatRect(0, -250, viewSize.x, viewSize.y + 250));
    
    //Sound
    m_soundEngine.setVolume(m_configuration->getSoundVolume());
}

Fight::~Fight()
{
    deletePlayers();
}

void Fight::setArena(const std::string &arenaName)
{
    //Init arena
    m_arena = Arena::loadFromXML(arenaName, "data/conf/arenas.xml");
    m_arena.applyToPhysics(m_physicsEngine);
    m_arena.subscribeObjects(m_physicsEngine);
    
    //Players repositioning
    for (unsigned int i = 0; i < m_playersList.size(); i++)
    {
        sf::Vector2f playerSpawn;
        if (m_arena.getPlayerSpawn(i, playerSpawn))
        {
            m_playersList[i]->setXPosition(playerSpawn.x);
            m_playersList[i]->setYPosition(playerSpawn.y);
        }
    }
}

void Fight::addPlayer(const std::string &playerName, int playerType)
{
    Player *newPlayer;
    
    if (playerType == 0) //Human
    {
        //Create player
        Human *newHuman = Human::loadFromXML(playerName, "data/conf/characters.xml");
        
        PlayerKeys keys;
        if (m_configuration->getPlayerKeys(m_playersList.size(), keys))
            newHuman->setKeys(keys);
        
        newPlayer = newHuman;
    }
    else if (playerType == 1) //AI
    {
        //Create player
        AI *newAI = AI::loadFromXML(playerName, "data/conf/characters.xml");
        
        newPlayer = newAI;
    }
    
    newPlayer->setPhysicsEngine(m_physicsEngine);
    newPlayer->setSoundEngine(m_soundEngine);
    
    newPlayer->loadGraphics();
    
    //Default position
    newPlayer->setXPosition(m_playersList.size() * 450 + 550);
    
    //Add to engines, ...
    m_physicsEngine.addObject(newPlayer);
    m_interface.addPlayer(newPlayer);
    
    m_playersList.push_back(newPlayer);
}

void Fight::clearPlayers()
{
    deletePlayers();
    m_playersList.clear();
}

void Fight::run()
{
    //Run
    int fps;
    while (1)
    {
        sf::Event event;
        while (m_renderWindow->PollEvent(event))
        {
            if (event.Type == sf::Event::Closed)
            {
                m_gameEngine->exit();
                return;
            }
        }
        
        //Update physics
        m_physicsEngine.update();
        
        //Update sounds
        m_soundEngine.update();
        
        //Update players
        updatePlayers();
        
        fps = 1000 / m_renderWindow->GetFrameTime();
        
        std::ostringstream convertFramerate;
        convertFramerate << fps;
        m_fpsText.SetString(convertFramerate.str());
        
        //Display
            //Clear
        m_renderWindow->Clear();
        
            //Graphic part
        m_renderWindow->SetView(m_gameView);
        
        m_arena.render(*m_renderWindow);
        renderPlayers(*m_renderWindow);
        
            //Interface part
        m_renderWindow->SetView(m_renderWindow->GetDefaultView());
        
        m_renderWindow->Draw(m_interface);
        m_renderWindow->Draw(m_fpsText);
        
            //Render
        m_renderWindow->Display();
    }
}

//Private methods
void Fight::updatePlayers()
{
    for (unsigned int i = 0; i < m_playersList.size(); i++)
    {
        m_playersList[i]->act();
        m_playersList[i]->update();
        
        m_interface.updateHealth(m_playersList[i]);
    }
}

void Fight::renderPlayers(sf::RenderWindow &renderWindow)
{
    for (unsigned int i = 0; i < m_playersList.size(); i++)
    {
        m_playersList[i]->render(renderWindow);
    }
}

void Fight::deletePlayers()
{
    for (unsigned int i = 0; i < m_playersList.size(); i++)
    {
        //Remove from engines, ...
        m_physicsEngine.removeObject(m_playersList[i]);
        m_interface.removePlayer(m_playersList[i]);
        
        //Delete
        delete m_playersList[i];
    }
}