<?php
/*********************************************************************************
 * The contents of this file are subject to the TimeTrex Public License Version
 * 1.1.0 ("License"); You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at http://www.TimeTrex.com/TPL
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * All copies of the Covered Code must include on each user interface screen:
 *    (i) the "Powered by TimeTrex" logo and
 *    (ii) the TimeTrex copyright notice
 * in the same form as they appear in the distribution.  See full license for
 * requirements.
 *
 * The Original Code is: TimeTrex Open Source
 * The Initial Developer of the Original Code is TimeTrex Payroll Services
 * Portions created by TimeTrex are Copyright (C) 2004-2007 TimeTrex Payroll Services;
 * All Rights Reserved.
 *
 ********************************************************************************/
/*
 * $Revision: 2158 $
 * $Id: RecurringScheduleControlFactory.class.php 2158 2008-09-15 23:26:15Z ipso $
 * $Date: 2008-09-15 16:26:15 -0700 (Mon, 15 Sep 2008) $
 */

/**
 * @package Module_Schedule
 */
class RecurringScheduleControlFactory extends Factory {
	protected $table = 'recurring_schedule_control';
	protected $pk_sequence_name = 'recurring_schedule_control_id_seq'; //PK Sequence name

	protected $recurring_schedule_template_obj = NULL;
	function getCompany() {
		if ( isset($this->data['company_id']) ) {
			return $this->data['company_id'];
		}

		return FALSE;
	}
	function setCompany($id) {
		$id = trim($id);

		$clf = new CompanyListFactory();

		if ( $this->Validator->isResultSetWithRows(	'company',
													$clf->getByID($id),
													TTi18n::gettext('Company is invalid')
													) ) {

			$this->data['company_id'] = $id;

			return TRUE;
		}

		return FALSE;
	}

	function getRecurringScheduleTemplateControl() {
		if ( isset($this->data['recurring_schedule_template_control_id']) ) {
			return $this->data['recurring_schedule_template_control_id'];
		}

		return FALSE;
	}
	function setRecurringScheduleTemplateControl($id) {
		$id = trim($id);

		$rstclf = new RecurringScheduleTemplateControlListFactory();

		if ( $this->Validator->isResultSetWithRows(	'recurring_schedule_template_control',
													$rstclf->getByID($id),
													TTi18n::gettext('Recurring Schedule Template Control is invalid')
													) ) {

			$this->data['recurring_schedule_template_control_id'] = $id;

			return TRUE;
		}

		return FALSE;
	}

	function getStartWeek() {
		if ( isset($this->data['start_week']) ) {
			return (int)$this->data['start_week'];
		}

		return FALSE;
	}
	function setStartWeek($int) {
		$int = trim($int);

		if 	(	$int > 0
				AND
				$this->Validator->isNumeric(		'week',
													$int,
													TTi18n::gettext('Week is invalid')) ) {
			$this->data['start_week'] = $int;

			return TRUE;
		}

		return FALSE;
	}

	function getStartDate( $raw = FALSE ) {
		if ( isset($this->data['start_date']) ) {
			if ( $raw === TRUE ) {
				return $this->data['start_date'];
			} else {
				return TTDate::strtotime( $this->data['start_date'] );
			}
		}

		return FALSE;
	}
	function setStartDate($epoch) {
		$epoch = trim($epoch);

		if 	(	$this->Validator->isDate(		'start_date',
												$epoch,
												TTi18n::gettext('Incorrect start date'))
			) {

			$this->data['start_date'] = $epoch;

			return TRUE;
		}

		return FALSE;
	}

	function getEndDate( $raw = FALSE ) {
		if ( isset($this->data['end_date']) ) {
			if ( $raw === TRUE ) {
				return $this->data['end_date'];
			} else {
				return TTDate::strtotime( $this->data['end_date'] );
			}
		}

		return FALSE;
	}
	function setEndDate($epoch) {
		$epoch = trim($epoch);

		if ( $epoch == '' ){
			$epoch = NULL;
		}

		if 	(	$epoch == NULL
				OR
				$this->Validator->isDate(		'end_date',
												$epoch,
												TTi18n::gettext('Incorrect end date'))
			) {

			$this->data['end_date'] = $epoch;

			return TRUE;
		}

		return FALSE;
	}

	function getAutoFill() {
		if ( isset($this->data['auto_fill']) ) {
			return $this->fromBool( $this->data['auto_fill'] );
		}

		return FALSE;
	}
	function setAutoFill($bool) {
		$this->data['auto_fill'] = $this->toBool($bool);

		return true;
	}

