<?php
/*

$ed[$trainingWeek] = round( ( $output * $maintenance ) / $sport['Sport']['round_at']) * $sport['Sport']['round_at'];
$roundUp = ceil( ( $ed[$trainingWeek-1] * $modifier['Modifier']['up'] ) / $sport['Sport']['round_at']) * $sport['Sport']['round_at'];
$roundDown = floor( ( $ed[$trainingWeek-1] * $modifier['Modifier']['down'] ) / $sport['Sport']['round_at']) * $sport['Sport']['round_at'];
*/
App::uses('ModelBehavior', 'Model');

class AdjustmentBehavior extends ModelBehavior
{
	public $shapes = array(
		0 => 'burned-out',
		25 => 'exhausted',
		50 => 'tired',
		75 => 'fatigued',
		100 => 'top-shape',
	);

  protected $_complete = 0.90;

  protected $_var1 = array(
    0 => 0.40,
    25 => 0.35,
    50 => 0.30,
    75 => 0.25,
    100 => 0.20,
  );

  protected $_var2 = array(
    0 => 0.60,
    25 => 0.70,
    50 => 0.80,
    75 => 0.90,
    100 => 1.00,
  );

  protected $_var3 = 0.60;

  protected $_var4 = 2.20;

	public function setup(Model $Model, $settings = array())
	{
		$this->shapeLabels = array(
			0 => __('Burned Out'),
			25 => __('Exhausted'),
			50 => __('Tired'),
			75 => __('Fatigued'),
			100 => __('Top Shape'),
		);
	}

  public function shape2Value(Model $Model, $ajaxShapeString)
  {
    foreach($this->shapes as $shape => $shapeString)
    {
      if($shapeString === $ajaxShapeString) {
        return $shape;
      }
    }

    return $ajaxShapeString;
  }

	protected function _getIndex(Model $Model, $trigger)
	{
		$date = new DateTime($trigger['Workout']['date']);
		$dateStart = clone $date;
		$dateEnd = clone $date;

		if ($dateStart->format('D') !== 'Mon') {
			$dateStart->modify('last monday');
		}

		if ($dateEnd->format('D') !== 'Sun') {
			$dateEnd->modify('next Sunday');
		}

		$workouts = $Model->find('all', array(
			'conditions' => array(
				'Workout.program_id' => $trigger['Workout']['program_id'],
				'Workout.zone_id' => $trigger['Workout']['zone_id'],
				'Workout.sport_id' => $trigger['Workout']['sport_id'],
				array('Workout.date >= ' => $dateStart->format('Y-m-d'), 'Workout.date <= ' => $dateEnd->format('Y-m-d')),
			),
			'order' => array('Workout.date' => 'asc'),
		));

		if(!empty($workouts)) {
			foreach($workouts as $key => $workout) {
				if($workout['Workout']['date'] === $trigger['Workout']['date']) {
					return $key;
				}
			}
		}

		return false;
	}

	public function adjust(Model $Model, $trigger)
	{
		$workouts = $Model->find('all', array(
			'conditions' => array(
					'Workout.program_id' => $trigger['Workout']['program_id'],
					'Workout.zone_id' => $trigger['Workout']['zone_id'],
					'Workout.sport_id' => $trigger['Workout']['sport_id'],
			),
            'contain' => array(
                'Program',
            ),
			'order' => array(
				'Workout.date' => 'asc',
			),
		));

		$this->_updateScheda($Model, $trigger);

		$sorted = array();
		foreach ($workouts as $key => $workout) {
			$trainingweek = $this->_getTrainingweek($Model, $workout);
			if (!isset($sorted[$trainingweek])) {
				$sorted[$trainingweek] = array();
			}

			array_push($sorted[$trainingweek], $workout['Workout']);

		}

		$index = $this->_getIndex($Model, $trigger);

		#return $trigger;
		return $this->_calculateAdjust($Model, $trigger, $sorted, $index);
	}

