<?php
	class Controller {
		
		public $config;
		public $locale;
		public $layout;
		public $user;
		//public $helper;
		public $utility;
		public $view;
		public $viewDir;
		public $appTitle;
		public $db;
		public $security;
		public $cookie;
		public $session;
		public $logger;
		public $media;
		public $allow;
		public $allowedRoles;
		public $permissionDenied;
		public $showBreadcrumbs;
		public $breadcrumbs;
		public $actionTitle;
		public $appRequestType; //web [default], mob, desk (TODO: read the http header appRequestType)
		public $memoryCache;
		public $alerts;
		public $paginationRange;
		public $userLocale;
		
		function __construct() {
			global $config, $layout, $locale, $memoryCache, $user, $db, $security, $session, $cookie, $logger;
			
			$this->db = $db;
			$this->config = $config;
			$this->layout = $layout;
			$this->locale = $locale;
			$this->defLang = $this->locale->defaultLanguage;
			$this->utility = new Utility();
			//$this->helper = new Helper();
			$this->alerts = new Alerts(); //Deprecated
			$this->media = new Media();
			$this->user = $user;
			$this->view = new stdClass();
			$this->viewDir = null;
			$this->appTitle = $this->config['settings']['app-title'];
			$this->security = $security;
			$this->session = $session;
			$this->cookie = $cookie;
			$this->logger = $logger;
			$this->allow = [];
			$this->permissionDenied = false;
			$this->appRequestType = 'web';
			$this->memoryCache = $memoryCache;
			$this->paginationRange = 10;
			$this->userLocale = null;
			
			$this->showBreadcrumbs = true;
			$this->breadcrumbs = [];
			$this->actionTitle = '';
			$this->controllerName = '';
			$this->actionName = '';
			
			$this->setContentLocale();	
		}
		
		public function allowAccess() {
			return false;
		}
		
		public function beforeRender($content=null) {
			return false;
		}
		
		public function checkPermissions($allowedRoles=[]) {
			if (is_array($allowedRoles) && !empty($allowedRoles)) {
				return $this->user->checkPermissions($allowedRoles);
			}
			
			return true;
		}
		
		public function setContentLocale() {
			
			$this->userLocale = $this->locale->setCurrentLanguage();
			$this->view->userLocale = $this->userLocale;
			
			$this->locale->setLocaleEnvironment($this->userLocale);
		}
		
		public function setView($file=null, $compact=true) {
			$content = '';
						
			//Check whether allowAccess() method is overriden in the child class and return its content
			if (!in_array($file, $this->allow)) {
				$allowAccess = $this->allowAccess();
				if ($allowAccess !== false) {
					$data = json_decode($allowAccess, true);
					return $data['html'];
				}
			}
			
			if (!is_null($file)) {
				$ob_string = $this->config['settings']['gzip-content'] ? 'ob_gzhandler' : '';	
				ob_start($ob_string);
				include VIEWS_DIR.$this->viewDir.'/'.$file.'.view.php';
				$content = ob_get_clean();
				
			}
			
			$isUTF8 = mb_detect_encoding($content, 'UTF-8', true);
			
			if (!$isUTF8)		
				return utf8_encode(utf8_decode($content));
			else 
				return $content;
		}
		
		public function setJsonView($file=null, $compress=true, $jsRedirect='', $jsonData=[]) {
			$content = $this->setView($file, $compress);
			
			//You can overraid this method in mainController for all controllers or in a specific controller
			$beforeRender = $this->beforeRender($content);
			if ($beforeRender !== false) {
				$content = $beforeRender;
			}
			
			return $this->setRawJsonResponse('ok', null, ['jsonData'=>$jsonData, 'page'=>1, 'html'=>$content, 'jsRedirect'=>$jsRedirect]);
		}
		
		public function setRawJsonResponse($status='ok', $msg=null, $args=[], $jsArgs=null) {
			return json_encode(array_merge(['status'=>$status, 'msg'=>$msg, 'jsArgs'=>$jsArgs, 'userId'=>$this->user->getUserId(), 'groupId'=>$this->user->getGroupId(), 'username'=>$this->user->getUserField('userUsername'), 'apiKey' => $this->config['settings']['api-key'], 'userLang'=>$this->locale->setCurrentLanguage()], $args));
		}
		
		public function setJsonError($msg='', $action=null) {
			return $this->setRawJsonResponse('err', $msg, ['action', $action]);
		}
		
		public function partial($path, $params=[], $compact=true) {
			if (!empty($params)) extract($params);
							
			ob_start();
			include VIEWS_DIR.'Elements/'.$path.'.part.php';
			$content = ob_get_clean();
			
			return $content;
		}
		
		public function setPagination($dbRef, $totalRows, $currentPage, $link) {
			$this->view->totalPages = $dbRef->totalPages;
			$this->view->totalRows = $totalRows;
			$this->view->currentPage = $currentPage;
			
			$this->view->pageNumbers = [];
			$this->view->hasPrevPage = $this->view->currentPage > 1 ? true : false;
			$this->view->hasNextPage = $this->view->currentPage < $this->view->totalPages ? true : false;
			$this->view->prevPageLink = $this->utility->setHash($link.'/'.((int)$this->view->currentPage-1));
			$this->view->nextPageLink = $this->utility->setHash($link.'/'.((int)$this->view->currentPage+1));
			
			$this->view->pagNumbRange = $this->paginationRange;
			$this->view->pagLimitLeft = 1;
			$this->view->pagLimitRight = ($this->view->pagNumbRange<$this->view->totalPages) 
			? $this->view->pagLimitLeft+($this->view->pagNumbRange-1) : $this->view->totalPages;
			
			if ($this->view->currentPage > $this->view->pagNumbRange) {
				if ($this->view->totalPages > $this->view->pagNumbRange) {
					//$this->view->pagLimitLeft = $this->view->totalPages-$this->view->pagNumbRange;
					//$this->view->pagLimitRight = $this->view->pagLimitLeft+$this->view->pagNumbRange;
					
					$this->view->pagLimitLeft = $this->view->pagNumbRange+1;
					$this->view->pagLimitRight = ($this->view->pagLimitLeft+$this->view->pagNumbRange) < $this->view->totalPages ? $this->view->pagLimitLeft+$this->view->pagNumbRange : $this->view->totalPages;
				}
			}
			
			if ($this->view->totalPages > 1) {
				for($i=$this->view->pagLimitLeft; $i<=$this->view->pagLimitRight; $i++) {
					$pageActive = $i == $this->view->currentPage ? true : false;
					$this->view->pageNumbers[$i] = ['active'=>$pageActive, 'label'=>$i, 'link'=>$this->utility->setHash($link.'/'.$i)];
				}
			}
		}
		
		public function validateForm($data=[], $checkPasswords=false) {
			
			if (is_array($data) && !empty($data)) {
				$pwd1 = null;
				$pwd2 = null;
				foreach($data as $key => $item) {
					if (isset($item['required']) && (int)$item['required'] == 1) {
						if (trim($item['value']) == '') {
							return ['msg'=>vsprintf(_('"%s" is a required field.'), [$item['label']]), 'class'=>$item['class']];
						}
						
						if ($item['type'] == 'email' && trim($item['value']) != '') {
							if (!filter_var($item['value'], FILTER_VALIDATE_EMAIL)) {
								return ['msg'=>vsprintf(_('"%s" is not a valid email address.'), [$item['label']]), 'class'=>$item['class']];
							}
						}
						
						if ($checkPasswords) {
							if ($item['type'] == 'password1' || $item['type'] == 'password2' || $item['type'] == 'password') {
								/*if (strlen($item['value']) < $this->security->passwordMinLength) {
									return ['msg'=>vsprintf(_('"%s" field length is too short.'), [$item['label']]), 'class'=>$item['class']];
								}*/
								
								if (!$this->security->validatePassword($item['value'])) {
									return ['msg'=>vsprintf(_('The password provided is not valid. The password must contain at least %s characters and at least 1 non-alphanumeric symbol (!, ?, -, etc.)'), [$item['label'], $this->security->passwordMinLength]), 'class'=>$item['class']];
								}
							}
							
							if ($item['type'] == 'password1') {
								$pwd1 = trim($item['value']);
							}
							
							if ($item['type'] == 'password2') {
								$pwd2 = trim($item['value']);
							}
							
							if (!is_null($pwd1) && !is_null($pwd2)) {
								if ($pwd1 != $pwd2) {
									return ['msg'=>_('The password fields do not match.'), 'class'=>$item['class']];
								}
							}
						}
					}
				}
				
				return true;
			}
			
			return false;
		}
		
		public function setJson($structure=null) {
			return json_encode($structure);
		}
		
		public function parseArgs($args) {
			$params = isset($args['params']) ? $args['params'] : false;
			
			if ($params !== false) {
				parse_str($params, $output);
			} else {
				$output = null;
			}
			
			return $output;
		}
		
		public function getPost($key=null, $default=false) {
			$value = isset($_POST[$key]) ? $_POST[$key] : $default;
			return $value;
		}
		
		public function redirect($controller, $action, $args=null) {
			$args = $this->parseArgs($args);
			return Dispatch::route($controller, $action, $args);
		}
		
		public function compactText($content=null) {
			$content = str_replace(array("\n","\r","\t"), '', $content);
			$content = preg_replace('/\s+/', ' ', $content);
			
			return $content;
		}
	}