<?php

class FiveYearPlansController extends \BaseController {

	/**
	 * Checks whether a user has permission to view a page in this controller
	 *
	 * @var User $user				Authenticated user
	 */
	private function userHasAccess($program_id)
	{
		$user = Auth::user();

		switch ($user->role) {
			case '3':
				$programs = $user->programs->lists('id');

				// If program does not belong to user, show 403
				if(!in_array($program_id, $programs))
					return false;

				break;

			case '2':
				$programs = Program::where('school_id', $user->school_id)->lists('id');

				// If program is not in user's school, show 403
				if(!in_array($program_id, $programs))
					return false;

				break;
			case '4':
				return false;
		}

		return true;
	}

	/**
	 * Page to create a new plan for the current quinquennium
	 * @var string $title			Title for page
	 * @var Program $programs	Collection of programs user has access to
	 * @var Outcome $outcomes      List of outcomes ordered by name
	 * @var User $user      Currently logged user
	 * @var Course $courses      Courses for a particular program
	 */
	public function create(Program $program)
	{
		$title = 'New Five Year Plan for '.$program->name;
		$user = Auth::user();
		$outcomes = Outcome::orderBy('name')->get();

		$current_quinquennium = Quinquennium::
			where('start_date', '<=', date('Y-m-d'))
			->where('end_date', '>=', date('Y-m-d'))
			->first();

		$courses = Course::
			select('id', 'code', 'number', 'name')
			->where('program_id', $program->id)
			->groupBy('name')
			->orderBy('code','ASC')
			->orderBy('number','ASC')
			->orderBy('name','ASC')
			->get();

		// Check if user can create a plan
		if(!$this->userHasAccess($program->id))
		{
			return View::make('global.403');
		}

		return View::make('local.managers.shared.create_five_year_plan', compact('title', 'program', 'current_quinquennium', 'outcomes', 'courses'));
	}

	/**
	 * Lists five year plans by quinquennium and program
	 * @var string $title			Title for page
	 * @var Program $programs	Collection of programs user has access to
	 * @var User $user				Authenticated user
	 */
	public function index()
	{
		$title = 'Five Year Plans';
		$user = Auth::user();
		$quinquenniums = Quinquennium::all();
		$current_quinquennium = Quinquennium::
			where('start_date', '<=', date('Y-m-d'))
			->where('end_date', '>=', date('Y-m-d'))
			->first();

		switch ($user->role) {
			case '1':
				$programs = Program::all();
				break;
			case '2':
				$programs = Program::where('school_id', $user->school_id)->get();
				break;
			case 3:
				$programs = $user->programs;
				break;
			default:
				App::abort('404');
				break;
		}

		return View::make('local.managers.shared.index_five_year_plans', compact('title', 'quinquenniums', 'programs', 'current_quinquennium'));
	}