	public function getScheda(Model $Model, $workout, $schedaType)
	{
		$conditions = array(
			'Workout.program_id' => $workout['Workout']['program_id'],
		);

		if ($schedaType == 'hide') {
			$conditions['or'] = array(
				array('Workout.scheda' => 25),
				array('Workout.scheda' => 100),
			);
		} elseif ($schedaType == 'as') {
			$conditions['or'] = array(
				array('Workout.scheda' => 1),
				array('Zone.value' => 'speed'),
				array('Zone.value' => 'tempo'),
			);
		} else {
			return false;
		}

		$workouts = $Model->find('all', array(
			'conditions' => $conditions,
			'contain' => array(
				'Zone',
			),
			'fields' => array(
				'Workout.id',
				'Workout.scheda',
				'Zone.name',
			),
		));

		if($schedaType == 'as') {
			$zone = $Model->Zone->find('first', array(
				'conditions' => array(
					'Zone.value' => 'aerobic_stimulation'
				)
			));
			foreach ($workouts as $key => $workout) {
				if($workout['Workout']['scheda'] == 1) {
					$workouts[$key]['Zone']['id'] = $zone['Zone']['id'];
					$workouts[$key]['Zone']['name'] = $zone['Zone']['name'];
				}
			}
		}

		return $workouts;
	}

	protected function _updateScheda(Model $Model, $trigger)
	{
		$Model->updateAll(array(
			'Workout.scheda' => null
		), array(
			'Workout.program_id' => $trigger['Workout']['program_id'],
		));

		$workouts = $Model->find('all', array(
			'conditions' => array(
				'Workout.program_id' => $trigger['Workout']['program_id'],
			),
			'contain' => array(
				'Zone',
			),
			'fields' => array(
				'Workout.id',
				'Workout.shape',
				'Workout.adjustment',
				'Workout.date',
				'Zone.id',
				'Zone.value',
			),
			'order' => array('Workout.date' => 'asc'),
		));


		foreach ($workouts as $key => $workout) {
			if (in_array($workout['Zone']['value'], array('speed', 'tempo', 'aerobic_stimulation'))) {
				$this->log($workouts);
			}
			if (!is_null($workout['Workout']['shape'])) {
				if(in_array($workout['Zone']['value'], array('endurance_development', 'aerobic_development', 'recovery'))) {
					if ($workout['Workout']['shape'] == 25) {
						$workouts[$key]['Workout']['schedule_length'] = 1;
						$workouts[$key]['Workout']['schedule_effect'] = 25;
					}
					elseif ($workout['Workout']['shape'] == 0) {
						$workouts[$key]['Workout']['schedule_length'] = 2;
						$workouts[$key]['Workout']['schedule_effect'] = 100;
					}
				} elseif (in_array($workout['Zone']['value'], array('speed', 'tempo', 'aerobic_stimulation'))) {
					if ($workout['Workout']['shape'] == 50) {
						$workouts[$key]['Workout']['schedule_length'] = 1;
						$workouts[$key]['Workout']['schedule_effect'] = 1;
					}
					elseif ($workout['Workout']['shape'] == 25) {
						$workouts[$key]['Workout']['schedule_length'] = 2;
						$workouts[$key]['Workout']['schedule_effect'] = 1;
					}
					elseif ($workout['Workout']['shape'] == 0) {
						$workouts[$key]['Workout']['schedule_length'] = 3;
						$workouts[$key]['Workout']['schedule_effect'] = 1;
					}
				}
			}
		}

		$scheduleWorkouts = array();

		foreach ($workouts as $key => $workout) {
			if (isset($workout['Workout']['schedule_length'])) {
				for ($schedule = 1; $schedule <= $workout['Workout']['schedule_length']; $schedule++) {
					$date = new DateTime($workout['Workout']['date']);
					$date->modify('+' . $schedule . ' day');

					foreach ($workouts as $keyDateCheck => $workoutDateCheck) {
						if($workoutDateCheck['Workout']['date'] == $date->format('Y-m-d')) {
							if($workout['Workout']['schedule_effect'] == 1 && in_array($workouts[$keyDateCheck]['Zone']['value'], array('tempo', 'speed'))) {
								//$this->log($workouts[$keyDateCheck]['Zone']['value']);
								$workouts[$keyDateCheck]['Workout']['scheda'] = $workout['Workout']['schedule_effect'];
								array_push($scheduleWorkouts, $workouts[$keyDateCheck]['Workout']);
							} elseif (in_array($workout['Workout']['schedule_effect'], array(25, 100))) {
								$workouts[$keyDateCheck]['Workout']['scheda'] = $workout['Workout']['schedule_effect'];
								array_push($scheduleWorkouts, $workouts[$keyDateCheck]['Workout']);
							}
						}
					}
				}
			}
		}

		$Model->saveAll($scheduleWorkouts);
	}

