<?php

declare(strict_types=1);

namespace App\Presenters;

use Nette;
use Exception;

use App\Model\AccountManager;
use App\Model\PersonManager;
use App\Model\CourseManager;
use App\Model\CourseThemeManager;
use App\Model\SchoolManager;
use App\Model\FreeScopesManager;
use App\Model\FundManager;
use App\Model\EvaluationManager;
use App\Model\LogManager;

use Nette\Application\UI\Form;

define("WWW_FOLDER", $_SERVER['SERVER_ADDR'] == '127.0.0.1' ? '' : '/www');

define("PASSWORD_HASH_OPTIONS", array( 'cost' => 9 ));
define("PASSWORD_HASH_ALGO", PASSWORD_DEFAULT);

define("TRANSFER_TO_DB", 1);
define("TRANSFER_TO_JSON", 2);

define("DATA_MULTIPLE_ROWS", 1);
define("DATA_SINGLE_ROW", 2);
define("DATA_OBJECT", 3);

define("INSTRUCTOR_COURSE_ROLES", array(
    1 => array('name' => 'Vedoucí', 'minRequired' => 1, 'maxAllowed' => 1),
    2 => array('name' => 'Instruktor', 'minRequired' => 1, 'maxAllowed' => 2),
    3 => array('name' => 'Nováček', 'minRequired' => 0, 'maxAllowed' => 2),
));

define("INSTRUCTOR_USER_ROLES", array('blokovany', 'cekatel', 'instruktor', 'zamestnanec', 'administrator', 'zadna-osoba'));

define("INSTRUCTOR_BASIC_DATA_TRANSFER", array(
	'ID' => 'ID',
	'email' => 'email',
	'jmeno' => 'firstname',
	'prijmeni' => 'lastname',
	'opravneni' => 'role',
	'max_role' => 'maxCourseRole',
	'datum_narozeni' => 'birthdate',
	'adresa_mesto' => 'addressCity',
	'adresa_ulice' => 'addressStreet',
	'adresa_psc' => 'addressZip',
	'telefon' => 'phone',
	'pohlavi' => 'gender',
	'poznamky' => 'notes',
    'souhlas_ou' => 'agreement'
));

define("SCHOOL_BASIC_DATA_TRANSFER", array(
	'ID' => 'ID',
	'email' => 'email',
	'nazev' => 'name',
	'osoba_jmeno' => 'personName',
	'osoba_email' => 'personEmail',
	'osoba_telefon' => 'personPhone',
	'adresa_ulice' => 'addressStreet',
	'adresa_mesto' => 'addressCity',
	'adresa_psc' => 'addressZip',
    'souhlas_ou' => 'agreement'
));

define("LOG_SETTINGS", array(
	'kurzy' => array('vlozeni', 'uprava', 'smazani'),
	'osoby' => array('vlozeni', 'uprava', 'smazani'),
	'skoly' => array('vlozeni', 'uprava', 'smazani'),
	'temata_kurzu' => array('vlozeni', 'uprava', 'smazani'),
	'osoba_kurz' => array('vlozeni', 'uprava', 'smazani'),
	'dotazniky' => array('vlozeni', 'uprava', 'smazani'),
	'fond' => array('vlozeni', 'uprava', 'smazani'),
	'hodnoceni' => array('vlozeni', 'uprava', 'smazani'),
));

abstract class BasePresenter extends Nette\Application\UI\Presenter
{

    protected AccountManager $accountManager;
    protected PersonManager $personManager;
    protected CourseManager $courseManager;
    protected CourseThemeManager $courseThemeManager;
    protected SchoolManager $schoolManager;
    protected FreeScopesManager $freeScopesManager;
    protected FundManager $fundManager;
    protected EvaluationManager $evaluationManager;
    protected LogManager $logManager;

    protected ?Nette\Database\Table\ActiveRow $userInfo;
    protected ?Nette\Database\Table\ActiveRow $schoolInfo;

	public function __construct(AccountManager $accountManager, PersonManager $personManager, CourseManager $courseManager, CourseThemeManager $courseThemeManager, SchoolManager $schoolManager, FreeScopesManager $freeScopesManager, FundManager $fundManager, EvaluationManager $evaluationManager, LogManager $logManager)
	{
        $this->accountManager = $accountManager;
        $this->personManager = $personManager;
        $this->courseManager = $courseManager;
        $this->courseThemeManager = $courseThemeManager;
        $this->schoolManager = $schoolManager;
        $this->freeScopesManager = $freeScopesManager;
        $this->fundManager = $fundManager;
        $this->evaluationManager = $evaluationManager;
        $this->logManager = $logManager;
    }
    
    public function beforeRender()
    {  
        $this->setUserInfo();
    }

