<?php

declare(strict_types=1);

namespace App\Presenters;

use Nette;
use Exception;

define("COURSE_DATA_TRANSFER", array(
	'ID' => 'ID',
	'trida' => 'class',
	'datum_zacatku' => 'dateStart',
	'datum_konce' => 'dateEnd',
	'informace' => 'information',
	'ID_tema_kurzu' => 'themeId',
	'ID_skoly' => 'schoolId',
	'stav' => 'state',
	'zapis' => 'report'
));

define("COURSE_INSTRUCTOR_DATA_TRANSFER", array(
	'ID_osoby' => 'instructorId',
	'cislo_role' => 'roleId',
	'stav' => 'state'
));

define("QUESTIONNAIRE_DATA_TRANSFER", array(
	'ID_kurzu' => 'courseId',
	'cas_prijezdu' => 'arrivalTime',
	'cas_odjezdu' => 'departureTime',
	'pocet_muzu' => 'maleCount',
	'pocet_zen' => 'femaleCount',
	'pocet_dopr_muzu' => 'maleTeachers',
	'pocet_dopr_zen' => 'femaleTeachers',
	'osoba_jmeno' => 'personName',
	'osoba_email' => 'personEmail',
	'osoba_telefon' => 'personPhone',
	'ocekavani' => 'expectations',
	'aktualni_situace' => 'actualSituation',
	'specificka_strava' => 'specificDiet',
	'svaciny' => 'snacks',
	'jine_kurzy' => 'otherCourses',
	'dalsi_informace' => 'otherInformation',
	'cas_vyplneni' => 'filledAt',
	'cas_zmeny' => 'changedAt',
	'souhlas_ou' => 'agreement'
));

define("EVALUATION_DATA_TRANSFER", array(
	'ID' => 'ID',
	'ID_hodnotitele' => 'evaluatorId',
	'ID_hodnoceneho' => 'evaluatedId',
	'ID_kurzu' => 'courseId',
	'popis' => 'description',
));

final class CoursePresenter extends BasePresenter
{
    public function renderDefault() {

    }

	public function actionCreateCourse(): void
	{
		$this->checkUserAccess('zamestnanec', false);
		$httpRequest = $this->getHttpRequest();
		$body = $httpRequest->getRawBody();
		$json = json_decode($body);	
		$data = $this->applyTransfer($json, COURSE_DATA_TRANSFER, TRANSFER_TO_DB, DATA_OBJECT);
		$result = $this->courseManager->createCourse($data);

		if(!$result) {
			$this->error('data se nepovedlo ulozit', Nette\Http\Response::S500_INTERNAL_SERVER_ERROR);
		}

		$json = $this->applyTransfer($result, COURSE_DATA_TRANSFER, TRANSFER_TO_JSON, DATA_OBJECT);
		$json = $this->addInstructors($json, DATA_SINGLE_ROW);
		$json = $this->addQuestionnaires($json, DATA_SINGLE_ROW);
		$this->sendJson($json);
	}

	public function actionUpdateCourse(): void
	{
		$this->checkUserAccess('zamestnanec', false);
		$httpRequest = $this->getHttpRequest();
		$body = $httpRequest->getRawBody();
		$json = json_decode($body);	
		$data = $this->applyTransfer($json, COURSE_DATA_TRANSFER, TRANSFER_TO_DB, DATA_OBJECT);

		try {
			$result = $this->courseManager->updateCourse($data);
		} catch (Exception $e) {
			$this->error('data se nepovedlo ulozit', Nette\Http\Response::S500_INTERNAL_SERVER_ERROR);
		}

		$data = $this->courseManager->getCourseById($json->ID);
		if($data != null) {
			$json = $this->applyTransfer($data, COURSE_DATA_TRANSFER, TRANSFER_TO_JSON, DATA_OBJECT);
			$json = $this->addInstructors($json, DATA_SINGLE_ROW);
			$json = $this->addQuestionnaires($json, DATA_SINGLE_ROW);
			$this->sendJson($json);
		}
		$this->error('pozadovana data se nepovedlo nacist', Nette\Http\Response::S500_INTERNAL_SERVER_ERROR);	
	}

