/*Copyright (C) 2010-2020 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 "CharacterPreview.hpp"

CharacterPreview::CharacterPreview() : Drawable(), m_selected(false)
{
    
}

void CharacterPreview::draw()
{
    //Update matrix
    Drawable::pushMatrix();
    Drawable::updateMatrix();
    
    if (m_selected) m_selectedAnim.draw();
    else m_defaultAnim.draw();
    
    Drawable::popMatrix();
}

void CharacterPreview::update(float frameTime)
{
    Animation &anim = m_selected ? m_selectedAnim : m_defaultAnim;
    
    if (anim.getCurrentTime() == anim.getDuration())
            anim.goToTime(0);
        
    anim.goForward(frameTime / 1000);
}

void CharacterPreview::load(const std::string &characterName, TextureManager &manager)
{
    loadAnimations(characterName, m_defaultAnim, m_selectedAnim, manager);
}

void CharacterPreview::select()
{
    m_selected = true;
}

void CharacterPreview::unselect()
{
    m_selected = false;
}

float CharacterPreview::getBodyWidth() const
{
    const Animation &anim = m_selected ? m_selectedAnim : m_defaultAnim;
    
    Box bodyBox;
    if (!anim.getBodyBox(bodyBox))
        return 0.f;
    
    return bodyBox.width;
}

float CharacterPreview::getBodyHeight() const
{
    const Animation &anim = m_selected ? m_selectedAnim : m_defaultAnim;
    
    Box bodyBox;
    if (!anim.getBodyBox(bodyBox))
        return 0.f;
    
    return bodyBox.height;
}

void CharacterPreview::loadAnimation(Texture &texture, const TiXmlElement *xmlData, Animation &dst) const
{
    if (xmlData != NULL)
    {
        //Main params
        float duration = 0;
        xmlData->QueryFloatAttribute("duration", &duration);
        
        dst.setTexture(texture);
        dst.setDuration(duration);
        
        //Frames
        if (!xmlData->NoChildren())
        {
            const TiXmlElement *xmlFrames = xmlData->FirstChildElement();
            
            while (xmlFrames)
            {
                int srcX = 0, srcY = 0, srcWidth = 0, srcHeight = 0, time = 1;
                float bodyX = 0, bodyY = 0, bodyWidth = 0, bodyHeight = 0;
                
                xmlFrames->QueryIntAttribute("x", &srcX);
                xmlFrames->QueryIntAttribute("y", &srcY);
                
                xmlFrames->QueryIntAttribute("width", &srcWidth);
                xmlFrames->QueryIntAttribute("height", &srcHeight);
                
                xmlFrames->QueryFloatAttribute("bodyX", &bodyX);
                xmlFrames->QueryFloatAttribute("bodyY", &bodyY);
                
                xmlFrames->QueryFloatAttribute("bodyWidth", &bodyWidth);
                xmlFrames->QueryFloatAttribute("bodyHeight", &bodyHeight);
                
                xmlFrames->QueryIntAttribute("time", &time);
                
                Frame frame( Box(srcX, srcY, srcWidth, srcHeight), Box(bodyX, bodyY, bodyWidth, bodyHeight) );
                
                for (int i = 0; i < time; i++)
                    dst.addFrame(frame);
                
                xmlFrames = xmlFrames->NextSiblingElement();
            }
        }
    }
}

void CharacterPreview::loadAnimations(const std::string &player,
                                        Animation &dstDefault,
                                        Animation &dstSelected,
                                        TextureManager &manager) const
{
    //Locate absolute path to xml data
    std::string xmlPath = BuildValues::data( "gfx/characters/" + player + "/data.xml" );
    std::string animationsRelPath = "gfx/characters/" + player + "/";
    
    //TinyXML initialization
    TiXmlDocument xmlFile;
    if (!xmlFile.LoadFile(xmlPath.c_str()))
        return;
    
    TiXmlHandle hdl(&xmlFile);
    hdl = hdl.FirstChildElement().FirstChildElement();
    
    //Default state -> default animation
    TiXmlElement *xmlAnimationDefault = hdl.Child(0).FirstChildElement("animation").ToElement();
    Texture *textureDefault = manager.getTexture( animationsRelPath + xmlAnimationDefault->Attribute("path") + ".png" );
    
    //Default punch animation -> selected animation
    TiXmlElement *xmlAnimationSelected = hdl.Child(2).FirstChildElement("animation").ToElement();
    Texture *textureSelected = manager.getTexture( animationsRelPath + xmlAnimationSelected->Attribute("path") + ".png" );

    loadAnimation((*textureDefault), xmlAnimationDefault, dstDefault);
    loadAnimation((*textureSelected), xmlAnimationSelected, dstSelected);
}
