<?php
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
/*********************************************************************************
 * SugarCRM Community Edition is a customer relationship management program developed by
 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.

 * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd.
 * Copyright (C) 2011 - 2014 Salesagility Ltd.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by the
 * Free Software Foundation with the addition of the following permission added
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
 *
 * 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 Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along with
 * this program; if not, see http://www.gnu.org/licenses or write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 *
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
 * these Appropriate Legal Notices must retain the display of the "Powered by
 * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
 * reasonably feasible for  technical reasons, the Appropriate Legal Notices must
 * display the words  "Powered by SugarCRM" and "Supercharged by SuiteCRM".
 ********************************************************************************/





require_once('include/utils/activity_utils.php');
require_once('modules/Calendar/CalendarUtils.php');
require_once('modules/Calendar/CalendarActivity.php');

class Calendar {

	public $activityList = array("FP_events" => array("showCompleted" => true,"start" =>  "date_start", "end" => "date_end"),
								 "Meetings" => array("showCompleted" => true,"start" =>  "date_start", "end" => "date_end"),
								 "Calls" => array("showCompleted" => true,"start" =>  "date_start", "end" => "date_end"),
								 "Tasks" => array("showCompleted" => true,"start" =>  "date_due", "end" => "date_due"),
//								 "ProjectTask" => array("showCompleted" => true,"start" =>  "date_start", "end" => "date_finish"),
	//							 "Project" => array("showCompleted" => true,"start" =>  "estimated_start_date", "end" => "estimated_end_date")
								 );
	public $views = array("agendaDay" => array(),"basicDay" => array(), "basicWeek" => array(), "agendaWeek" => array(),"month" => array(), "sharedMonth" => array(), "sharedWeek" => array());

	public $view = 'agendaWeek'; // current view
	public $style; // calendar style (basic or advanced)
	public $dashlet = false; // if is displayed in dashlet	
	public $date_time; // current date
	
	public $show_tasks = true;
	public $show_calls = true;
	public $show_completed = true;
	public $enable_repeat = true;	

	public $time_step = 60; // time step of each slot in minutes
		
	public $acts_arr = array(); // Array of activities objects	
	public $items = array(); // Array of activities data to be displayed	
	public $shared_ids = array(); // ids of users for shared view
	
	
	public $cells_per_day; // entire 24h day count of slots 	
	public $grid_start_ts; // start timestamp of calendar grid
	
	public $day_start_time; // working day start time in format '11:00'
	public $day_end_time; // working day end time in format '11:00'
	public $scroll_slot; // first slot of working day
	public $celcount; // count of slots in a working day	

    /**
     * @var bool $print Whether is print mode.
     */
    private $print = false;
		