	public function actionChangeCourseState(): void
	{
		$this->checkUserAccess('zamestnanec', false);
		$httpRequest = $this->getHttpRequest();
		$body = $httpRequest->getRawBody();
		$json = json_decode($body);
		$courseId = $httpRequest->getQuery('courseId');	
		if($courseId) {		
			$data = array('ID' => $courseId, 'stav' => $json->newState);
			try {
				$result = $this->courseManager->updateCourse($data);
			} catch (Exception $e) {
				$this->error('data se nepovedlo ulozit', Nette\Http\Response::S500_INTERNAL_SERVER_ERROR);
			}
			$data = $this->courseManager->getCourseById($courseId);
			if($data != null) {
				$json = $this->applyTransfer($data, COURSE_DATA_TRANSFER, TRANSFER_TO_JSON, DATA_OBJECT);
				$json = $this->addInstructors($json, DATA_SINGLE_ROW);
				$json = $this->addQuestionnaires($json, DATA_SINGLE_ROW);
				$this->sendJson($json);
			}
			$this->error('pozadovana data se nepovedlo nacist', Nette\Http\Response::S500_INTERNAL_SERVER_ERROR);	
		} else {
			$this->error('nebyl vlozen parametr id', Nette\Http\Response::S400_BAD_REQUEST);
		}
	}

	public function actionEnlistNewCourse(): void
	{
		$this->checkUserAccess('zadna-osoba', true);
		$httpRequest = $this->getHttpRequest();
		$body = $httpRequest->getRawBody();
		$json = json_decode($body);	
		$data = $this->applyTransfer($json, COURSE_DATA_TRANSFER, TRANSFER_TO_DB, DATA_OBJECT);
		$data['stav'] = 'zadost';
		$result = $this->courseManager->createCourse($data);
		if(!$result) {
			$this->error('data se nepovedlo ulozit', Nette\Http\Response::S500_INTERNAL_SERVER_ERROR);
		}
		$json = $this->applyTransfer($result, COURSE_DATA_TRANSFER, TRANSFER_TO_JSON, DATA_OBJECT);
		$this->sendJson($json);	
	}

	public function actionEnlistModifiedCourse(): void
	{
		$this->checkUserAccess('zadna-osoba', true);
		$httpRequest = $this->getHttpRequest();
		$body = $httpRequest->getRawBody();
		$json = json_decode($body);	
		$data = $this->applyTransfer($json, COURSE_DATA_TRANSFER, TRANSFER_TO_DB, DATA_OBJECT);
		$data['stav'] = 'zadost';
		try {
			$result = $this->courseManager->updateCourse($data);
		} catch (Exception $e) {
			$this->error('data se nepovedlo ulozit', Nette\Http\Response::S500_INTERNAL_SERVER_ERROR);
		}
		$data = $this->courseManager->getCourseById($json->ID);
		$json = $this->applyTransfer($data, COURSE_DATA_TRANSFER, TRANSFER_TO_JSON, DATA_OBJECT);
		$this->sendJson($json);	
	}

	public function actionUpdateCourseInstructors(): void
	{
		$this->checkUserAccess('zamestnanec', false);
		$httpRequest = $this->getHttpRequest();
		$courseId = $httpRequest->getQuery('courseId');
		$roleId = $httpRequest->getQuery('roleId');
		if($courseId && $roleId) {		
			$body = $httpRequest->getRawBody();
			$json = json_decode($body, true);	
			$data = $this->applyTransfer($json, COURSE_INSTRUCTOR_DATA_TRANSFER, TRANSFER_TO_DB);
			$this->saveLog('osoba_kurz', 'uprava', array('ID_ kurzu' => $courseId, 'role' => $roleId, 'instruktori' => $data));
			$result = $this->courseManager->updateCourseInstructors($courseId, $roleId, $data);
			if($result != null) {
				$this->sendJson(array());
			} else {
				$this->error('data se nepovedlo ulozit', Nette\Http\Response::S500_INTERNAL_SERVER_ERROR);
			}
		} else {
			$this->error('nebyl vlozen parametr id', Nette\Http\Response::S400_BAD_REQUEST);
		}	
	}

	public function actionSaveInterest(): void
	{
		$this->checkUserAccess('instruktor');
		$httpRequest = $this->getHttpRequest();
		$body = $httpRequest->getRawBody();
		$json = json_decode($body);
		if($this->userInfo->max_role != 0 && $this->userInfo->max_role <= $json->role) {
			$data = array('ID_kurzu' => $json->courseId, 'ID_osoby' => $this->userInfo->ID, 'cislo_role' => $json->role);
			if(in_array($this->userInfo->opravneni, array('zamestnanec', 'administrator'))) {
				$data['stav'] = 'aktivni';
			} else {
				$data['stav'] = 'zadost';
			}
			$this->saveLog('osoba_kurz', 'uprava', $data);
			$result = $this->courseManager->addCourseInstructor($data);
			$this->sendJson(array());
		} else {
			$this->error('nedostatecna opravneni pro tuto roli', Nette\Http\Response::S403_FORBIDDEN);
		}
		$this->sendJson(array());	
	}

