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

Animation::Animation() : m_frameIx(0), m_duration(0), m_time(0), m_reversed(false)
{
    
}

void Animation::draw()
{
    //Update matrix
    Drawable::pushMatrix();
    Drawable::updateMatrix();
    
    if (m_texture != NULL && m_frameIx <= m_framesList.size() - 1)
    {
        Box &frame = m_framesList[m_frameIx];
        
        float x1 = (m_texture->getWidth() > 0) ? frame.left / m_texture->getWidth() : 0;
        float y1 = (m_texture->getHeight() > 0) ? frame.top / m_texture->getHeight() : 0;
        
        float x2 = (m_texture->getWidth() > 0) ? (frame.left + frame.width) / m_texture->getWidth() : 1;
        float y2 = (m_texture->getHeight() > 0) ? (frame.top + frame.height) / m_texture->getHeight() : 1;
        
        if (!m_reversed) m_texture->draw(x1, y1, x2, y2);
        else m_texture->draw(x2, y1, x1, y2);
    }
    
    Drawable::popMatrix();
}

void Animation::addFrame(const Box &frameData, int frameIx)
{
    if (frameIx == -1)
        m_framesList.push_back(frameData);
    
    else if (frameIx >= 0 && frameIx <= static_cast<int>(m_framesList.size()) - 1)
        m_framesList[frameIx] = frameData;
}

void Animation::removeFrame(int frameIx)
{
    if (frameIx >= 0 && frameIx <= static_cast<int>(m_framesList.size()) - 1)
        m_framesList.erase(m_framesList.begin() + frameIx);
}

void Animation::goToTime(float time)
{
    if (m_duration > 0 && (time >= 0 && time <= m_duration))
    {
        m_time = time;
        
        m_frameIx = m_framesList.size() * (m_time / m_duration);
        if (m_time == m_duration) m_frameIx = m_framesList.size() - 1;
    }
}

void Animation::goForward(float distance)
{
    float bufferTime = m_time + distance;
    
    if (bufferTime > m_duration)
        bufferTime = m_duration;
    
    goToTime(bufferTime);
}

void Animation::goBack(float distance)
{
    float bufferTime = m_time - distance;
    
    if (bufferTime < 0)
        bufferTime = 0;
    
    goToTime(bufferTime);
}

//Get and set methods
void Animation::setTexture(Texture &texture)
{
    m_texture = &texture;
}

const Texture &Animation::getTexture() const
{
    return *m_texture;
}

void Animation::setDuration(float duration)
{
    if (duration > 0)
        m_duration = duration;
}

float Animation::getDuration() const
{
    return m_duration;
}

float Animation::getCurrentTime() const
{
    return m_time;
}

void Animation::setReverse(bool reverse)
{
    m_reversed = reverse;
}

bool Animation::isReversed() const
{
    return m_reversed;
}

float Animation::getWidth() const
{
    if (m_texture != NULL && m_frameIx <= m_framesList.size() - 1)
    {
        float left = m_framesList[m_frameIx].left;
        float right = m_framesList[m_frameIx].left + m_framesList[m_frameIx].width;
        
        return right - left;
    }
    
    return 0;
}

float Animation::getHeight() const
{
    if (m_texture != NULL && m_frameIx <= m_framesList.size() - 1)
    {
        float top = m_framesList[m_frameIx].top;
        float bottom = m_framesList[m_frameIx].top + m_framesList[m_frameIx].height;
        
        return bottom - top;
    }
    
    return 0;
}