	/**
	 * constructor
	 * @param string $view 
	 * @param array $time_arr
	 * @param array $views
	 */	
	function __construct($view = "agendaWeek", $time_arr = array()){
		global $current_user, $timedate, $current_language;
		
		$this->view = $view;		

		if(!array_key_exists($this->view, $this->views))
			$this->view = 'agendaWeek';
		
		$date_arr = array();
		if(!empty($_REQUEST['day']))
			$_REQUEST['day'] = intval($_REQUEST['day']);
		if(!empty($_REQUEST['month']))
			$_REQUEST['month'] = intval($_REQUEST['month']);

		if (!empty($_REQUEST['day']))
			$date_arr['day'] = $_REQUEST['day'];
		if (!empty($_REQUEST['month']))
			$date_arr['month'] = $_REQUEST['month'];
		if (!empty($_REQUEST['week']))
			$date_arr['week'] = $_REQUEST['week'];
		if (!empty($_REQUEST['mobile']))
			$date_arr['mobile'] = $_REQUEST['mobile'];

		if (!empty($_REQUEST['year'])){
			if ($_REQUEST['year'] > 2037 || $_REQUEST['year'] < 1970){
                $calendarStrings = return_module_language($current_language, 'Calendar');
                print($calendarStrings['ERR_YEAR_BETWEEN']);
				exit;
			}
			$date_arr['year'] = $_REQUEST['year'];
		}

		if(empty($_REQUEST['day']))
			$_REQUEST['day'] = "";
		if(empty($_REQUEST['week']))
			$_REQUEST['week'] = "";
		if(empty($_REQUEST['month']))
			$_REQUEST['month'] = "";
		if(empty($_REQUEST['year']))
			$_REQUEST['year'] = "";
		if(empty($_REQUEST['mobile']))
			$_REQUEST['mobile'] = "";

		// if date is not set in request use current date
		if(empty($date_arr) || !isset($date_arr['year']) || !isset($date_arr['month']) || !isset($date_arr['day'])){
			$today = $timedate->getNow(true);
			$date_arr = array(
			      'year' => $today->year,
			      'month' => $today->month,
			      'day' => $today->day,
			      'mobile' => $today->day,
			);
		}
		
		$current_date_db = $date_arr['year']."-".str_pad($date_arr['month'],2,"0",STR_PAD_LEFT)."-".str_pad($date_arr['day'],2,"0",STR_PAD_LEFT);
		$this->date_time = $GLOBALS['timedate']->fromString($current_date_db);	
        
		$this->show_tasks = $current_user->getPreference('show_tasks');
		if(is_null($this->show_tasks))
			$this->show_tasks = SugarConfig::getInstance()->get('calendar.show_tasks_by_default',true);
        
		$this->show_calls = $current_user->getPreference('show_calls');
		if(is_null($this->show_calls))
			$this->show_calls = SugarConfig::getInstance()->get('calendar.show_calls_by_default',true);
        
		// Show completed Meetings, Calls, Tasks
        $this->show_completed = $current_user->getPreference('show_completed');
        if(is_null($this->show_completed))
        {
            $this->show_completed = SugarConfig::getInstance()->get('calendar.show_completed_by_default', true);
        }
        
		$this->enable_repeat = SugarConfig::getInstance()->get('calendar.enable_repeat',true);	

		if(in_array($this->view,array('month','year'))){
			$this->style = "basic";	
		}else{
			$displayTimeslots = $GLOBALS['current_user']->getPreference('calendar_display_timeslots');
			if (is_null($displayTimeslots)) {
				$displayTimeslots = SugarConfig::getInstance()->get('calendar.display_timeslots', true);
			}
			if (!$displayTimeslots) {
				switch($this->view) {
					case "agendaDay":
						$this->view = "basicDay";
					break;
					case "agendaWeek":
						$this->view = "basicWeek";
					break;
				}
			}else{
				switch($this->view) {
					case "basicDay":
						$this->view = "agendaDay";
						break;
					case "basicWeek":
						$this->view = "agendaWeek";
						break;
				}
			}
		}
		
		$this->day_start_time = $current_user->getPreference('day_start_time');
		if(is_null($this->day_start_time))
			$this->day_start_time = SugarConfig::getInstance()->get('calendar.default_day_start',"08:00");
		$this->day_end_time = $current_user->getPreference('day_end_time');
		if(is_null($this->day_end_time))
			$this->day_end_time = SugarConfig::getInstance()->get('calendar.default_day_end',"19:00");
			
		if($this->view == "day"){
			$this->time_step = SugarConfig::getInstance()->get('calendar.day_timestep',15);
		}else if($this->view == "week" || $this->view == "shared"){
			$this->time_step = SugarConfig::getInstance()->get('calendar.week_timestep',30);
		}else if($this->view == "month"){
			$this->time_step = SugarConfig::getInstance()->get('calendar.month_timestep',60);
		}else{
			$this->time_step = 60;
		}
		$this->cells_per_day = 24 * (60 / $this->time_step);		
		$this->calculate_grid_start_ts();
		$this->calculate_day_range();		
	}
	
