<?php 

	require_once SYSTEM_MODULE_PATH . '/controllers/ScheduleController.class.php';

	/**
	 * Reschedule milestone
	 * 
	 * @package activeCollab.modules.system
	 * @subpackage controller
	 */
	class MilestoneScheduleController extends ScheduleController {
		
		/**
		 * Reschedule milestone
		 */
		function reschedule() {
		  if($this->request->isAsyncCall() || ($this->request->isApiCall() && $this->request->isSubmitted()) || $this->request->isMobileDevice()) {
		    $describe_affected = $this->request->get('describe_affected', false);
  			
        $reschedule_url = $this->active_object->schedule()->getRescheduleUrl();
        if ($describe_affected) {
        	$reschedule_url = extend_url($reschedule_url, array('describe_affected' => true));
        } // if
  
        $milestone_data = $this->request->post('milestone', array(
  	      'start_on' => $this->request->get('start_on') ? DateValue::makeFromString($this->request->get('start_on')) : $this->active_object->getStartOn(),
  	      'due_on' => $this->request->get('due_on') ? DateValue::makeFromString($this->request->get('due_on')) : $this->active_object->getDueOn(),
  	      'reschedule_milestone_objects' => true,
        ));
        
        $successive_milestones = Milestones::findSuccessiveByMilestone($this->active_object, STATE_VISIBLE, $this->logged_user->getMinVisibility());
        
        $this->smarty->assign(array(
          'milestone_data' => $milestone_data,
          'successive_milestones' => $successive_milestones,
        	'reschedule_url'	=> $reschedule_url
        ));
        
        if($this->request->isSubmitted()) {
          $old_start_on = $this->active_object->getStartOn();
          $old_due_on = $this->active_object->getDueOn();
          
          $to_be_determined = isset($milestone_data['to_be_determined']) && $milestone_data['to_be_determined'];
          
          if($to_be_determined) {
            $new_start_on = null;
            $new_due_on = null;
            $reschedule_tasks = false;
          } else {
            $new_start_on = isset($milestone_data['start_on']) && $milestone_data['start_on'] ? new DateValue($milestone_data['start_on']) : null;
            $new_due_on = isset($milestone_data['due_on']) && $milestone_data['due_on'] ? new DateValue($milestone_data['due_on']) : null;
            
            if($new_start_on instanceof DateValue || $new_due_on instanceof DateValue) {
            	if (is_null($new_start_on)) {
            		$new_start_on = clone($new_due_on);
            	} elseif (is_null($new_due_on)) {
            		$new_due_on = clone($new_start_on);
            	} //if
              $reschedule_tasks = isset($milestone_data['reschedule_milestone_objects']) && $milestone_data['reschedule_milestone_objects'];
            } else {
              $to_be_determined = true;
              $reschedule_tasks = false;
            } // if
          } // if
  
          $skip_days_off = ConfigOptions::getValue('skip_days_off_when_rescheduling');
          
          try {
            DB::beginWork('Rescheduling a milestone  @ ' . __CLASS__);
            
            if ($to_be_determined) {
            	$this->active_object->setDueOn(null);
            	$this->active_object->setStartOn(null);
            	$this->active_object->save();
            } else {
            	ProjectScheduler::rescheduleMilestone($this->active_object, $new_start_on, $new_due_on, $reschedule_tasks, $skip_days_off);
            	
  	          if(!$to_be_determined && $old_start_on instanceof DateValue && ($new_start_on->getTimestamp() != $old_start_on->getTimestamp())) {
  	            $with_successive = array_var($milestone_data, 'with_sucessive');
  	            
  	            $to_move = null;
  	            switch(array_var($with_successive, 'action')) {
  	              case 'move_all':
  	                $to_move = $successive_milestones;
  	                break;
  	              case 'move_selected':
  	                $selected_milestones = array_var($with_successive, 'milestones');
  	                if(is_foreachable($selected_milestones)) {
  	                  $to_move = Milestones::findByIds($selected_milestones, STATE_VISIBLE, $this->logged_user->getMinVisibility());
  	                } // if
  	                break;
  	            } // switch
  	            
  	            if(is_foreachable($to_move)) {
  	              ProjectScheduler::rescheduleMilestones($to_move, $new_start_on->getTimestamp() - $old_start_on->getTimestamp(), $reschedule_tasks, $skip_days_off);
  	            } // if
  	          } // if
            } //if
            
            DB::commit('Milestone rescheduled  @ ' . __CLASS__);
            
            $described_milestone = $this->active_object->describe($this->logged_user, true, true); 
            
            if ($describe_affected && is_foreachable($to_move)) {
            	$milestone_ids = array();
            	$affected_milestones = array();
            	
            	foreach ($to_move as $moved) {
            		$milestone_ids[] = $moved->getId();
            	} // foreach
            		
            	$to_move = Milestones::findByIds($milestone_ids, STATE_VISIBLE, $this->logged_user->getMinVisibility());
            	if (is_foreachable($to_move)) {
            		foreach ($to_move as $affected_milestone) {
  								$described_milestone['affected_milestones'][] = $affected_milestone->describe($this->logged_user, true, true);
            		} // foreach
            	} // if
            } // if
            
            if ($this->request->isPageCall()) {
              $this->response->redirectToUrl($this->active_object->getViewUrl());
            } else {
              $this->response->respondWithData($described_milestone);
            } // if
          } catch(Exception $e) {
            DB::rollback('Failed to reschedule a milestone @ ' . __CLASS__);
            $this->response->exception($e);
          } // try
        } // if
		  } else {
		    $this->response->forbidden();
		  } // if
		} // reschedule		
		
	}