	public function actionRemoveInterest(): void
	{
		$this->checkUserAccess('instruktor');
		if($this->getUser()->isLoggedIn()) {
			$httpRequest = $this->getHttpRequest();
			$courseId = $httpRequest->getQuery('courseId');
			if($courseId) {
				$this->saveLog('osoba_kurz', 'smazani', array('ID_kurzu' => $courseId));
				$result = $this->courseManager->removeCourseInstructor($courseId, $this->getUser()->getId());
				$this->sendJson(array());
			} else {
				$this->error('nebyl vlozen parametr id', Nette\Http\Response::S400_BAD_REQUEST);
			}
		} else {
			$this->error('uzivatel neni prihlasen', Nette\Http\Response::S403_FORBIDDEN);
		}
	}

	public function actionCreateQuestionnaire(): void
	{
		$this->checkUserAccess('zamestnanec', true);
		$httpRequest = $this->getHttpRequest();
		$body = $httpRequest->getRawBody();
		$json = json_decode($body);	
		$data = $this->applyTransfer($json, QUESTIONNAIRE_DATA_TRANSFER, TRANSFER_TO_DB, DATA_OBJECT);
		$this->saveLog('dotazniky', 'vlozeni', $data);
		$result = $this->courseManager->createQuestionnaire($data);
		if(!$result) {
			$this->error('data se nepovedlo ulozit', Nette\Http\Response::S500_INTERNAL_SERVER_ERROR);
		}
		$questionnaire = $this->applyTransfer($result, QUESTIONNAIRE_DATA_TRANSFER, TRANSFER_TO_JSON, DATA_OBJECT);
		$course = $this->courseManager->getCourseById($result->ID_kurzu);
		$json = $this->applyTransfer($course, COURSE_DATA_TRANSFER, TRANSFER_TO_JSON, DATA_OBJECT);
		$json['questionnaire'] = $questionnaire;
		$this->sendJson($json);	
	}

	public function actionUpdateQuestionnaire(): void
	{
		$this->checkUserAccess('zamestnanec', true);
		$httpRequest = $this->getHttpRequest();
		$body = $httpRequest->getRawBody();
		$json = json_decode($body);	
		$data = $this->applyTransfer($json, QUESTIONNAIRE_DATA_TRANSFER, TRANSFER_TO_DB, DATA_OBJECT);
		$this->saveLog('dotazniky', 'uprava', $data);
		$result = $this->courseManager->updateQuestionnaire($data);
		if(!$result) {
			$this->error('data se nepovedlo ulozit', Nette\Http\Response::S500_INTERNAL_SERVER_ERROR);
		}
		$course = $this->courseManager->getCourseById($data['ID_kurzu']);
		$json = $this->applyTransfer($course, COURSE_DATA_TRANSFER, TRANSFER_TO_JSON, DATA_OBJECT);
		$json = $this->addQuestionnaires($json, DATA_SINGLE_ROW);	
		$this->sendJson($json);
	}

	public function actionCreateInstructorEvaluation(): void
	{
		$this->checkUserAccess('instruktor');
		$httpRequest = $this->getHttpRequest();
		$body = $httpRequest->getRawBody();
		$json = json_decode($body);	
		$data = $this->applyTransfer($json, EVALUATION_DATA_TRANSFER, TRANSFER_TO_DB, DATA_OBJECT);
		$this->saveLog('hodnoceni', 'vlozeni', $data);
		$result = $this->courseManager->createInstructorEvaluation($data);
		if(!$result) {
			$this->error('data se nepovedlo ulozit', Nette\Http\Response::S500_INTERNAL_SERVER_ERROR);
		}
		$data = $this->courseManager->getCourseById($data['ID_kurzu']);
		if($data != null) {
			$json = $this->applyTransfer($data, COURSE_DATA_TRANSFER, TRANSFER_TO_JSON, DATA_OBJECT);
			$json = $this->addInstructors($json, DATA_SINGLE_ROW);
			$json = $this->addQuestionnaires($json, DATA_SINGLE_ROW);
			$this->sendJson($json);
		}
		$this->error('pozadovana data se nepovedlo nacist', Nette\Http\Response::S500_INTERNAL_SERVER_ERROR);
	}