	/**
	 * Load activities data to array
	 */		
	public function load_activities(){


		$field_list = CalendarUtils::get_fields();

		$i = 0;
		foreach($this->acts_arr as $user_id => $acts){
			if(isset($acts) && empty($acts)){
				$shared_calendar_separate = $GLOBALS['current_user']->getPreference('calendar_display_shared_separate');
				if(is_null($shared_calendar_separate)) {
					$shared_calendar_separate = SugarConfig::getInstance()->get('calendar.calendar_display_shared_separate', true);
				}
				//if no calendar items we add the user to the list.
				if($shared_calendar_separate){
					//$this->items[ $item['user_id'] ][] = $item;
					$this->items[ $user_id ][] = array();
				}else{
					$this->items[ $GLOBALS['current_user']->id ][] = array();
				}
				continue;
			}
			foreach($acts as $act){
											
					$item = array();
					$item['user_id'] = $user_id;
					$item['module_name'] = $act->sugar_bean->module_dir;
					$item['type'] = strtolower($act->sugar_bean->object_name);
					$item['assigned_user_id'] = $act->sugar_bean->assigned_user_id;
					$item['record'] = $act->sugar_bean->id;		
					$item['name'] = $act->sugar_bean->name . ' ' . $act->sugar_bean->assigned_user_name;
					$item['description'] = $act->sugar_bean->description;

					if(isset($act->sugar_bean->duration_hours)){
						$item['duration_hours'] = $act->sugar_bean->duration_hours;
						$item['duration_minutes'] = $act->sugar_bean->duration_minutes;
					}				
					 			
					$item['detail'] = 0;
					$item['edit'] = 0;
					
					if($act->sugar_bean->ACLAccess('DetailView'))
						$item['detail'] = 1;						
					if($act->sugar_bean->ACLAccess('Save'))
						$item['edit'] = 1;					
						
					if(empty($act->sugar_bean->id)){
						$item['detail'] = 0;
						$item['edit'] = 0;
					}
					
					if(!empty($act->sugar_bean->repeat_parent_id))
						$item['repeat_parent_id'] = $act->sugar_bean->repeat_parent_id;					
					
					if($item['detail'] == 1){
						if(isset($field_list[$item['module_name']])){
							foreach($field_list[$item['module_name']] as $field){
								if(!isset($item[$field]) && isset($act->sugar_bean->$field)){
									$item[$field] = $act->sugar_bean->$field;
									if(empty($item[$field]))
										$item[$field] = "";
								}
							}					
						}				
					}

                    if (!empty($act->sugar_bean->parent_type) && !empty($act->sugar_bean->parent_id)) {
                        $focus = BeanFactory::getBean($act->sugar_bean->parent_type, $act->sugar_bean->parent_id);
                        // If the bean wasn't loaded, e.g. insufficient permissions
                        if (!empty($focus))
                        {
                            $item['related_to'] = $focus->name;
                        }
                    }

					if(!isset($item['duration_hours']) || empty($item['duration_hours']))
						$item['duration_hours'] = 0;
					if(!isset($item['duration_minutes']) || empty($item['duration_minutes']))
						$item['duration_minutes'] = 0;	

					if(isset($this->activityList[ $act->sugar_bean->module_name ]['start']) && !empty($this->activityList[ $act->sugar_bean->module_name ]['start'])){
						$item = array_merge($item,CalendarUtils::get_time_data($act->sugar_bean, $this->activityList[ $act->sugar_bean->module_name ]['start'], $this->activityList[ $act->sugar_bean->module_name ]['end']));
					}else{
						$item = array_merge($item,CalendarUtils::get_time_data($act->sugar_bean));
					}


				$shared_calendar_separate = $GLOBALS['current_user']->getPreference('calendar_display_shared_separate');
				if(is_null($shared_calendar_separate)) {
					$shared_calendar_separate = SugarConfig::getInstance()->get('calendar.calendar_display_shared_separate', true);
				}
				//if no calendar items we add the user to the list.
				if($shared_calendar_separate){
					$this->items[ $item['user_id'] ][] = $item;
				}else{
					$this->items[ $GLOBALS['current_user']->id ][] = $item;
				}
			}
			$i++;
		}
	}	
	
	/**
	 * initialize ids of shared users
	 */	
	public function init_shared(){
		global $current_user;
		
		
		$user_ids = $current_user->getPreference('shared_ids');
		if(!empty($user_ids) && count($user_ids) != 0 && !isset($_REQUEST['shared_ids'])) {
			$this->shared_ids = $user_ids;
		}else if(isset($_REQUEST['shared_ids']) && count($_REQUEST['shared_ids']) > 0){
			$this->shared_ids = $_REQUEST['shared_ids'];
			$current_user->setPreference('shared_ids', $_REQUEST['shared_ids']);
		}else{
			$this->shared_ids = array($current_user->id);				
		}
	}
	