	function getUser() {
		$rsulf = new RecurringScheduleUserListFactory();
		$rsulf->getByRecurringScheduleControlId( $this->getId() );
		foreach ($rsulf as $obj) {
			$list[] = $obj->getUser();
		}

		if ( isset($list) ) {
			return $list;
		}

		return FALSE;
	}
	function setUser($ids) {
		Debug::text('Setting User IDs : ', __FILE__, __LINE__, __METHOD__, 10);
		if (is_array($ids) and count($ids) > 0) {
			if ( !$this->isNew() ) {
				//If needed, delete mappings first.
				$rsulf = new RecurringScheduleUserListFactory();
				$rsulf->getByRecurringScheduleControlId( $this->getId() );

				$tmp_ids = array();
				foreach ($rsulf as $obj) {
					$id = $obj->getUser();
					Debug::text('Recurring Schedule ID: '. $obj->getRecurringScheduleControl() .' ID: '. $id, __FILE__, __LINE__, __METHOD__, 10);

					//Delete users that are not selected.
					if ( !in_array($id, $ids) ) {
						Debug::text('Deleting: '. $id, __FILE__, __LINE__, __METHOD__, 10);
						$obj->Delete();
					} else {
						//Save ID's that need to be updated.
						Debug::text('NOT Deleting : '. $id, __FILE__, __LINE__, __METHOD__, 10);
						$tmp_ids[] = $id;
					}
				}
				unset($id, $obj);
			}

			//Insert new mappings.
			$ulf = new UserListFactory();

			foreach ($ids as $id) {
				if ( isset($ids) AND !in_array($id, $tmp_ids) ) {
					$ulf->getById( $id );
					if ( $ulf->getRecordCount() > 0 ) {
						$obj = $ulf->getCurrent();

						$rsuf = new RecurringScheduleUserFactory();
						$rsuf->setRecurringScheduleControl( $this->getId() );
						$rsuf->setUser( $id );

						if ( $this->Validator->isTrue(		'user',
															$rsuf->Validator->isValid(),
															TTi18n::gettext('Selected Employee is invalid').' ('. $obj->getFullName() .')' )) {
							$rsuf->save();
						}
					}
				}
			}

			return TRUE;
		}

		Debug::text('No User IDs to set.', __FILE__, __LINE__, __METHOD__, 10);
		return FALSE;
	}

	function ReMapWeeks($week_arr) {
		//Remaps weeks based on start week
		Debug::text('Start Week: '.  $this->getStartWeek(), __FILE__, __LINE__, __METHOD__, 10);

		if ( $this->getStartWeek() > 1 AND in_array( $this->getStartWeek(), $week_arr) ) {
			Debug::text('Weeks DO need reordering: ', __FILE__, __LINE__, __METHOD__, 10);
			$max_week = count($week_arr);

			$i=1;
			foreach( $week_arr as $key => $val ) {
				$new_val = $key - ($this->getStartWeek()-1);

				if ( $key < $this->getStartWeek() ) {
					$new_val = $new_val + $max_week;
				}

				//$arr[$key] = $new_val;
				$arr[$new_val] = $key;
				//$arr[$i] = $key;

				$i++;
			}
			//var_dump($arr);
			return $arr;
		}

		Debug::text('Weeks do not need reordering: ', __FILE__, __LINE__, __METHOD__, 10);

		return $week_arr;
	}

