<?php 

//
// Open Web Analytics - An Open Source Web Analytics Framework
//
// Copyright 2008 Peter Adams. All rights reserved.
//
// Licensed under GPL v2.0 http://www.gnu.org/copyleft/gpl.html
//
// 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.
//
// $Id$
//

/**
 * Time Period Class
 * 
 * @author      Peter Adams <peter@openwebanalytics.com>
 * @copyright   Copyright &copy; 2008 Peter Adams <peter@openwebanalytics.com>
 * @license     http://www.gnu.org/copyleft/gpl.html GPL v2.0
 * @category    owa
 * @package     owa
 * @version		$Revision$	      
 * @since		owa 1.0.0
 */


class owa_timePeriod {

	var $period;
	var $startDate;
	var $endDate;
	var $label;
	var $diff_years;
	var $diff_months;
	var $diff_days;
	var $is_default_period = false;
	
	function __construct() {
		
		//parent::__construct();
		
		$this->startDate = owa_coreAPI::supportClassFactory('base', 'date');
		$this->endDate = owa_coreAPI::supportClassFactory('base', 'date');
	}
	
	function getDefaultReportingPeriod() {
		
		return owa_coreAPI::getSetting( 'base', 'default_reporting_period' );
	}
	
	function setFromMap( $map ) {
		
		// normalize map
		$m = array(
			'period' => false,
			'startDate' => false,
			'endDate' => false,
			'startTime'  => false,
			'endTime' => false
		);
		
		$map = owa_lib::array_intersect_key($map, $m);
		
		
		// set default period if necessary
		if ( empty( $map[ 'period' ] ) && empty( $map[ 'startDate' ] ) ) {

			$this->is_default_period = true;
			$period = $this->getDefaultReportingPeriod();
			
		} elseif (  empty( $map[ 'period' ] ) &&  ! empty( $map[ 'startDate' ] ) && ! empty( $map[ 'endDate' ] ) ) {

			$period = 'date_range';

		} else {

			$period = $map['period'];
		}
		
		//validate period value
		$valid = $this->isValid( $period );
		
		if ( $valid ) {
			
			$this->period = $period;
			
		
		} else {
		
			$this->period = $this->getDefaultReportingPeriod();
			owa_coreAPI::debug("$period is not a valid period. Defaulting to default.");
		}
		
		$this->_setDates( $map );
		$this->_setLabel( $period );
		$this->_setDifferences();
		
	}
	
	// checks to see if the period value passsed is valid.
	function isValid( $value ) {
		
		$valid_periods = $this->getPeriodLabels();
		//add in date_range
		$valid_periods[ 'date_range' ] = '';
		
		return array_key_exists( $value, $valid_periods );
	}
	
	function isDefaultPeriod() {
		
		return $this->is_default_period;
	}
	
	function set($value = '', $map = array()) {
	
		$this->period = $value;
		$this->_setDates($map);
		$this->_setLabel($value);
		$this->_setDifferences();
	}
	
	function getStartDate() {
		return $this->startDate;
	}
	
	function getEndDate() {
		return $this->endDate;
	}
	
	function getLabel() {
		return $this->label;
	}
	
	function get() {
		return $this->period;
	}
	
	function _setLabel($value = '') {

		$this->label = $this->startDate->getLabel() . ' - ' . $this->endDate->getLabel();	
	}
	
	/**
	 * Array of Reporting Periods
	 *
	 * @return array
	 */
	function getPeriodLabels() {
		
		return array(
					
					'today' 				=> array('label' => 'Today'),
					'yesterday' 			=> array('label' => 'Yesterday'),
					'this_week' 			=> array('label' => 'This Week'),
					'this_month' 			=> array('label' => 'This Month'),
					'this_year' 			=> array('label' => 'This Year'),
					'last_week'  			=> array('label' => 'Last Week'),
					'last_month' 			=> array('label' => 'Last Month'),
					'last_year' 			=> array('label' => 'Last Year'),
					//'last_half_hour' 		=> array('label' => 'The Last 30 Minutes'),				
					//'last_hour' 			=> array('label' => 'Last Hour'),
					//'last_24_hours' 		=> array('label' => 'Last 24 Hours'),
					'last_seven_days' 		=> array('label' => 'Last Seven Days'),
					'last_thirty_days' 		=> array('label' => 'Last Thirty Days'),
					'same_day_last_week' 	=> array('label' => 'Same Day last Week'),
					'same_week_last_year' 	=> array('label' => 'Same Week Last Year'),
					'same_month_last_year' 	=> array('label' => 'Same Month Last Year'),
					//'date_range' 			=> array('label' => 'Date Range')
					//'time_range'			=> array('label' => 'Time Range')
		);
		
	}
	
