/******************************** LICENSE ********************************

 Copyright 2007 European Centre for Medium-Range Weather Forecasts (ECMWF)

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at 

    http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.

 ******************************** LICENSE ********************************/

/*! \file DateAxisMethod.cc
    \brief Implementation of the Template class DateAxisMethod.
    
    Magics Team - ECMWF 2005
    
    Started: Mon 10-Oct-2005
    
    Changes:
    
*/


#include "DateAxisMethod.h"
#include "DateAxis.h"

using namespace magics;

DateAxisMethod::DateAxisMethod() 
{
}


DateAxisMethod::~DateAxisMethod() 
{
}


/*!
 Class information are given to the output-stream.
*/		
void DateAxisMethod::print(ostream& out)  const
{
	out << "DateAxisMethod[";
	out << "]";
}

void DateHourAxisMethod::prepare(DateAxis&, const DateTime& ref, const DateTime& left, const DateTime& right, AxisItems& list)
{
	DateTime label;
	DateTime tick;

	const DateTime& min = ( left < right ) ? left : right;
	const DateTime& max = ( left < right ) ? right : left;
	
	
	int frequency;

	if ( interval_ == INT_MAX ) {
	    if ( max-min  < 24*3600 ) {
		frequency = 1; // every hour
	    }
	    else if ( max-min < 2*24*3600 ) {
		frequency = 2; // every other hour!
	    }
	    else {
		frequency = 3;
	    }  
	}
	else {
		frequency = (int) interval_;
	}
	if ( frequency == 0)
		frequency = 1;
	for ( Date date = min.date(); date <= max.date(); ++date)
	{
		for (int i = 0; i < 24; i+=frequency )
		{
			tick = DateTime(date, Time(i, 0, 0));				
			list.push_back(new AxisDateItem(tick -ref, tick));
			list.push_back(new AxisTickItem(tick -ref));
		}
	}
}

void DateDayAxisMethod::prepare(DateAxis&, const DateTime& ref, const DateTime& left, const DateTime& right, AxisItems& list)
{
	DateTime label;
	DateTime tick;

	const DateTime& min = ( left < right ) ? left : right;
	const DateTime& max = ( left < right ) ? right : left;
	long position  =  ( max-min  < 20*24*3600 ) ? 12 : 0;

	int frequency;

	if ( interval_ == INT_MAX ) {
	    if ( max-min  < 20*24*3600 ) {
	    	frequency = 1;
	    }
	    else if ( max-min  < 120*24*3600 ) {
	    	frequency = 2;
	    }
	    else {
	    	frequency = 3;
	    }  
	}
	else {
		frequency = (int) interval_;
	}
	if ( frequency == 0)
		frequency = 1;
	int count = 0;

	for ( Date date = min.date(); date <= max.date(); ++date)
	{
		if ((count++ % frequency)!=0) continue; 
		label = DateTime(date, Time(position, 0, 0));
		list.push_back(new AxisDateItem(label -ref, label));
		tick = DateTime(date, Time(0, 0, 0));	
		
		list.push_back(new AxisTickItem(tick -ref));
		for (int i = 6; i < 24; i+=6 )
		{
			tick = DateTime(date, Time(i, 0, 0));
			//MagLog::dev()<< tick << "---" << tick-ref << endl;
			list.push_back(new AxisMinorTickItem(tick -ref));
		}
	}
	// we create 
}

void DateMonthAxisMethod::prepare(DateAxis& axis, const DateTime& ref, const DateTime& left, const DateTime& right, AxisItems& list)
{
	// reset the default for labelling! 
	
	axis.setHours(new NoHourDateAxis());
	axis.setDays(new NoDayDateAxis());
	
	DateTime label;
	DateTime tick;

	const DateTime& min = ( left < right ) ? left : right;
	const DateTime& max = ( left < right ) ? right : left;
	long position  =  0;

	int frequency;

	if ( interval_ == INT_MAX ) {
	    if ( max-min  < 20*24*3600*30 ) {
	    	frequency = 1;
	    }
	    else if ( max-min  < 120*24*3600*30 ) {
	    	frequency = 2;
	    }
	    else {
	    	frequency = 3;
	    }  
	}
	else {
		frequency = (int) interval_;
	}
	if ( frequency == 0)
		frequency = 1;
	int count = 0;


	Date date = min.date();
	while ( date <= max.date() ) {
		int year  = date.year();
		int month  = date.month();
	
		if ((count++ % frequency)==0) {
			label = DateTime(date, Time(position, 0, 0));
			list.push_back(new AxisDateItem(label -ref, label));
			tick = DateTime(date, Time(0, 0, 0));

			list.push_back(new AxisTickItem(tick -ref));
			MagLog::dev()<< " tick at ---" << tick << endl;
		}
		month++;
		if ( month == 13 ) {
			year++;
			month=1;
		} 

		date = Date(year, month, 1);
	}
}

void DateYearAxisMethod::prepare(DateAxis& axis, const DateTime&ref, const DateTime& left, const DateTime& right, AxisItems& list)
{
	axis.setHours(new NoHourDateAxis());
	axis.setDays(new NoDayDateAxis());
	axis.setMonths(new NoMonthDateAxis());
	DateTime label;
	DateTime tick;

	const DateTime& min = ( left < right ) ? left : right;
	const DateTime& max = ( left < right ) ? right : left;
	long position  =  0;

	int frequency;
	const long long seconds_a_year=24*3600*365;
	const long decade=120;

	if ( interval_ == INT_MAX ) {
	    if ( max-min < 20*seconds_a_year ) {
		frequency = 1;
	    }
	    else if ( max-min < decade*24*3600*365 ) {
		frequency = 2;
	    }
	    else {
		frequency = 3;
	    }  
	}
	else {
		frequency = (int) interval_;
	}
	if ( frequency == 0)
		frequency = 1;
	int count = 0;

	for ( int  year = min.date().year() ; year <= max.date().year() ; year++)
	{	
		if ((count++ % frequency)!=0) continue; 
		Date date(year, 1, 1);
		label = DateTime(date, Time(position, 0, 0));	
		list.push_back(new AxisDateItem(label -ref, label));
		tick = DateTime(date, Time(0, 0, 0));	

		list.push_back(new AxisTickItem(tick -ref));	
		for (int i = 2; i < 13; i+=1 )
		{
			Date date(year, i, 1);
			tick = DateTime(date, Time(0, 0, 0));
			MagLog::dev()<< "minor tick at ---" << tick << endl;
			list.push_back(new AxisMinorTickItem(tick -ref));
		}
	}
}
