/***************************************************************************
 *   Copyright (C) 2007 by Sébastien Laoût                                 *
 *   slaout@linux62.org                                                    *
 *                                                                         *
 *   This program 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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "showanimator.h"

const int PERIOD = 1000 / 25; // 25 frames per second (40 milliseconds)

ShowAnimator::ShowAnimator(int duration)
 : QObject(), m_duration(duration), m_begin(0), m_end(0), m_state(NotRunning), m_value(0)
{
	connect( &m_timer, SIGNAL(timeout()), this, SLOT(timeout()) );
}

ShowAnimator::~ShowAnimator()
{
}

void ShowAnimator::setRange(int begin, int end)
{
	m_begin = begin;
	m_end   = end;
	m_value = QMAX(m_begin, QMIN(m_value, m_end));
}

void ShowAnimator::toBegin()
{
	if (m_value > m_begin) {
		m_state = MoveBackward;
		if (!m_timer.isActive())
			m_timer.start(PERIOD);
		timeout();
	}
}

void ShowAnimator::toEnd()
{
	if (m_value < m_end) {
		m_state = MoveForward;
		if (!m_timer.isActive())
			m_timer.start(PERIOD);
		timeout();
	}
}

int ShowAnimator::value()
{
	return m_value;
}

ShowAnimator::State ShowAnimator::state()
{
	return m_state;
}

// TODO: setToBegin setToEnd progressToBegin progressToEnd !!!!

void ShowAnimator::setValueAndState(int value, ShowAnimator::State state)
{
	m_value = QMAX(m_begin, QMIN(value, m_end));
	if ((state == MoveForward && m_value != m_end) || (state == MoveBackward && m_value != m_begin)) {
		m_state = state;
		if (!m_timer.isActive())
			m_timer.start(PERIOD);
		timeout();
	} else {
		m_state == NotRunning;
		m_timer.stop();
	}
}

bool ShowAnimator::isInIntermediateState()
{
	return (m_value != m_begin && m_value != m_end);
}

bool ShowAnimator::atBegin()
{
	return (m_value == m_begin);
}

bool ShowAnimator::atEnd()
{
	return (m_value == m_end);
}

void ShowAnimator::timeout()
{
	emit beforeNewValue();

	int delta = (m_end - m_begin) * PERIOD / m_duration;
	if (m_state == MoveBackward)
		delta = -delta;

	m_value += delta;
	m_value = QMAX(m_begin, QMIN(m_value, m_end));

	emit newValue(m_value);

	if (m_value == m_begin || m_value == m_end)
		m_timer.stop();
}

#include "showanimator.moc"