	/**
	 * Calculate timestamp the calendar grid should be started from 
	 */
	protected function calculate_grid_start_ts(){
	
		if($this->view == "agendaWeek" || $this->view == "shared"){
			$week_start = CalendarUtils::get_first_day_of_week($this->date_time);
			$this->grid_start_ts = $week_start->format('U') + $week_start->getOffset(); 
		}else if($this->view == "month"){
			$month_start = $this->date_time->get_day_by_index_this_month(0);
			$week_start = CalendarUtils::get_first_day_of_week($month_start);
			$this->grid_start_ts = $week_start->format('U') + $week_start->getOffset(); // convert to timestamp, ignore tz
		}else if($this->view == "agendaDay"){
			$this->grid_start_ts = $this->date_time->format('U') + $this->date_time->getOffset();
		}	
	}
	
	/**
	 * calculate count of timeslots per visible day, calculates day start and day end in minutes 
	 */	
	function calculate_day_range(){	
		
		list($hour_start,$minute_start) =  explode(":",$this->day_start_time);		
		list($hour_end,$minute_end) =  explode(":",$this->day_end_time);
		$this->scroll_slot = intval($hour_start * (60 / $this->time_step) + ($minute_start / $this->time_step));
		$this->celcount = (($hour_end * 60 + $minute_end) - ($hour_start * 60 + $minute_start)) / $this->time_step;
	}	
	
	/**
	 * loads array of objects
	 * @param User $user user object
	 * @param string $type
	 */	
	public function add_activities($user,$type='sugar'){
		global $timedate;
		$start_date_time = $this->date_time;
		if($this->view == 'agendaWeek' || $this->view == 'sharedWeek'){
			$start_date_time = CalendarUtils::get_first_day_of_week($this->date_time);
			$end_date_time = $start_date_time->get("+7 days");
		}else if($this->view == 'month' || $this->view == "sharedMonth"){
			$start_date_time = $this->date_time->get_day_by_index_this_month(0);	
			$end_date_time = $start_date_time->get("+".$start_date_time->format('t')." days");
			$start_date_time = CalendarUtils::get_first_day_of_week($start_date_time);
			$end_date_time = CalendarUtils::get_first_day_of_week($end_date_time)->get("+7 days");
		}else{
			$end_date_time = $this->date_time->get("+1 day");
		}
		
		$start_date_time = $start_date_time->get("-5 days"); // 5 days step back to fetch multi-day activities that

		$acts_arr = array();
	    	if($type == 'vfb')
	    	{
				$acts_arr = CalendarActivity::get_freebusy_activities($user, $start_date_time, $end_date_time);
	    	}
	    	else
	    	{
				$acts_arr = CalendarActivity::get_activities($this->activityList, $user->id, $this->show_tasks, $start_date_time, $end_date_time, $this->view, $this->show_calls, $this->show_completed);
	    	}


	    	//$this->acts_arr[$user->id] = $acts_arr;
	    	$this->acts_arr[$user->id] = $acts_arr;
	}

	/**
	 * Get date string of next or previous calendar grid
	 * @param string $direction next or previous
	 * @return string
	 */
	public function get_neighbor_date_str($direction){
		if($direction == "previous")
			$sign = "-";
		else 
			$sign = "+";
			
		if($this->view == 'month' || $this->view == "sharedMonth"){
            $day = $this->date_time->get_day_by_index_this_month(0)->get($sign."1 month")->get_day_begin(1);
		}else if($this->view == 'agendaWeek' || $this->view == 'sharedWeek' || $this->view == 'basicWeek'){
			$day = CalendarUtils::get_first_day_of_week($this->date_time);
			$day = $day->get($sign."7 days");
		}else if($this->view == 'agendaDay' || $this->view == 'basicDay'){
			$day = $this->date_time->get($sign."1 day")->get_day_begin();
		}else if($this->view == 'year'){
            		$day = $this->date_time->get($sign."1 year")->get_day_begin();
		}else{
            $calendarStrings = return_module_language($GLOBALS['current_language'], 'Calendar');
            return $calendarStrings['ERR_NEIGHBOR_DATE'];
		}
		return $day->get_date_str();
	}

    public function setPrint($print)
    {
        $this->print = $print;
    }
    
    public function isPrint()
    {
        return $this->print;
    }

}

?>