	/**
	 * Processes and stores five year plan for a particular program
	 *
	 * @var array $input			JSON object containing new plan information
	 * @var FiveYearPlan $plan			Instance of newly created plan
	 * @var FypPart $mini_plan			Instance of limited annual plan belonging to five year plan
	 * @var string response			Encoded JSON string containing response for the browser
	 * @return string 			Encoded JSON string
	 */
	public function store()
	{
		header('Content-Type: application/json');

		$input = json_decode(Input::get('five_year_plan')); // Get plan as string

		DB::beginTransaction();

		try {

			// Create five year plan base structure
			$plan = FiveYearPlan::create(array(
					'program_id' => $input->program_id,
					'quinquennium_id' => $input->quinquennium_id,
				)
			);

			foreach ($input->mini_plans as $mini_plan_input) {

				$mini_plan_validator = Validator::make(
				    array(
				        'year_start' => $mini_plan_input->year_start,
						'year_end' => $mini_plan_input->year_end
				    ),
				    array(
				        'year_start' => 'required|integer|digits:4',
				        'year_end' => 'required|integer|digits:4'
				    )
				);

				/** If validation fails */
				if ($mini_plan_validator->fails())
				{
				    $response = array(
						'status' => 'danger',
					);
				}


				$mini_plan = FypPart::create(array(
						'five_year_plan_id' => $plan->id,
						'year_start' => $mini_plan_input->year_start,
						'year_end' => $mini_plan_input->year_end,
					)
				);

				foreach ($mini_plan_input->outcomes as $index => $outcome_input) {

					$outcomes_validator = Validator::make(
					    array(
					        'fyp_part_id'=> $mini_plan->id,
					        'outcome_id'=> $outcome_input->id,
					        'objectives'=> json_encode($outcome_input->objectives),
					        'courses'=> json_encode($outcome_input->courses),
					    ),
					    array(
					        'fyp_part_id'=> 'required|integer',
					        'outcome_id'=> 'required|integer',
					        'objectives'=> 'required',
					        'courses'=> 'required',
					    )
					);

					/** If validation fails */
					if ($outcomes_validator->fails())
					{
					    $response = array(
							'status' => 'danger',
						);
					}

					FypPartOutcome::create(array(
							'fyp_part_id'=> $mini_plan->id,
							'outcome_id'=> $outcome_input->id,
							'objectives'=> json_encode($outcome_input->objectives),
							'courses'=> json_encode($outcome_input->courses),
							'display_order'=> $index + 1,
						)
					);
				}
			}


			DB::commit();

			Session::flash('status', 'success');
			Session::flash('message', 'Five Year Plan created. You can review it below. Click the Edit button if you want to make any changes. To submit your plan, click the Submit button. Please note that submitted plans are final.');

			$response = array(
				'status' => 'success',
				'message' => $input->quinquennium_id,
				'redirect_url' => URL::action('FiveYearPlansController@show', array('program'=> $plan->program_id, 'five_year_plan'=> $plan->id))
			);

			echo json_encode($response);
			return;

		} catch (Exception $e) {

			DB::rollBack();

			$response = array(
				'status' => 'danger',
				'message' => $e->getMessage()
			);

			echo json_encode($response);

		}
	}


	/**
	 * Shows five year plan
	 *
	 * @param Program $program			Program to which the plan belongs to
	 * @param FiveYearPlan $plan			An instance of the Five Year Plan to show
	 * @var string $quinquennium_start_date		Year when the quinquennium starts
	 * @var string $quinquennium_end_date		Year when the quinquennium ends
	 * @var string title			Title of the page
	 * @var Program $programs			Logged user's program(s)
	 * @var Outcome $outcomes			List of all outcomes
	 */
	public function show(Program $program, FiveYearPlan $plan)
	{

		$outcomes = Outcome::orderBy('name')->get();

		$quinquennium_start_date = date('Y', strtotime($plan->quinquennium->start_date));
		$quinquennium_end_date = date('Y', strtotime($plan->quinquennium->end_date));

		$title = $quinquennium_start_date.'-'.$quinquennium_end_date.' Five Year Plan for '.$program->name;

		// Check if user can create a plan
		if(!$this->userHasAccess($program->id))
		{
			return View::make('global.403');
		}

		return View::make('local.managers.shared.show_five_year_plan', compact('title', 'program', 'plan', 'outcomes'));
	}

	/**
	 * Page to edit a plan for the current quinquennium
	 * @var string $title			Title for page
	 * @var Program $programs	Collection of programs user has access to
	 * @var User $user				Authenticated user
	 */
	public function edit(Program $program, FiveYearPlan $plan)
	{
		$title = 'Edit Five Year Plan for '.$program->name;
		$user = Auth::user();
		$outcomes = Outcome::orderBy('name')->get();

		$current_quinquennium = Quinquennium::
			where('start_date', '<=', date('Y-m-d'))
			->where('end_date', '>=', date('Y-m-d'))
			->first();

		$courses = Course::
			select('id', 'code', 'number', 'name')
			->where('program_id', $program->id)
			->groupBy('name')
			->orderBy('code','ASC')
			->orderBy('number','ASC')
			->orderBy('name','ASC')
			->get();

		// Check if user can create a plan
		if(!$this->userHasAccess($program->id))
		{
			return View::make('global.403');
		}

		return View::make('local.managers.shared.edit_five_year_plan', compact('title', 'program', 'current_quinquennium', 'outcomes', 'courses', 'plan'));
	}