	function _setDates($map = array()) {	
		
		$time_now = owa_lib::time_now();
		$nowDate = owa_coreAPI::supportClassFactory('base', 'date');
		$nowDate->set(time(), 'timestamp');
		$start = '';
		$end = '';
		
		switch ($this->period) {
			
			case "today":
				
				$start = mktime(0, 0, 0, $time_now['month'], $time_now['day'], $time_now['year']); 
				$end = $start + 3600 * 24 -1; 			
				break;
				
			case "last_24_hours":
				$end = $time_now['timestamp'];
				$start = $end - 3600*24;
				break;
				
			case "last_hour":
				$end = $time_now['timestamp'];
				$start = $end - 3600;
				break;
				
			case "last_half_hour":
				$end = $time_now['timestamp'];
				$start = $end - 1800;
				break;
				
			case "last_seven_days":
				//$end = mktime(0, 0, 0, $time_now['month'], $time_now['day']+1, $time_now['year']);
				$end = mktime(23, 59, 59, $time_now['month'], $time_now['day'], $time_now['year']);
				$start = $end - 3600*24*7;
				break;
			
			case "this_week":
				$end = mktime(23, 59, 59, $time_now['month'], $time_now['day'], $time_now['year']) + 
				((6 - $nowDate->get('day_of_week')) * 3600 * 24);
				$start = mktime(0, 0, 0, $time_now['month'], $time_now['day'], $time_now['year']) - 
				($nowDate->get('day_of_week') * 3600 * 24);
				break;
				
			case "this_month":
				$start = mktime(0, 0, 0, $time_now['month'], 1 , $time_now['year']);
				$end = mktime(23, 59, 59, $time_now['month'], $nowDate->get('num_days_in_month'), $time_now['year']);
				break;
				
			case "this_year":
				$start = mktime(0, 0, 0, 1, 1, $time_now['year']);
				$end = mktime(23, 59, 59, 12, 31, $time_now['year']);
				break;
				
			case "yesterday":
				$end = mktime(0, 0, 0, $time_now['month'], $time_now['day'], $time_now['year']); 
				$start = $end - 3600*24;
				$end = $end - 1;
				break;
				
			case "last_week":
				$day = ($time_now['day'] - $time_now['dayofweek']) - 7;
				$start = mktime(0, 0, 0, $time_now['month'], $day, $time_now['year']);
				$end = $start + 3600*24*7;
				break;
				
			case "last_month":
				$month =  $time_now['month'] - 1;
				$start = mktime(0, 0, 0, $month, 1, $time_now['year']);
				$last = owa_coreAPI::supportClassFactory('base', 'date');
				$last->set($start, 'timestamp');
				$end = mktime(23, 59, 59, $last->get('month'), $last->get('num_days_in_month'), $last->get('year'));
				break;
				
			case "last_year":
				$year = $time_now['year'] - 1;
				$start = mktime(0, 0, 0, 1, 1, $year);
				$end = mktime(23, 59, 59, 12, 31, $year);
				break;
				
			case "same_day_last_week":
				$start = mktime(0, 0, 0, $time_now['month'], $time_now['day'], $time_now['year']) - 3600*24*7;
				$end = $start + (3600*24) - 1;
				break;
			///	
			case "same_month_last_year":
				$year = $time_now['year'] - 1;
				$month = $time_now['month'];
				$start = mktime(0, 0, 0, $month, 1, $year);
				$last = owa_coreAPI::supportClassFactory('base', 'date');
				$last->set($start, 'timestamp');
				$end = mktime(23, 59, 59, $month, $last->get('num_days_in_month'), $year);
				break;
				
			case "all_time":
				$end = time();
				$start = mktime(0, 0, 0, 1, 1, 1969);
				break;
				
			case "last_thirty_days":
				$end = mktime(23, 59, 59, $time_now['month'], $time_now['day'], $time_now['year']);
				$start = ($end + 1) - (30 * 3600 * 24);
				break;	
					
			case "date_range":
				list($year, $month, $day) = sscanf($map['startDate'], "%4d%2d%2d");
				$start = mktime(0, 0, 0, $month, $day, $year);		
				list($year, $month, $day) = sscanf($map['endDate'], "%4d%2d%2d");
				$end = mktime(23, 59, 59, $month, $day, $year);
								
				break;
				
			case "time_range":
				$start = $map['startTime'];
				$end = $map['endTime'];				
				break;
				
			case "day":
				list($year, $month, $day) = sscanf($map['startDate'], "%4d%2d%2d");
				$start = mktime(0, 0, 0, $month, $day, $year);	
				$end = mktime(23, 59, 59, $month, $day, $year);
				break;
				
		}
		
		$this->startDate->set($start, 'timestamp');
		$this->endDate->set($end, 'timestamp');
	}
	
	function getPeriodProperties() {
	
		$period_params = array();
		$period_params['period'] = $this->get();
		$period_params['startDate'] = $this->startDate->getYyyymmdd();
		$period_params['endDate'] = $this->endDate->getYyyymmdd();	
		//$period_params['startTime'] = $this->startDate->getTimestamp();
		//$period_params['endTime'] = $this->endDate->getTimestamp();
		return $period_params;
	}
	