	public function actionUpdateInstructorEvaluation(): void
	{
		$this->checkUserAccess('instruktor');
		$httpRequest = $this->getHttpRequest();
		$body = $httpRequest->getRawBody();
		$json = json_decode($body);	
		$data = $this->applyTransfer($json, EVALUATION_DATA_TRANSFER, TRANSFER_TO_DB, DATA_OBJECT);
		$this->saveLog('hodnoceni', 'uprava', $data);
		try {
			$result = $this->courseManager->updateInstructorEvaluation($data);
		} catch (Exception $e) {
			$this->error('data se nepovedlo ulozit', Nette\Http\Response::S500_INTERNAL_SERVER_ERROR);
		}
		$data = $this->courseManager->getCourseById($data['ID_kurzu']);
		if($data != null) {
			$json = $this->applyTransfer($data, COURSE_DATA_TRANSFER, TRANSFER_TO_JSON, DATA_OBJECT);
			$json = $this->addInstructors($json, DATA_SINGLE_ROW);
			$json = $this->addQuestionnaires($json, DATA_SINGLE_ROW);
			$this->sendJson($json);
		}
		$this->error('pozadovana data se nepovedlo nacist', Nette\Http\Response::S500_INTERNAL_SERVER_ERROR);
	}

	public function actionUpdateCourseReport(): void
	{
		$this->checkUserAccess('instruktor', false);
		$httpRequest = $this->getHttpRequest();
		$body = $httpRequest->getRawBody();
		$courseId = $httpRequest->getQuery('courseId');
		if($courseId) {		
			$json = json_decode($body, true);	
			if(isset($json['reportText'])) {	
				try {
					$result = $this->courseManager->updateCourseReport($courseId, $json['reportText']);
				} catch (Exception $e) {
					$this->error('data se nepovedlo ulozit', Nette\Http\Response::S500_INTERNAL_SERVER_ERROR);
				}
	
				$data = $this->courseManager->getCourseById($courseId);
				if($data != null) {
					$json = $this->applyTransfer($data, COURSE_DATA_TRANSFER, TRANSFER_TO_JSON, DATA_OBJECT);
					$json = $this->addInstructors($json, DATA_SINGLE_ROW);
					$json = $this->addQuestionnaires($json, DATA_SINGLE_ROW);
					$this->sendJson($json);
				}
				$this->error('pozadovana data se nepovedlo nacist', Nette\Http\Response::S500_INTERNAL_SERVER_ERROR);
			} else {
				$this->error('neplatna struktura pozadavku', Nette\Http\Response::S400_BAD_REQUEST);
			}
		} else {
			$this->error('nebyl vlozen parametr id', Nette\Http\Response::S400_BAD_REQUEST);
		}
	}

	public function actionGetById(): void
	{
		$this->checkUserAccess('instruktor', true);
		$httpRequest = $this->getHttpRequest();
		$id = $httpRequest->getQuery('courseId');
		if($id) {
			$data = $this->courseManager->getCourseById($id);
			if($data != null) {
				$json = $this->applyTransfer($data, COURSE_DATA_TRANSFER, TRANSFER_TO_JSON, DATA_OBJECT);
				$json = $this->addInstructors($json, DATA_SINGLE_ROW);
				$json = $this->addQuestionnaires($json, DATA_SINGLE_ROW);
				$this->sendJson($json);
			}
			$this->error('pozadovana data se nepovedlo nacist', Nette\Http\Response::S500_INTERNAL_SERVER_ERROR);
		} else {
			$this->error('nebyl vlozen parametr id', Nette\Http\Response::S400_BAD_REQUEST);
		}
	}

	public function actionGetActualYearCourses(): void
	{
		$this->checkUserAccess('instruktor');
		$schoolyearTimespan = $this->getActualSchoolyear();
		$data = $this->courseManager->getCoursesByTimespan($schoolyearTimespan['from'], $schoolyearTimespan['to']);
		$json = $this->applyTransfer($data, COURSE_DATA_TRANSFER, TRANSFER_TO_JSON);
		$json = $this->addInstructors($json);
		$json = $this->addQuestionnaires($json);
		$this->sendJson($json);	
	}

	public function actionGetRequestedCourses(): void
	{
		$this->checkUserAccess('zamestnanec');
		$dataRequested = $this->courseManager->getCoursesByState('zadost');
		$dataDenied = $this->courseManager->getCoursesByState('zamitnuty');
		$jsonRequested = $this->applyTransfer($dataRequested, COURSE_DATA_TRANSFER, TRANSFER_TO_JSON);
		$jsonDenied = $this->applyTransfer($dataDenied, COURSE_DATA_TRANSFER, TRANSFER_TO_JSON);
		$json = array_merge($jsonRequested, $jsonDenied);
		$json = $this->addInstructors($json);
		$json = $this->addQuestionnaires($json);
		$this->sendJson($json);	
	}

