/*
 * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
 *
 * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 *
 * You can also choose to distribute this program under the terms of
 * the Unmodified Binary Distribution Licence (as given in the file
 * COPYING.UBDL), provided that you have satisfied its requirements.
 */

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
FILE_SECBOOT ( PERMITTED );

#include <assert.h>
#include <time.h>

/** @file
 *
 * Date and time
 *
 * POSIX:2008 section 4.15 defines "seconds since the Epoch" as an
 * abstract measure approximating the number of seconds that have
 * elapsed since the Epoch, excluding leap seconds.  The formula given
 * is
 *
 *    tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 +
 *    (tm_year-70)*31536000 + ((tm_year-69)/4)*86400 -
 *    ((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400
 *
 * This calculation assumes that leap years occur in each year that is
 * either divisible by 4 but not divisible by 100, or is divisible by
 * 400.
 */

/** Current system clock offset */
signed long time_offset;

/** Days of week (for debugging) */
static const char *weekdays[] = {
	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};

/**
 * Determine whether or not year is a leap year
 *
 * @v tm_year		Years since 1900
 * @v is_leap_year	Year is a leap year
 */
static int is_leap_year ( int tm_year ) {
	int leap_year = 0;

	if ( ( tm_year % 4 ) == 0 )
		leap_year = 1;
	if ( ( tm_year % 100 ) == 0 )
		leap_year = 0;
	if ( ( tm_year % 400 ) == 100 )
		leap_year = 1;

	return leap_year;
}

/**
 * Calculate number of leap years since 1900
 *
 * @v tm_year		Years since 1900
 * @v num_leap_years	Number of leap years
 */
static int leap_years_to_end ( int tm_year ) {
	int leap_years = 0;

	leap_years += ( tm_year / 4 );
	leap_years -= ( tm_year / 100 );
	leap_years += ( ( tm_year + 300 ) / 400 );

	return leap_years;
}

/**
 * Calculate day of week
 *
 * @v tm_year		Years since 1900
 * @v tm_mon		Month of year [0,11]
 * @v tm_day		Day of month [1,31]
 */
static int day_of_week ( int tm_year, int tm_mon, int tm_mday ) {
	static const uint8_t offset[12] =
		{ 1, 4, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5 };
	int pseudo_year = tm_year;

	if ( tm_mon < 2 )
		pseudo_year--;
	return ( ( pseudo_year + leap_years_to_end ( pseudo_year ) +
		   offset[tm_mon] + tm_mday ) % 7 );
}

/** Days from start of year until start of months (in non-leap years) */
static const uint16_t days_to_month_start[] =
	{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };

/**
 * Calculate seconds since the Epoch
 *
 * @v tm		Broken-down time
 * @ret time		Seconds since the Epoch
 */
time_t mktime ( struct tm *tm ) {
	int tm_year = tm->tm_year;
	int tm_mon = tm->tm_mon;
	int tm_mday = tm->tm_mday;
	int tm_hour = tm->tm_hour;
	int tm_min = tm->tm_min;
	int tm_sec = tm->tm_sec;
	int tm_yday;
	int tm_wday;
	int days_since_epoch;
	int seconds_since_day;
	time_t seconds;

	/* Normalize month for use as an array index */
	tm_year += ( tm_mon / 12 );
	tm_mon = ( tm_mon % 12 );
	if ( tm_mon < 0 ) {
		tm_year--;
		tm_mon += 12;
	}
	assert ( tm_mon >= 0 );
	assert ( tm_mon < 12 );

	/* Calculate day of year */
	tm_yday = ( ( tm_mday - 1 ) + days_to_month_start[tm_mon] );
	if ( ( tm_mon >= 2 ) && is_leap_year ( tm_year ) )
		tm_yday++;
	tm->tm_yday = tm_yday;

	/* Calculate day of week */
	tm_wday = day_of_week ( tm_year, tm_mon, tm_mday );
	tm->tm_wday = tm_wday;

	/* Calculate seconds since the Epoch */
	days_since_epoch = ( tm_yday + ( 365 * tm_year ) - 25567 +
			     leap_years_to_end ( tm_year - 1 ) );
	seconds_since_day =
		( ( ( ( tm_hour * 60 ) + tm_min ) * 60 ) + tm_sec );
	seconds = ( ( ( ( time_t ) days_since_epoch ) * ( ( time_t ) 86400 ) )
		    + seconds_since_day );

	DBGC ( &weekdays, "TIME %04d-%02d-%02d %02d:%02d:%02d => %lld (%s, "
	       "day %d)\n", ( tm->tm_year + 1900 ), ( tm->tm_mon + 1 ),
	       tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, seconds,
	       weekdays[ tm->tm_wday ], tm->tm_yday );

	return seconds;
}