	function getAllInfo() {
		
		$info = array();
		$info['period'] = $this->get();
		$info['startDate'] = $this->startDate->getYyyymmdd();
		$info['endDate'] = $this->endDate->getYyyymmdd();
		$info['startTime'] = $this->startDate->getTimestamp();
		$info['endTime'] = $this->endDate->getTimestamp();	
		$info['label'] = $this->getLabel();
		
		return $info;
	}
	
	function _setDifferences() {
		
		// calc years diff
		$start = $this->startDate->getYyyymmdd();
		$end = $this->endDate->getYyyymmdd();	
		$diff = $this->getDateDifference($start, $end);
		
		$this->diff_years = $diff['YearsSince'];
		$this->diff_months = $diff['MonthsSince'];
		$this->diff_days = $diff['DaysSince'];
	}
	
	function getMonthsDifference() {
		
		return $this->diff_months;
	}

	function getYearsDifference() {
		
		return $this->diff_years;
	}
	
	function getDaysDifference() {
		
		return $this->diff_days;
	}
	
	// Function used to take two date strings, and returns an associative array 
    // with different formats for the difference between the dates. 
    // based on function by: tchapin at gmail dot com
    // -------------------- 
    // Variables: 
    // StartDateString (String - MM/DD/YYYY) 
    // EndDateString (String - MM/DD/YYYY) 
    // -------------------- 
    // Example: $DateDiffAry = GetDateDifference('01/09/2008', '02/11/2009'); 
    // print_r($DateDiffAry); 
    // -------------------- 
    // Returns Something Like: 
    /*    
    Array 
    ( 
        [YearsSince] => 1.0931506849315 
        [MonthsSince] => 13.117808219178 
        [DaysSince] => 399 
        [HoursSince] => 9576 
        [MinutesSince] => 574560 
        [SecondsSince] => 34473600 
        [NiceString] => 1 year, 1 month, and 2 days 
        [NiceString2] => Years: 1, Months: 1, Days: 2 
    ) 
    */ 
    function getDateDifference($StartDateString=NULL, $EndDateString=NULL) { 
        $ReturnArray = array(); 
        
        $SDSplit = sscanf($StartDateString,'%4d%2d%2d'); 
        $StartDate = mktime(0,0,0,$SDSplit[1],$SDSplit[2],$SDSplit[0]); 
        
        $EDSplit = sscanf($EndDateString,'%4d%2d%2d'); 
        $EndDate = mktime(0,0,0,$EDSplit[1],$EDSplit[2],$EDSplit[0]); 
        
        $DateDifference = $EndDate-$StartDate; 
        
        $ReturnArray['YearsSince'] = $DateDifference/60/60/24/365; 
        $ReturnArray['MonthsSince'] = $DateDifference/60/60/24/365*12; 
        $ReturnArray['DaysSince'] = $DateDifference/60/60/24; 
        $ReturnArray['HoursSince'] = $DateDifference/60/60; 
        $ReturnArray['MinutesSince'] = $DateDifference/60; 
        $ReturnArray['SecondsSince'] = $DateDifference; 

        $y1 = date("Y", $StartDate); 
        $m1 = date("m", $StartDate); 
        $d1 = date("d", $StartDate); 
        $y2 = date("Y", $EndDate); 
        $m2 = date("m", $EndDate); 
        $d2 = date("d", $EndDate); 
        
        $diff = ''; 
        $diff2 = ''; 
        if (($EndDate - $StartDate)<=0) { 
            // Start date is before or equal to end date! 
            $diff = "0 days"; 
            $diff2 = "Days: 0"; 
        } else { 

            $y = $y2 - $y1; 
            $m = $m2 - $m1; 
            $d = $d2 - $d1; 
            $daysInMonth = date("t",$StartDate); 
            if ($d<0) {$m--;$d=$daysInMonth+$d;} 
            if ($m<0) {$y--;$m=12+$m;} 
            $daysInMonth = date("t",$m2); 
            
            // Nicestring ("1 year, 1 month, and 5 days") 
            if ($y>0) $diff .= $y==1 ? "1 year" : "$y years"; 
            if ($y>0 && $m>0) $diff .= ", "; 
            if ($m>0) $diff .= $m==1? "1 month" : "$m months"; 
            if (($m>0||$y>0) && $d>0) $diff .= ", and "; 
            if ($d>0) $diff .= $d==1 ? "1 day" : "$d days"; 
            
            // Nicestring 2 ("Years: 1, Months: 1, Days: 1") 
            if ($y>0) $diff2 .= $y==1 ? "Years: 1" : "Years: $y"; 
            if ($y>0 && $m>0) $diff2 .= ", "; 
            if ($m>0) $diff2 .= $m==1? "Months: 1" : "Months: $m"; 
            if (($m>0||$y>0) && $d>0) $diff2 .= ", "; 
            if ($d>0) $diff2 .= $d==1 ? "Days: 1" : "Days: $d"; 
            
        }
        
        $ReturnArray['NiceString'] = $diff; 
        $ReturnArray['NiceString2'] = $diff2; 
        return $ReturnArray; 
    }	
}

?>