	public function actionGetMyCourses(): void
	{
		$this->checkUserAccess('instruktor');
		$data = $this->courseManager->getCoursesByInstructor($this->getUser()->getId());
		$json = $this->applyTransfer($data, COURSE_DATA_TRANSFER, TRANSFER_TO_JSON);
		$json = $this->addInstructors($json);
		$json = $this->addQuestionnaires($json);
		$this->sendJson($json);	
	}

	public function actionGetSchoolCourses(): void
	{
		$this->checkUserAccess('zadna-osoba', true);
		$data = $this->courseManager->getCoursesBySchool($this->getUser()->getId());
		$json = $this->applyTransfer($data, COURSE_DATA_TRANSFER, TRANSFER_TO_JSON);
		foreach ($json as $key => $course) {
			$result[$key]['instructors'] = array();
		}
		$json = $this->addQuestionnaires($json);
		$this->sendJson($json);	
	}

	public function actionGetInstructorCourses(): void
	{
		$this->checkUserAccess('zamestnanec');
		$httpRequest = $this->getHttpRequest();
		$id = $httpRequest->getQuery('personId');
		if($id) {
			$data = $this->courseManager->getCoursesByInstructor($id);
			$json = $this->applyTransfer($data, COURSE_DATA_TRANSFER, TRANSFER_TO_JSON);
			$json = $this->addInstructors($json);
			$json = $this->addQuestionnaires($json);
			$this->sendJson($json);	
		} else {
			$this->error('nebyl vlozen parametr id', Nette\Http\Response::S400_BAD_REQUEST);
		}
	}

	public function getInstructorsForCourse($courseId) {
		$instructors = $this->courseManager->getCourseInstructors($courseId);
		$result = array();
		foreach ($instructors as $connection) {
			$instructor = $connection->ref('osoby', 'ID_osoby');
			// hodnoceni instruktora
			$evaluationRow = $this->evaluationManager->getByPersonIdCourseId($connection->ID_osoby, $courseId);
			$evaluation = null;
			if($evaluationRow != null) {
				$evaluation = array(
					'evaluatorId' => $evaluationRow->ID_hodnotitele,
					'description' => $evaluationRow->popis
				);
			}
			// kompletni informace o instruktorovi
			$result[] = array(
				'instructorId' => $connection->ID_osoby,
				'roleId' => $connection->cislo_role, 
				'instructorName' => $instructor->jmeno . ' ' . $instructor->prijmeni,
				'state' => $connection->stav,
				'evaluation' => $evaluation
			);
		}
		return $result;
	}

	public function addInstructors($courses, $dataType = DATA_MULTIPLE_ROWS)
    {   
		if($dataType == DATA_OBJECT) {
			$result = $courses;
			$result->instructors = $this->getInstructorsForCourse($courses->ID);
			return $result;
		}

		$result = $courses;
		if($dataType == DATA_SINGLE_ROW) {
			$result = array($courses);
		}
		foreach ($result as $key => $course) {
			$result[$key]['instructors'] = $this->getInstructorsForCourse($course['ID']);
		}
		if($dataType == DATA_SINGLE_ROW) {
			return $result[0];
		}
        return $result;
    }

	public function getQuestionnaireForCourse($courseId) {
		$questionnaire = $this->courseManager->getCourseQuestionnaire($courseId);
		if($questionnaire == null) {
			$result = null;	
		} else {
			$result = $this->applyTransfer($questionnaire, QUESTIONNAIRE_DATA_TRANSFER, TRANSFER_TO_JSON, DATA_OBJECT);
			$result['arrivalTime'] = $questionnaire->cas_prijezdu->format('%H:%I');
			$result['departureTime'] = $questionnaire->cas_odjezdu->format('%H:%I');
		}
		return $result;
	}

	public function addQuestionnaires($courses, $dataType = DATA_MULTIPLE_ROWS)
    {   
		if($dataType == DATA_OBJECT) {
			$result = $courses;
			$result->questionnaire = $this->getQuestionnaireForCourse($courses->ID);
			return $result;
		}

		$result = $courses;
		if($dataType == DATA_SINGLE_ROW) {
			$result = array($courses);
		}
		foreach ($result as $key => $course) {
			$result[$key]['questionnaire'] = $this->getQuestionnaireForCourse($course['ID']);
		}
		if($dataType == DATA_SINGLE_ROW) {
			return $result[0];
		}
        return $result;
    }
}
