/*
 * Copyright (C) 2009 - 2010 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
 * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
 *
 * 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 Affero General Public License
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 *
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */

/* $Id$ */

#include "Timer.h"
#include "Logger/LoggerMacroses.h"


using namespace NS_DM_Client;
using namespace NS_DM_Client::NS_Common;

const char* const c_LogName = "Timer";

Timer::Timer() :
	m_isRunning(false), m_terminate(false), m_pulsesCount(0), m_pulsesPerInterval(0), m_ticksCount(0), m_ticksToCount(0), m_timerInterval(0), 
	m_callback(NULL)
{
}


Timer::~Timer()
{
	Stop();
}


bool Timer::IsRunning()
{
	return m_isRunning;
}


void Timer::SetCallback(Callback *c)
{
	m_callback = c;
}


void Timer::SetInterval(uint seconds)
{
	m_timerInterval = seconds;
	m_pulsesPerInterval = m_timerInterval;
}


void Timer::SetTicksCount(int count)
{
	m_ticksCount = count;
}


void Timer::Start()
{
	if (m_isRunning) return;

	if (m_timerInterval)
	{
		m_ticksToCount = m_ticksCount;
		if (m_ticksCount == -1 || m_ticksCount > 0)
			startTimer();
	}
}


void Timer::Stop()
{
	if (!m_isRunning) return;

	softTerminate();
	wait();

	m_isRunning = false;
	terminate = false;
}


void Timer::run()
{
	m_isRunning = true;
	
	// tick once
	if (m_ticksToCount)
		tick();
	
	if (m_ticksToCount)
		while (!terminate)
		{
			sleep(1000);
			if (terminate) break;
			if (++m_pulsesCount > m_pulsesPerInterval)
			{
				m_pulsesCount = 0;
				tick();
			}
		}

	terminate = false;
	m_isRunning = false;
}


void Timer::notifyCallback()
{
	if (m_callback) m_callback->Call();
}


void Timer::startTimer()
{
	if (m_isRunning) return;
	terminate = false;
	start();
}


void Timer::tick()
{
	if (m_ticksToCount == 0)
	{
		terminate = true;
	}
	else
	{
		if (m_ticksToCount > 0)
			--m_ticksToCount;
		notifyCallback();				
	}
}