	protected function _calculateAdjust(Model $Model, $trigger, $sorted, $index)
	{
		$data = array();

		foreach ($sorted as $trainingweek => $workouts) {
			if (isset($workouts[$index]) && $trainingweek >= 2 && $trainingweek <= $trigger['Program']['training_length'] - 2) {

				#$this->log($index . 'giraffe');
				$workout = $workouts[$index];

				#need to ask tris about this
				$lastWorkout = $workout;
				if (isset($sorted[$trainingweek - 1][$index])) {
					$lastWorkout = $sorted[$trainingweek - 1][$index];
				}

				$roundAt = $trigger['Sport']['round_at'];

				if ($trainingweek === 2) {
					array_push($data, $this->_secondWeek($Model, $workout, $lastWorkout, $roundAt));
					#$sorted[$trainingweek][$index]['adjustment'] = $this->_secondWeek($Model, $workout, $lastWorkout, $roundAt);
				} else {
					array_push($data, $this->_nextWeeks($Model, $workout, $lastWorkout, $roundAt));
					#$sorted[$trainingweek][$index]['adjustment'] = $this->_nextWeeks($Model, $workout, $lastWorkout, $roundAt);
				}
			}
		}

		return $data;
	}

  protected function _secondWeek(Model $Model, $workout, $lastWorkout, $roundAt)
  {
		$lastComplete = $this->_checkComplete($lastWorkout);
		$lastShape = $this->_checkShape($lastWorkout);

    $var1 = $this->_var1[$lastShape] - $this->_var1[$lastShape] * ($lastComplete / 100);

		$workout['adjustment'] = round((($workout['value'] - $workout['value'] * $var1) * $this->_var2[$lastShape]) / $roundAt) * $roundAt;
    return $workout;
  }

  protected function _nextWeeks(Model $Model, $workout, $lastWorkout, $roundAt)
  {
		$lastComplete = $this->_checkComplete($lastWorkout);
		$lastShape = $this->_checkShape($lastWorkout);

    $var1 = $this->_var1[$lastShape] - $this->_var1[$lastShape] * ($lastComplete / 100);
		$safevar = $this->_safeguard($Model, $workout, $lastWorkout);
    $safeguard = $safevar - ($safevar * $var1);

		$workout['adjustment'] = round($safeguard * $this->_var2[$lastShape] / $roundAt) * $roundAt;
		return $workout;
  }

	protected function _checkComplete($lastWorkout)
	{
		$zoneIds = array(1, 2, 3); //'re, ad, ed'

		if(in_array($lastWorkout['zone_id'], $zoneIds) && isset($lastWorkout['scheda']) &&  $lastWorkout['scheda'] == 1) {
			$this->log($lastWorkout);
		}
		if(!isset($lastWorkout['complete'])) {
				return 100;
		}

		return $lastWorkout['complete'];
	}

	protected function _checkShape($lastWorkout)
	{
		if(!isset($lastWorkout['shape'])) {
				return 100;
		}

		return $lastWorkout['shape'];
	}

  protected function _safeguard(Model $Model, $workout, $lastWorkout)
  {
    if(($workout['value'] * $this->_var3) < $lastWorkout['adjustment']) {
      return $workout['value'];
    }

    return ($lastWorkout['adjustment'] + $workout['value']) / $this->_var4;
  }

	public function _getTrainingweek(Model $Model, $workout)
	{
		$date = new DateTime($workout['Workout']['date']);

		$training = new DateTime($workout['Program']['training']);
		$race = new DateTime($workout['Program']['race']);

		if($training <= $date && $race > $date)
		{
			$weekStart = clone $training;
			$weekEnd = clone $training; $weekEnd->modify( '+1 week' );

			for ($index = 1; $index <= $workout['Program']['training_length']; $index++)
			{
				if($weekStart <= $date && $weekEnd > $date)
				{
					return $index;
				}
				else
				{
					$weekStart->modify( '+1 week' );
					$weekEnd->modify( '+1 week' );
				}
			}
		}

		return false;
	}
}
?>