	/**
	 * Processes and stores five year plan for a particular program
	 *
	 * @var array $input			JSON object containing new plan information
	 * @var FiveYearPlan $plan			Instance of newly created plan
	 * @var FypPart $mini_plan			Instance of limited annual plan belonging to five year plan
	 * @var string response			Encoded JSON string containing response for the browser
	 * @return string 			Encoded JSON string
	 */
	public function update()
	{
		if(Input::get('submit'))
		{

		}
		elseif(Input::get('revert'))
		{

		}
		else
		{
			header('Content-Type: application/json');

			$input = json_decode(Input::get('five_year_plan')); // Get plan as string

			DB::beginTransaction();

			try {

				$plan = FiveYearPlan::find($input->plan_id);
				$plan->updated_at = date('Y-m-d H:i:s');
				$plan->save();

				// Delete all annual (mini) plans and consequently, all their outcomes
				FypPart::where('five_year_plan_id', $plan->id)->delete();

				foreach ($input->mini_plans as $mini_plan_input) {

					$mini_plan_validator = Validator::make(
					    array(
					        'year_start' => $mini_plan_input->year_start,
							'year_end' => $mini_plan_input->year_end
					    ),
					    array(
					        'year_start' => 'required|integer|digits:4',
					        'year_end' => 'required|integer|digits:4'
					    )
					);

					/** If validation fails */
					if ($mini_plan_validator->fails())
					{
					    $response = array(
							'status' => 'danger',
						);
					}


					$mini_plan = FypPart::create(array(
							'five_year_plan_id' => $plan->id,
							'year_start' => $mini_plan_input->year_start,
							'year_end' => $mini_plan_input->year_end,
						)
					);

					foreach ($mini_plan_input->outcomes as $index => $outcome_input) {

						$outcomes_validator = Validator::make(
						    array(
						        'fyp_part_id'=> $mini_plan->id,
						        'outcome_id'=> $outcome_input->id,
						        'objectives'=> json_encode($outcome_input->objectives),
						        'courses'=> json_encode($outcome_input->courses),
						    ),
						    array(
						        'fyp_part_id'=> 'required|integer',
						        'outcome_id'=> 'required|integer',
						        'objectives'=> 'required',
						        'courses'=> 'required',
						    )
						);

						/** If validation fails */
						if ($outcomes_validator->fails())
						{
						    $response = array(
								'status' => 'danger',
							);
						}

						FypPartOutcome::create(array(
								'fyp_part_id'=> $mini_plan->id,
								'outcome_id'=> $outcome_input->id,
								'objectives'=> json_encode($outcome_input->objectives),
								'courses'=> json_encode($outcome_input->courses),
								'display_order'=> $index + 1,
							)
						);
					}
				}


				DB::commit();

				Session::flash('status', 'success');
				Session::flash('message', 'Five Year Plan updated.');

				$response = array(
					'status' => 'success',
					'message' => $input->quinquennium_id,
					'redirect_url' => URL::action('FiveYearPlansController@show', array('program'=> $plan->program_id, 'five_year_plan'=> $plan->id))
				);

				echo json_encode($response);
				return;

			} catch (Exception $e) {

				DB::rollBack();

				$response = array(
					'status' => 'danger',
					'message' => $e->getMessage().' '.$e->getLine()
				);

				echo json_encode($response);

			}
		}
	}


