//------------------------------------------------------------------------------
//	Copyright (C) 2008, 2009 Humboldt-Universitaet zu Berlin
//
//	This library is free software; you can redistribute it and/or
//	modify it under the terms of the GNU Lesser General Public
//	License as published by the Free Software Foundation; either
//	version 2.1 of the License, or (at your option) any later version.
//
//	This library 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
//	Lesser General Public License for more details.
//
//	You should have received a copy of the GNU Lesser General Public
//	License along with this library; if not, write to the Free Software
//	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//------------------------------------------------------------------------------

/**
 * @file TimeFormat.h
 * @author Ronald Kluth
 * @date created at 2008/03/14
 * @brief Declaration of odemx::data::output::TimeFormat
 * @sa TimeFormat.cpp
 * @since 2.1
 */

#ifndef ODEMX_DATA_OUTPUT_TIMEFORMAT_INCLUDED
#define ODEMX_DATA_OUTPUT_TIMEFORMAT_INCLUDED

#include <odemx/base/SimTime.h>
#include <odemx/data/output/TimeBase.h>
#include <odemx/data/output/TimeUnit.h>

#include <string>

namespace odemx {
namespace data {
namespace output {

/**
 * @brief Abstract base class for formatted simulation time output
 * @ingroup data
 * @author Ronald Kluth
 * @since 2.1
 * @see odemx::data::output::GermanTime odemx::data::output::Iso8601Time
 *
 * This abstract base class provides an implementation for time computations.
 * In order to transform an abstract SimTime value into a concrete time
 * value, a starting point and a time unit are required. Both are provided
 * in the form of a TimeBase object.
 *
 * This class computes year, month, day, hour minutes, and seconds from SimTime
 * values and stores them in protected members so that they can be used by
 * subclasses to produce a formatted time string. The interface for converting
 * SimTime to string is provided by the member function @c timeToString.
 */
class TimeFormat
{
public:
	/// Default construction for uninitialized TimeFormat objects
	TimeFormat();
	/// Construction with a given time base and unit
	TimeFormat( const TimeBase& timeBase );
	/// Destruction
	virtual ~TimeFormat();

	/// Set the time base (date, time of day, unit) for the time computation
	void setTimeBase( unsigned short year, unsigned short month,
			unsigned short day, base::SimTime dayTimeOffset, TimeUnit::Type unit );
	/// Set the time base by providing a TimeBase object
	void setTimeBase( const TimeBase& timeBase );
	/// Get a reference to the format's time base
	const TimeBase& getTimeBase() const;

	/**
	 * @brief Transforms SimTime into a formatted string for logging output
	 * @param time The SimTime value to be transformed
	 * @return A string representation of the given SimTime value
	 *
	 *  This function can be used by all output components to transform
	 *  SimTime values into actual dates and points in time. To achieve this,
	 *  the function uses the virtual function @c computeTimeValues to
	 *  determine the date and time according to the time base and unit.
	 *
	 * 	Finally, this function calls the pure virtual function makeString(),
	 *  which must be defined by all subclasses in order to produce the
	 *  formatted string from the internal numeric time representation.
	 */
	const std::string timeToString( base::SimTime time );

protected:

	/// Computes a real date and clock time from SimTime, stores values in member data
	virtual void computeTimeValues( base::SimTime time );

	/**
	 * @brief Assembles the previously computed values as formatted time string
	 *
	 * All subclasses must provide an implementation of this function so that
	 * @c timeToString can be called for the time transformation.
	 */
	virtual const std::string makeString() const = 0;

	/// The starting point of the simulation time, represents SimTime 0
	TimeBase base;

	// values to be set by computeTimeValues()
	base::SimTime simTime; ///< The SimTime to be converted considering base
	unsigned short year; ///< Computed year
	unsigned short month; ///< Computed month
	unsigned short day; ///< Computed day
	unsigned short hour; ///< Computed hour
	unsigned short min; ///< Computed minutes
	double sec; ///< Computed seconds and milliseconds

	/// Heper function to get the days of a month, with regard to the year
	static unsigned short daysOfMonth( unsigned short month, unsigned short year );
private:
	/// Reset member data, used for initialization and reset
	void resetTimeValues();
};

} } } // namespace odemx::data::output

#endif /* ODEMX_DATA_OUTPUT_TIMEFORMAT_INCLUDED */