	function getShiftsByStartDateAndEndDate($start_date, $end_date) {

		//Make sure timezone isn't in the time format. Because recurring schedules
		//are timezone agnostic. 7:00AM in PST is also 7:00AM in EST.
		//This causes an issue where the previous users timezone carries over to the next
		//users timezone, causing errors.
		//TTDate::setTimeFormat('g:i A');

		if ( $start_date == '' ) {
			return FALSE;
		}

		if ( $end_date == '' ) {
			return FALSE;
		}

		if ( $start_date < $this->getStartDate() ) {
			$start_date = $this->getStartDate();
		}

		if ( $this->getEndDate(TRUE) != NULL AND $end_date > $this->getEndDate() ) {
			$end_date = $this->getEndDate();
		}
		Debug::text('Start Date: '. TTDate::getDate('DATE+TIME', $start_date) .' End Date: '. TTDate::getDate('DATE+TIME', $end_date), __FILE__, __LINE__, __METHOD__, 10);

		//Get week data
		$rstlf = new RecurringScheduleTemplateListFactory();
		$rstlf->getByRecurringScheduleTemplateControlId( $this->getRecurringScheduleTemplateControl() )->getCurrent();
		$max_week = 1;
		$weeks = array();
		if ( $rstlf->getRecordCount() > 0 ) {
			foreach($rstlf as $rst_obj) {
				Debug::text('Week: '. $rst_obj->getWeek(), __FILE__, __LINE__, __METHOD__, 10);
				$template_week_rows[$rst_obj->getWeek()][] = $rst_obj->getObjectAsArray();

				$weeks[$rst_obj->getWeek()] = $rst_obj->getWeek();

				if ( $rst_obj->getWeek() > $max_week ) {
					$max_week = $rst_obj->getWeek();
				}
			}
		}

		$weeks = $this->ReMapWeeks( $weeks );

		//Get week of start_date
		$start_date_week = TTDate::getWeek( $this->getStartDate() );
		Debug::text('Week of Start Date: '. $start_date_week ,__FILE__, __LINE__, __METHOD__, 10);

		for ( $i=$start_date; $i <= $end_date; $i+=86400) {
			$current_week = TTDate::getWeek( $i );
			//Debug::text('Current Date: '. TTDate::getDate('DATE+TIME', $i) .' Current Week: '. $current_week,__FILE__, __LINE__, __METHOD__, 10);

			$template_week = ( ( ( abs($current_week-$start_date_week) ) % $max_week ) ) + 1;
			//Debug::text('Template Week: '. $template_week .' Max Week: '. $max_week,__FILE__, __LINE__, __METHOD__, 10);

			$day_of_week = strtolower(date('D', $i));
			//Debug::text('Day Of Week: '. $day_of_week,__FILE__, __LINE__, __METHOD__, 10);

			if ( isset($weeks[$template_week] ) ) {
				$mapped_template_week = $weeks[$template_week];
				//Debug::text('Mapped Template Week: '. $mapped_template_week,__FILE__, __LINE__, __METHOD__, 10);

				if ( isset($template_week_rows[$mapped_template_week]) ) {
					//Debug::text('Starting Looping...!',__FILE__, __LINE__, __METHOD__, 10);

					foreach( $template_week_rows[$mapped_template_week] as $template_week_arr ) {
						if ( $template_week_arr['days'][$day_of_week] == TRUE ) {
							//Debug::text('Found Scheduled Time: Start Time: '. TTDate::getDate('DATE+TIME', TTDate::getTimeLockedDate( $template_week_arr['start_time'], $i ) ),__FILE__, __LINE__, __METHOD__, 10);

							$start_time = TTDate::getTimeLockedDate( $template_week_arr['start_time'], $i );
							$end_time = TTDate::getTimeLockedDate( $template_week_arr['end_time'], $i );
							if ( $end_time < $start_time ) {
								//Spans the day boundary, add 86400 to end_time
								$end_time = $end_time + 86400;
								Debug::text('Schedule spans day boundary, bumping endtime to next day: ',__FILE__, __LINE__, __METHOD__, 10);
							}
							//Debug::text('Start Date: '. TTDate::getDate('DATE+TIME', $start_time) .' End Date: '. TTDate::getDate('DATE+TIME', $end_time),__FILE__, __LINE__, __METHOD__, 10);

							//$shifts[TTDate::getBeginDayEpoch($i)][] = array(
							$shifts[TTDate::getISODateStamp($i)][] = array(
																'status_id' => $template_week_arr['status_id'],
																'start_time' => $start_time,
																'raw_start_time' => TTDate::getDate('DATE+TIME', $start_time ),
																'end_time' => $end_time,
																'raw_end_time' => TTDate::getDate('DATE+TIME', $end_time ),
																'total_time' => $template_week_arr['total_time'],
																'schedule_policy_id' => $template_week_arr['schedule_policy_id'],
																'branch_id' => $template_week_arr['branch_id'],
																'department_id' => $template_week_arr['department_id'],
																'job_id' => $template_week_arr['job_id'],
																'job_item_id' => $template_week_arr['job_item_id']
																);
							unset($start_time, $end_time);
						} else {
							//Debug::text('aSkipping!',__FILE__, __LINE__, __METHOD__, 10);
						}
					}

				} else {
					//Debug::text('bSkipping!',__FILE__, __LINE__, __METHOD__, 10);
				}
			} else {
				//Debug::text('cSkipping!',__FILE__, __LINE__, __METHOD__, 10);
			}

		}

		//var_dump($shifts);
		if ( isset($shifts) ) {
			return $shifts;
		}

		return FALSE;
	}

	function addLog( $log_action ) {
		return TTLog::addEntry( $this->getId(), $log_action,  TTi18n::getText('Recurring Schedule'), NULL, $this->getTable() );
	}
}
?>
