/*  This file is part of lsnet. 
    Copyright (C) 2009-2010  Sterling Pickens
    Lsnet 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.

    Lsnet 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 lsnet.  If not, see <http://www.gnu.org/licenses/>.
*/


/*
	USAGE: 
	int days_in_month(int month_num)
	int days_since_start(char *datestring, int start_day)
	int total_days(char *date_start, char *date_end)

*/


#include "dates.h"

//######## For days in month translation
static unsigned int Month_Table(int monthnumber)
{
	//printf("m_num: %d\n", monthnumber);
	int days = 0;
        if (monthnumber == 1){
                days = 31; 
        //}else if ( monthnumber == 2 ) {
          //      days = 1;
        }else if ( monthnumber == 3 ) {
                days = 31;
        }else if ( monthnumber == 4 ) {
                days = 30;
        }else if ( monthnumber == 5 ) {
                days = 31;
        }else if ( monthnumber == 6 ) {
                days = 30;
        }else if ( monthnumber == 7 ) {
                days = 31;
        }else if ( monthnumber == 8 ) {
                days = 31;
        }else if ( monthnumber == 9 ) {
                days = 30;
        }else if ( monthnumber == 10 ) {
                days = 31;
        }else if ( monthnumber == 11 ) {
                days = 30;
        }else if ( monthnumber == 12 ) {
                days = 31;
        }else{
                printf("Invalid Month Number!\n");
                exit (1);
        }
	return days;
}

//##########Returns the number of days in any month###############
//int days_in_month(int month_num)
unsigned int Days_In_Month(struct Date *date_cur) {
	int daysinmonth = 0;
	int isleap      = 100;	
	int year        = date_cur->year;
	int month       = date_cur->month;
	int modulo1     = year % 4;
	int modulo2     = year % 100;
	int modulo3     = year % 400;
	//#leap years  2000 2004 2008
	//#not leaps 2009 2002 1999
	if(modulo1 == 0){
		isleap = 1;
		if(modulo2 == 0){
			isleap = 0;
			if(modulo3 == 0){
				isleap = 1;
			}
		}
	}else{
		isleap = 0;
	}
	//printf("isleap: %d\n", isleap);
   	//1. Every year that is divisible by four is a leap year;
   	//2. of those years, if it can be divided by 100, it is NOT a leap year, unless
   	//3. the year is divisible by 400. Then it is a leap year.

	if (isleap == 1 && month == 2){
		daysinmonth = 29;
	}else if (isleap == 0 && month == 2) {
        	daysinmonth = 28; 
	}else{
		//printf("%d\n", month);
		daysinmonth = Month_Table(month);
	}

	return daysinmonth;
}

//############ "03/03/2009","-20.00","*"
//unsigned int Days_Since_Start(struct date *date_start, struct date *date_cur){
	//int day;
	//int month;
	//int year;
//}

//########## change date to offset number of days in the past
void Decrement_Date(struct Date *date, int offset){
	//struct Date date_backup;
	//memcpy(&date_backup, date, sizeof(struct Date) );
	//unsigned int days_cur_month;
	//unsigned int day_count;
	//unsigned int month_count;
	//unsigned int year_count;
	int offset_reached = 0;
	
	while(1){
		while(date->day>1){
			date->day--;
			offset_reached++;
			if(offset_reached == offset)
				return;
		}
		if(date->month == 1){
			date->month = 12;
			date->year--;
		}else{
			date->month--;
		}
		date->day = Days_In_Month(date);
	}
}

void Increment_Date(struct Date *date, int offset){
	//offset into future
	unsigned int days_cur_month;
	int offset_reached = 0;
	while(1){
		days_cur_month = Days_In_Month(date);
		//for(day_count=date.day; day_count<=days_cur_month; day_count++){
		//day_count = date.day;
		if(date->day == days_cur_month){
			if(date->month == 12){
				date->month = 1;
				date->year++;
			}else{
				date->month++;
			}
			date->day = 1;
			offset_reached++;
			if(offset_reached == offset)
				return;
			continue;
		}
		while(date->day<days_cur_month){
			date->day++;
			offset_reached++;
			if(offset_reached == offset)
				return;
			//day_count++;
		}
		if(date->day == days_cur_month){
			date->day = 1;
			offset_reached++;
		}
		if(date->month == 12){
			date->month = 1;
			date->year++;
		}else{
			date->month++;
		}
		if(offset_reached == offset)
			return;
		//date->day = 1;
	}
}

unsigned int Is_Older(struct Date *date_start, struct Date *date_end){
	//1 for date_end is older, 0 for date_start is older
	if(date_start->year >= date_end->year){
		if(date_start->month >= date_end->month){
			if(date_start->day >= date_end->day){
				return 1;
			}
		}
	}
	return 0;
}

//###########  Calculates total days between two dates
unsigned int Total_Days(struct Date *date_start, struct Date *date_end){
	//printf("in Total_Days\n");
	unsigned int total_days  = 0;
	unsigned int day_count   = 0;
	unsigned int day_num = 0;
	unsigned int stop_day = date_end->day;
	unsigned int stop_month = date_end->month;
	unsigned int stop_year = date_end->year;
	int first_month = 1;
	int break_loop = 0;
	//unsigned int month_count = 0;
	//unsigned int year_count  = 0;
	struct Date date_tmp;
	//should add checks here for start/end relation
	//total_days = Days_In_Month(date_start) - date_start->day + 1;
	//sum of all days in all months after start month
	//day_count = date_start->day;

	date_tmp.year=date_start->year;
	date_tmp.month=date_start->month;
	date_tmp.day=date_start->day;


	//years
	while(date_tmp.year <= stop_year){
		while(date_tmp.month <= 12){
			day_count = Days_In_Month(&date_tmp);

			if(date_tmp.year == stop_year){
				if(date_tmp.month == stop_month){
					day_count = stop_day;
					break_loop = 1;
				}
			}
			if(first_month){
				total_days += day_count-date_tmp.day;
				first_month = 0;
			}else{
				total_days += day_count;
			}
			if(break_loop)
				return total_days;
			date_tmp.month++;
		}
		date_tmp.month = 1;
		date_tmp.year++;
	}

	return total_days;
}