	public function msWord(FiveYearPlan $plan)
	{
		try {

			$filename = 'OLAS Five Year Plan for '.$plan->program->name.' ('.date('d-m-Y').').docx';
			require_once 'PHPWord-0.12.1/src/PhpWord/Autoloader.php';
			\PhpOffice\PhpWord\Autoloader::register();

			// Instantiate new document
			$phpWord = new \PhpOffice\PhpWord\PhpWord();

			// -----------------


			// $styleTable = array(
			// 	'borderColor'=>'006699',
			   //           	'borderSize'=>6,
			   //          	'cellMargin'=>50);
			// $styleFirstRow = array('bgColor'=>'DD0026');
			// $phpWord->addTableStyle('table', $styleTable, $styleFirstRow);

			/* Note: any element you append to a document must reside inside of a Section. */

			// // Adding an empty Section to the document...
			// $section = $phpWord->addSection();


			// $table = $section->addTable('table');
			// $table->addRow(3);
			// $table->addCell(3300)->addText("Col 1");
			// $table->addCell(3300)->addText("Col 2");
			// $table->addCell(3300)
			// ->addTable('table')
			// ->addRow(2)->addCell(3300)
			// ->addText("Col 1");

			// ----------------


			// Add new section. All elements must be inside a section
			$section_style = array(
			    'orientation' => 'landscape',
			    'lineNumbering' => array(
			    	'start' => 1
			    ),
			);
			$section = $phpWord->addSection($section_style);


			// Table styles
			$table_styles = $tableStyle = array(
			    'borderColor' => 'd0d0d0',
			    'borderSize'  => 6,
			    'cellMargin'  => 500
			);
			$header_styles = array(
				'bgColor' => 'FDFBE2',
				'valign' => 'center',
				'bold' => true,
			);

			$first_column_styles = array(
				'bgColor' => 'F5F5F5',
				'valign' => 'center',
				'bold' => true,
			);

			$rowspan_restart = array('vMerge' => 'restart');
			$rowspan_continue = array('vMerge' => 'continue');


			foreach($plan->fypParts as $number => $mini_plan)
			{
				$table = $section->addTable('table'.$number, $table_styles);

				// Header row
				$table->addRow(700, array('exactHeight'=>true));
				$table->addCell(3300, $header_styles)->addText("Academic Year");
				$table->addCell(3300, $header_styles)->addText("Learning Outcome to be assessed");
				$table->addCell(3300, $header_styles)->addText("Learning Objectives");
				$table->addCell(3300, $header_styles)->addText("Courses to use for assessment");

				// Body
				foreach($mini_plan->fypPartOutcomes as $index => $outcome)
				{
					$table->addRow();

					// If outcome is the first, include multi-row year column
					if($index == 0)
					{
						$table->addCell(3300, array_merge($first_column_styles, $rowspan_restart))->addText($mini_plan->year_start.'-'.$mini_plan->year_end);
					}
					else
					{
						$table->addCell(3300, array_merge($first_column_styles, $rowspan_continue))->addText('');
					}

					// Outcome name
					$table->addCell(3300)->addText($outcome->outcome->name);

					// Objectives
					$cell = $table->addCell(3300);

					foreach(json_decode($outcome->objectives) as $objective)
					{
						$cell->addText('• '.$objective->text);
					}

					// Courses
					$cell = $table->addCell(3300);

					foreach(json_decode($outcome->courses) as $course)
					{
						$cell->addText(trim('• '.$course->code.$course->number.': '.$course->name));
					}
				}

				$section->addTextBreak(2);
			}



			// Saving the document as OOXML file...
			$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007');


			$objWriter->save('exports/'.$filename);

			return Response::download('exports/'.$filename);

		}
		catch(Exception $e)
		{
			Session::flash('status', 'danger');
			Session::flash('message', 'An error occurred while generating the document. Try again later or contact an administrator.');

			return Redirect::back();
		}
	}

}
