/*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())
{
    //Get view size
    sf::Vector2f viewSize = m_renderWindow->GetDefaultView().GetSize();
    
    ImageEngine *imageManager = ImageEngine::getInstance();
    
    //Game view
    m_gameView = sf::View(sf::FloatRect(0, 0, viewSize.x, viewSize.y));
    
    //Game render
    m_background.SetImage(*imageManager->getImage("fond.png"));
    
    m_gameRenderEngine.addObject(&m_background);
    
    //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));
    
    m_interfaceRenderEngine.addObject(&m_interface);
    m_interfaceRenderEngine.addObject(&m_fpsText);
    
    //Physics
    m_physicsEngine.setPhysicsWorld(sf::FloatRect(0, -250, viewSize.x, viewSize.y + 250));
    m_physicsEngine.setGroundPosition(550);
    m_physicsEngine.setGravityForce(10);
}

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

void Fight::addPlayer(const std::string &playerName)
{
    Player *newPlayer = loadPlayer(playerName, "data/conf/characters.xml");
    
    newPlayer->setPhysicsEngine(&m_physicsEngine);
    newPlayer->setYPosition(550);
    newPlayer->setXPosition(m_playersList.size() * 150 + 150);
    
    //Add to engines, ...
    newPlayer->startRendering(m_gameRenderEngine);
    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;
            }
            
            if (event.Key.Code == sf::Key::F1)
            {
                sf::Image screen;
                screen.CopyScreen(*m_renderWindow, sf::IntRect(0, 0, 1000, 600));
                screen.SaveToFile("screenshot.png");
            }
        }
        
        //Update physics
        m_physicsEngine.update();
        
        //Update players
        for (int i=0; i < m_playersList.size(); i++)
        {
            m_playersList[i]->update(m_renderWindow->GetInput());
            
            if (m_playersList[i]->healthAltered())
                m_interface.updateHealth(m_playersList[i]);
        }
        
        fps = 1.f / m_renderWindow->GetFrameTime();
        
        std::ostringstream convertFramerate;
        convertFramerate << fps;
        m_fpsText.SetString(convertFramerate.str());
        
        m_renderWindow->Clear();
        
        //Graphic part
        m_renderWindow->SetView(m_gameView);
        m_gameRenderEngine.draw(*m_renderWindow);
        
        //Interface part
        m_renderWindow->SetView(m_renderWindow->GetDefaultView());
        m_interfaceRenderEngine.draw(*m_renderWindow);
        
        m_renderWindow->Display();
    }
}

Player *Fight::loadPlayer(const std::string &playerName, const std::string &xmlPath)
{
    TiXmlDocument xmlFile;
    xmlFile.LoadFile(xmlPath.c_str());
    
    TiXmlHandle hdl(&xmlFile);
    TiXmlElement *xmlElement = hdl.FirstChildElement().FirstChildElement().Element();
    
    int i = 0;
    while (xmlElement)
    {
        std::string itemName = xmlElement->Attribute("name");
        if (itemName == playerName)
        {
            //Get informations
            int strenght;
            int speed;
            
            xmlElement->QueryIntAttribute("strenght", &strenght);
            xmlElement->QueryIntAttribute("speed", &speed);
            
            //Create player
            Player *player = new Player(playerName, 100, 100, strenght, speed);
            
            return player;
        }
        
        xmlElement = xmlElement->NextSiblingElement();
        i++;
    }
}

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