    public function setUserInfo()
    {
        if(!isset($this->userInfo))
        {
            if($this->getUser()->isLoggedIn()){
                if($this->getUser()->isInRole('instructor')){
                    $this->userInfo = $this->personManager->getById($this->getUser()->getId());
                    $this->template->userInfo = $this->userInfo;
                }
                if($this->getUser()->isInRole('school')){
                    $this->schoolInfo = $this->schoolManager->getById($this->getUser()->getId());
                    $this->template->schoolInfo = $this->schoolInfo;
                }

                $this->template->user = $this->getUser();
                $this->template->identity = $this->template->user->getIdentity(); 
            } else {
                $this->userInfo = null;
            }
        }
    }

	public function handleLogout()
    {
        $this->getUser()->logout(true);
        $this->flashMessage("Uživatel byl odhlášen", 'success');
        $this->redirect('Homepage:default');
    }

    public function getActualSchoolyear()
    {
        $year = date('Y');
        $month = date('m');
        if($month < 9) {
            $year--;
        }
        $result = array('from' => $year.'-09-01', 'to' => ($year+1).'-08-31');
        return $result;
    }
    
    public function saveLog($dataType, $operation, $data)
    {
        if(isset(LOG_SETTINGS[$dataType])) {
            if(in_array($operation, LOG_SETTINGS[$dataType])) {
                $this->setUserInfo();
                $dbData = array();
                if(isset($this->userInfo)) {           
                    $dbData['ID_osoby'] = $this->userInfo->ID;
                }
                if(isset($this->schoolInfo)) {  
                    $dbData['ID_skoly'] = $this->schoolInfo->ID;
                }
                $dbData['typ_dat'] = $dataType;
                $dbData['hodnota'] = json_encode($data);
                $dbData['operace'] = $operation;
                try {
                    $this->logManager->saveLogRecord($dbData);
                } catch (Exception $e) {
                }
            }
        }
    }

    public function applyTransfer($data, $transfer, $way, $dataType = DATA_MULTIPLE_ROWS)
    {
        $result = array();
        // data jako objekt
        if($dataType == DATA_OBJECT) {
            foreach ($transfer as $dbName => $jsonName) {
                if($way == TRANSFER_TO_JSON) {
                    $result[$jsonName] = $data->$dbName;
                } else if($way == TRANSFER_TO_DB) {
                    $result[$dbName] = $data->$jsonName;
                }
            }
            return $result;
        }
        // data jako pole
        if($dataType == DATA_SINGLE_ROW) { $data = array($data); } // uprava pokud je vlozen jen jeden objekt
        foreach($data as $dataRow){
            $resultRow = array();
            foreach ($transfer as $dbName => $jsonName) {
                if($way == TRANSFER_TO_JSON) {
                    $resultRow[$jsonName] = $dataRow[$dbName];
                } else if($way == TRANSFER_TO_DB) {
                    $resultRow[$dbName] = $dataRow[$jsonName];
                }
            }
            $result[] = $resultRow;
        }
        if($dataType == DATA_SINGLE_ROW) { $result = $result[0]; } // uprava pokud je vlozen jen jeden objekt
        return $result;
    }

    public function checkUserAccess($minAllowedRole, $schoolAccess = false)
    {
        $this->setUserInfo();
        if(isset($this->userInfo)) {           
            if($this->userInfo == null) {
                $this->error('uzivatel neni prihlasen', Nette\Http\Response::S401_UNAUTHORIZED);
            }
            $allowedRoles = $this->getAllowedRolesByMin($minAllowedRole);
            if(in_array($this->userInfo->opravneni, $allowedRoles))
            {
                return true;
            }
            $this->error('nedostatecna opravneni', Nette\Http\Response::S403_FORBIDDEN);
        }
        if(isset($this->schoolInfo)) {  
            if($this->schoolInfo == null) {
                $this->error('uzivatel neni prihlasen', Nette\Http\Response::S401_UNAUTHORIZED);
            }         
            if($schoolAccess == true) {           
                return true;
            }
            $this->error('nedostatecna opravneni', Nette\Http\Response::S403_FORBIDDEN);
        }
        $this->error('uzivatel neni prihlasen', Nette\Http\Response::S401_UNAUTHORIZED);
    } 

    public function getAllowedRolesByMin($minAllowedRole)
    {
        $allowedRoles = array();
        $found = false;
        foreach (INSTRUCTOR_USER_ROLES as $role) {
            if($role == $minAllowedRole) {
                $found = true;
            }
            if($found) {
                $allowedRoles[] = $role;
            }
        }
        return $allowedRoles;
    }

    public function roleIsAtLeast($minimalRole) 
    {
        $this->setUserInfo();
        if(isset($this->userInfo)) {
            $allowedRoles = $this->getAllowedRolesByMin($minimalRole);
            if(in_array($this->userInfo->opravneni, $allowedRoles))
            {
                return true;
            }
        }
        return false;
    }

}
