<?php defined('SYSPATH') or die('No direct access allowed.');

/**
 * This is class is for calculating date periods.
 *
 * @package    OSB
 * @category   Helpers
 * @author     Deon George
 * @copyright  (c) 2009-2013 Open Source Billing
 * @license    http://dev.osbill.net/license.html
 */
class Period {
	/**
	 * Calculate both the start and end dates for a billing period
	 * and the pro-rata percentage.
	 *
	 * See [StaticList_RecurSchedule]
	 *
	 * @param StaticList_RecurSchedule Period Type [StaticList_RecurSchedule]
	 * @param int Starting date if recurring must start on a day of the month
	 * @param datetime Date to start calculating from, otherwise now() is used
	 * @param boolean Show dates in 'Y-m-d' format
	 * @return array
	 */
	public static function details($type,$weekday=NULL,$start=NULL,$df=FALSE,$strict=FALSE) {
		// Round the time integer to a whole day.
		if (is_null($start))
			$start = strtotime('today');
		else
			$start = strtotime(date('Y-m-d',$start));

		$inc_months = $used_months = 0;

		switch ($type) {
			// Weekly
			case 0:
				if ($strict)
					throw new Kohana_Exception('Strict doesnt work here');

				$period_start = is_null($weekday) ? $start : $start+86400*($weekday-date('w',$start));
				$period_end = $period_start+(86400*7);

				break;

			// Monthly
			case 1:
				// NOTE: Strict doesnt do anything here.
				$inc_months = 1;
				break;

			// Quarterly
			case 2:
				$inc_months = 3;
				break;

			// Half Yearly
			case 3:
				$inc_months = 6;
				break;

			// Yearly
			case 4:
				$inc_months = 12;
				break;

			// Biennial
			case 5:
				$inc_months = 24;
				break;

			// Triennial
			case 6:
				if ($strict)
					throw new Kohana_Exception('Strict not implemented here');

				$inc_months = 36;
				break;

			default:
				return FALSE;
		}

		// Workout the period start day
		if (is_null($weekday))
			$weekday = $strict ? 1 : date('d',$start);

		// We only work our used_months for periods monthly or more.
		if ($inc_months) {
			if ($strict)
				$used_months = $inc_months-(($inc_months-(date('n',$start)%$inc_months))%$inc_months+1);

			$d = mktime(0,0,0,date('m',$start)-$used_months,$weekday,date('y',$start));
			if ($d <= $start)
				$period_start = $d;
			else
				$period_start = mktime(0,0,0,date('m',$d)-1-$used_months,$weekday,date('y',$d));

			// Workout the period end
			$period_end = mktime(0,0,0,date('m',$period_start)+$inc_months,$weekday,date('y',$period_start));
		}

		$total_time = $period_end-$period_start;
		$remain_time = $period_end-$start;
		$used_time = $start-$period_start;

		// Change our end date to the day before
		$period_end -= 86400;

		$result = array(
			'start'=>$period_start,
			'start_time'=>$start,
			'date'=>$start,
			'end'=>$period_end,
			'end_time'=>$period_end,
			'weekday'=>$weekday,
			'prorata'=>round($remain_time/$total_time,4),
			'total_time'=>sprintf('%3.1f',$total_time/86400),
			'remain_time'=>sprintf('%3.1f',$remain_time/86400),
			'used_time'=>sprintf('%3.1f',$used_time/86400),
		);

		if ($df)
			foreach (array('start','date','end') as $key)
				$result[$key] = Config::date($result[$key]);

		return $result;
	}

	/**
	 * Return if a date is in the same month as another date
	 */
	public static function inMonth($date,$period=NULL) {
		if (is_null($period))
			$period = time();

		return ($date >= strtotime('first day of',$period) AND $date <= strtotime('last day of',$period));
	}

	public static function multiple($rs) {
		switch($rs) {
			case 0: $multiple=52; break;
			case 1: $multiple=12; break;
			case 2: $multiple=4; break;
			case 3: $multiple=2; break;
			case 4: $multiple=1; break;
			case 5: $multiple=0.5; break;
			case 6: $multiple=0.33; break;
		}

		return $multiple;
	}
}
?>
