
<?php
	class HandleRequest {

		private $db;
		private $user;
		private $config;

		public $requestStatusLabels;
		public $activityCodes;
		public $statusNumbers;

		public const REQUEST_STATUS_PENDING = 'pending';
		public const REQUEST_STATUS_DRAFT = 'draft';
		public const REQUEST_STATUS_OPENED = 'opened';
		public const REQUEST_STATUS_PART_REPORTED = '! referted'; //Partially reported
		public const REQUEST_STATUS_REPORTED = 'referted';
		public const REQUEST_STATUS_REOPENED = 'reopened';

		function __construct() {
			global $db, $user, $config;

			$this->db = $db;
			$this->user = $user;
			$this->config = $config;

			//Set the codes and labels array
			$this->requestStatusLabels = [self::REQUEST_STATUS_PENDING=>_('Sending'), self::REQUEST_STATUS_DRAFT=>_('Draft'), self::REQUEST_STATUS_OPENED=>_('Opened'), self::REQUEST_STATUS_PART_REPORTED=>_('Partially answered'), self::REQUEST_STATUS_REPORTED=>_('Answered'), self::REQUEST_STATUS_REOPENED=>_('Reopened')];

			$this->statusNumbers = ['pending'=>-1, 'draft'=>5, 'opened'=>1, '! referted'=>2, 'reopened'=>3, 'referted'=>4];

			$this->activityCodes = [
				'USR_LOGGED_IN' => _('User %s logged in (regular login).'),
				'USR_AUTO_LOGGED_IN' => _('User %s logged in (auto-login).'),
				'USR_LOGIN_FAILED' => _('User %s login failed (regular login).'),
				'USR_AUTO_LOGIN_FAILED' => _('User %s login failed (auto-login).'),
				'REQ_LISTED' => _('Requests listed by the user %s.'),
				'REQ_NEW' => _('Opened new Request for writing by the user %s.'),
				'REQ_EDITED' => _('Opened draft Request #%s for editing by the user %s.'),
				'REQ_VIEW' => _('Opened Request #%s for reading by the user %s.'),
				'REQ_SAVED_DRAFT' => _('Saved Request #%s as draft by the user %s.'),
				'REQ_SENT' => _('Sent new Request #%s by the user %s.'),
				'REQ_FILE_ADDED' => _('File %s attached to the Request #%s by the user %s.'),
				'REQ_DELETED' => _('Request #%s deleted by the user %s.'),
				'REQ_FWD' => _('Added new specialties to the Request #%s by the user %s.'),
				'REQ_MSG' => _('New message added to the Request #%s by the user %s.'),
				'REQ_STATUS_CNG_MODERATOR' => _('Status of the Request #%s changed to %s by the Moderator.')
			];

		}

		public function isUserTheAuthor($requestID=0, $userID=0) {
			$result = $this->db
				->where('r.id', $requestID)
				->where('r.user_id', $userID)
				->get('requests r');

			return is_array($result) && !empty($result) ? true : false;
		}

		public function isUserModerator($requestCenterID=0, $clinicalCenters=[], $userID=0) {
			return isset($clinicalCenters[$requestCenterID]) ? true : false;
		}

		public function isUserReferrer($requestID=0, $userID=0) {
			$result = $this->db
				->where('rr.request_id', $requestID)
				->where('rr.user_id', $userID)
				->get('requests_recipients rr');

			return is_array($result) && !empty($result) ? true : false;
		}

		//Check whether the provided user is a referral in the provided request
		public function isReferralInRequest($requestID=0, $userID=0) {
			$recipients = $this->db
				->where('rr.request_id', $requestID)
				->where('rr.user_id', $userID)
				->get('requests_recipients rr');

			return count($recipients) > 0 ? true : false;
		}

		public function isApplicantInRequest($requestID=0, $userID=0) {
			$request = $this->db
				->where('id', $requestID)
				->getOne('requests r', 'r.user_id');

			return isset($request['user_id']) && (int)$request['user_id'] == (int)$userID ? true : false;
		}

		public function getSpecialtyByClinicalCenterId($ccId=0, $groupId=0) {
			$specialties = [];

			/*if ($ccId > 0) {
				$results = $this->db
					->where('ccmst.center_id', $ccId)
					->join('users_medical_specialties ums', 'ums.id=ccmst.specialty_id', 'INNER')
					->orderBy('ums.description', 'asc')
					->get('clinical_center_medical_specialties_to ccmst', null, ['ums.id', 'ums.description']);
			} else {
				$results = $this->db
					->orderBy('ums.description', 'asc')
					->get('users_medical_specialties ums', null, ['ums.id', 'ums.description']);
			}*/

			//All Medical Specialties
			if ($ccId > 0) {
				$results = $this->db
					->where('ccmst.center_id', $ccId)
					->where('urt.role_id', REFERRER_ROLE_ID)
					->where('u.group_id', $groupId)
					->where('u.status', 1)
					->join('users_medical_specialties ums', 'ums.id=ccmst.specialty_id', 'INNER')
					->join('users_medical_specialties_to umst', 'umst.specialty_id=ums.id', 'INNER')
					->join('users u', 'u.id=umst.user_id', 'INNER')
					->join('users_roles_to urt', 'urt.user_id=u.id', 'INNER')
					->groupBy('ums.id')
					->orderBy('ums.description', 'asc')
					->get('clinical_center_medical_specialties_to ccmst', null, ['ums.id', 'ums.description']);
			} else {
				$results = $this->db
					->where('urt.role_id', REFERRER_ROLE_ID)
					->where('u.group_id', $groupId)
					->where('u.status', 1)
					->join('users_medical_specialties_to umst', 'umst.specialty_id=ums.id', 'INNER')
					->join('users u', 'u.id=umst.user_id', 'INNER')
					->join('users_roles_to urt', 'urt.user_id=u.id', 'INNER')
					->groupBy('ums.id')
					->orderBy('ums.description', 'asc')
					->get('users_medical_specialties ums', null, ['ums.id', 'ums.description']);
			}

			if (is_array($results)) {
				foreach($results as $item) {
					$specialties[$item['id']]['id'] = $item['id'];
					$specialties[$item['id']]['description'] = _($item['description']);
				}
			}

			return $specialties;
		}

		public function getRecipientsByRequestId($requestId=0) {
			$recipients = $this->db
				->where('rr.request_id', $requestId)
				->join('users u', 'u.id=rr.user_id', 'INNER')
				->orderBy('u.surname', 'ASC')
				->get('requests_recipients rr', null, ['u.name', 'u.surname', "(SELECT GROUP_CONCAT(ms.description SEPARATOR '|') FROM users_medical_specialties_to umst JOIN users_medical_specialties ms ON ms.id=umst.specialty_id WHERE umst.user_id=u.id ORDER BY ms.description) AS ms_list"]);

			if(is_array($recipients)) {
				foreach($recipients as $index => $recipient) {
					$ms = $recipient['ms_list'];
					if (strpos($ms, '|') !== false) {
						$temp = explode('|', $ms);
						$tempArr = [];
						foreach($temp as $item) {
							$tempArr[] = _($item);
						}

						$recipients[$index]['ms_list'] = implode(', ', $tempArr);

					} else {
						$recipients[$index]['ms_list'] = _($ms);
					}
				}
			}

			return $recipients;
		}

		public function getRecipients($params=[]) {
			$referralMs = isset($params['ms']) ? $params['ms'] : []; //Medical Specialty
			$referralCc = isset($params['cc']) ? $params['cc'] : []; //Clinical Center
			$referralLangs = isset($params['langs']) ? $params['langs'] : [];
			$recipientList = isset($params['recipientList']) ? $params['recipientList'] : [];
			$groupId = isset($params['groupId']) ? $params['groupId'] : 0;

			$arrayLangs = [];
			foreach($referralLangs as $lang) {
				$arrayLangs[] = $lang;
			}

			if (is_array($recipientList) && !empty($recipientList)) {

					return $this->db
						->where('ucct.role_id', REFERRER_ROLE_ID)
						->where('u.id IN('.implode(',', $recipientList).')')
						->where('u.group_id', $groupId)
						->where('u.status', 1)
						->join('users u', 'u.id=ucct.user_id', 'INNER')
						->orderBy('u.surname', 'asc')
						->get('users_clinical_centers_to ucct', null, [
							'u.id user_id',
							'u.surname',
							'u.name',
							'ucct.user_id',
							"(SELECT GROUP_CONCAT(ms.description SEPARATOR ', ') FROM users_medical_specialties_to umst JOIN users_medical_specialties ms ON ms.id=umst.specialty_id WHERE umst.user_id=u.id ORDER BY ms.description) AS ms_list",
							"(SELECT GROUP_CONCAT(cc.description SEPARATOR ', ') FROM users_clinical_centers_to ucct JOIN clinical_centers cc ON cc.id=ucct.center_id WHERE ucct.user_id=u.id AND ucct.role_id=".REFERRER_ROLE_ID." ORDER BY cc.description) AS cc_list"
						]);

			} else {

				if (!empty($referralCc)) {
					$this->db->where("ucct.center_id IN(".implode(',', $referralCc).")");
				}

				if (!empty($referralMs) && !empty($referralLangs)) {
					$results = $this->db
						->where('ucct.role_id', REFERRER_ROLE_ID)
						//->where("u.language_default IN($langList)")
						->where('u.status', 1)
						->where('u.group_id', $groupId)
						->join('users u', 'u.id=ucct.user_id', 'INNER')
						->having('ms_total', 0, '>')
						->orderBy('u.surname', 'asc')
						->get('users_clinical_centers_to ucct', null, [
							'u.id user_id',
							'u.surname',
							'u.name',
							'u.language_default',
							'ucct.user_id',
							"(SELECT COUNT(*) FROM users_medical_specialties_to umst WHERE umst.specialty_id IN(".implode(',', $referralMs).") AND umst.user_id=ucct.user_id) ms_total",
							"(SELECT GROUP_CONCAT(ms.description SEPARATOR ', ') FROM users_medical_specialties_to umst JOIN users_medical_specialties ms ON ms.id=umst.specialty_id WHERE umst.user_id=u.id ORDER BY ms.description) AS ms_list",
							"(SELECT GROUP_CONCAT(cc.description SEPARATOR ', ') FROM users_clinical_centers_to ucct JOIN clinical_centers cc ON cc.id=ucct.center_id WHERE ucct.user_id=u.id AND ucct.role_id=".REFERRER_ROLE_ID." ORDER BY cc.description) AS cc_list",
							"(SELECT GROUP_CONCAT(ult.language_id) FROM users_languages_to ult WHERE ult.user_id=u.id) AS user_alt_langs"
					]);

					//Check the languages
					$recipients = [];
					if (is_array($results)) {
						/*foreach($results as $result) {
							$checkLangsList = !empty($result['user_alt_langs']) ? $result['user_alt_langs'].','.$result['language_default'] : $result['language_default'];
							$checkLangs = explode(',', $checkLangsList);

							foreach($arrayLangs as $lng) {
								if (in_array($lng, $checkLangs)) {
									$recipients[] = $result;
								}
							}
						}

						return $recipients;
						*/

						return $results;
					}
				}

			}

			return false;
		}

		//public function forwardRequest($requestID=0, $formSpecialtyList=[], $groupId=0, $senderId=0, $centerId=0) {
		public function forwardRequest($requestID=0, $newSpecialties=[], $groupId=0, $senderId=0, $centerId=0) {

			//if (empty($formSpecialtyList)) return false;
			if (!is_array($newSpecialties)) return false;
			if (count($newSpecialties) < 1) return false;

			$isForward = false;

			/*$requestSpecialties = $this->db
				->where('rmst.request_id', $requestID)
				->getOne('requests_medical_specialties_to rmst', "GROUP_CONCAT(rmst.specialty_id) specialty_comma_list");

			$specialtyList = explode(',', $requestSpecialties['specialty_comma_list']);

			//Moderator or Referral has added a specialty
			$newSpecialties = [];
			$referrals = [];

			if(count($formSpecialtyList) > count($specialtyList)) {
				foreach($formSpecialtyList as $formSpecialty) {
					if (!in_array($formSpecialty, $specialtyList)) {
						$newSpecialties[$formSpecialty] = $formSpecialty;
					}
				}
			*/

				//if (!empty($newSpecialties)) {

					$referrals = $this->db
						->where("umst.specialty_id IN(".implode(',', $newSpecialties).")")
						->where('u.group_id', $groupId)
						->where('u.status', 1)
						->having('centers', 0, '>')
						->join('users u', 'u.id=umst.user_id', 'INNER')
						->get('users_medical_specialties_to umst', null, ['umst.user_id', "(SELECT COUNT(*) FROM users_clinical_centers_to ucct WHERE ucct.user_id=u.id AND ucct.role_id=".REFERRER_ROLE_ID." AND ucct.center_id=$centerId) centers"]);

					//Add these user to the recipient list
					if (is_array($referrals) && !empty($referrals)) {

						$isForward = true;

						//Add the new specialty
						foreach($newSpecialties as $newSpecialty) {
							$this->db->insert('requests_medical_specialties_to', ['request_id'=>$requestID, 'specialty_id'=>$newSpecialty]);
						}

						foreach($referrals as $referral) {
							$this->db->insert('requests_recipients', ['request_id'=>$requestID, 'user_id'=>$referral['user_id']]);
							$this->queueMessage($requestID, $referral['user_id'], $senderId, 'NEW_FWD_REQUEST');
						}

						$this->setActivityLog($this->user->getUserId(), 'REQ_FWD', ['userId'=>$this->user->getUserId(), 'requestId'=>$requestID]);
					}


				//}

			//}

			return $isForward;
			//return $this->db->getLastQuery();
		}

		public function setRequestProgress($requestID=0, $userID=0) {
			$request = $this->db->where('id', $requestID)->getOne('requests');

		}

		public function incrementReferralCounter($requestID=0, $userID=0) {
			if ($this->isReferralInRequest($requestID, $userID)) {

				$specialtyList = [];

				$specialties = $this->db
					->where('umst.user_id', $userID)
					->get('users_medical_specialties_to umst', null, ['umst.specialty_id']);

				if (is_array($specialties) && !empty($specialties)) {
					foreach($specialties as $specialty) {
						$specialtyList[] = $specialty['specialty_id'];
					}

					//Sort the array to always get the same comma separated list
					sort($specialtyList);
				}

				return $this->db->insert('request_reports_counter', ['request_id'=>$requestID, 'referral_id'=>$userID, 'referral_specialties'=>implode(',', $specialtyList)]);
			}

			return false;
		}

		public function cleanReferralCounter($requestID=0) {
			return $this->db->where('request_id', $requestID)->delete('request_reports_counter');
		}

		public function isRequestFullyReported($requestID=0) {
			//Request spcialties
			$specialties = $this->db
				->where('rmst.request_id', $requestID)
				->get('requests_medical_specialties_to rmst', null, ['rmst.specialty_id']);

			$specialtyList = [];
			if (is_array($specialties) && !empty($specialties)) {

				//Flat the specialties in a one dimensional array
				foreach($specialties as $specialty) {
					$specialtyList[] = $specialty['specialty_id'];
				}
				$specialtyList = array_unique($specialtyList);
				sort($specialtyList);

				//Get all answers
				$comments = $this->db
					->where('rc.request_id', $requestID)
					->get('requests_comments rc');

				//Array of specialties for each responders
				$msPerResponders = [];

				//Get all medical specialties for each responders
				if (is_array($comments) && !empty($comments)) {

					foreach($comments as $comment) {
						$ms = $this->db
							->where('umst.user_id', $comment['user_id'])
							->get('users_medical_specialties_to umst');

						if (is_array($ms)) {

							//Flat the medical specialties in a one dimensional array with no duplicates
							foreach($ms as $item) {
								if (in_array($item['specialty_id'], $specialtyList)) {
									$msPerResponders[$item['specialty_id']] = $item['specialty_id'];
								}
							}
							$msPerResponders = array_unique($msPerResponders);
							sort($msPerResponders);
						}

					}

					$diff = array_diff($specialtyList, $msPerResponders);

					return empty($diff) ? true : -2;
				}

				return 0;

			} else {
				return -1;
			}
		}

		public function setLog($logName='', $output=null) {
			file_put_contents(BASE_ROOT.'log/'.$logName.'.log', $output."\n", FILE_APPEND);
		}

		public function setActivityLog($userId=0, $activityCode='', $params=[]) {
			return;
			$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
			$requestId = $params['requestId'] ?? 0;
			$this->db->insert('log_activities', ['user_id'=>$userId, 'request_id'=>$requestId, 'user_agent'=>$userAgent, 'activity_code'=>$activityCode, 'activity_params'=>json_encode($params), 'created_at'=>date('Y-m-d H:i:s')]);
		}

		public function setRequestStatus($requestID=0, $statusCode='', $userId=0) {
			$statusNumber = isset($this->statusNumbers[$statusCode]) ? $this->statusNumbers[$statusCode] : -1;
			if ($this->db->where('id', $requestID)->update('requests', ['request_status'=>$statusCode, 'request_status_number'=>$statusNumber])) {
				return $this->setStatusHistory($requestID, $statusCode, $userId);
			}

			return false;
		}

		public function filterActivityLog($activityCode='', $params=[]) {
			$userData = isset($params['userId']) ? $this->user->getUserDB($params['userId']) : null;
			$userString = !empty($userData) && is_array($userData) ? $userData['surname'].' '.$userData['name'] : 'n/d';
			$requestId = $params['requestId'] ?? 'n/d';
			$fileTitle = $params['fileTitle'] ?? 'n/d';
			$newStatus = $params['newStatus'] ?? 'n/d';

			switch($activityCode) {
				case 'USR_LOGGED_IN':
				case 'USR_AUTO_LOGGED_IN':
				case 'USR_LOGIN_FAILED':
				case 'USR_AUTO_LOGIN_FAILED':
				case 'REQ_LISTED':
				case 'REQ_NEW':
					return vsprintf($this->activityCodes[$activityCode], [$userString]);
				break;

				case 'REQ_EDITED':
				case 'REQ_VIEW':
				case 'REQ_SAVED_DRAFT':
				case 'REQ_SENT':
				case 'REQ_DELETED':
				case 'REQ_FWD':
				case 'REQ_MSG':
					return vsprintf($this->activityCodes[$activityCode], [$requestId, $userString]);
				break;

				case 'REQ_FILE_ADDED':
					return vsprintf($this->activityCodes[$activityCode], [$fileTitle, $requestId, $userString]);
				break;

				case 'REQ_STATUS_CNG_MODERATOR':
					return vsprintf($this->activityCodes[$activityCode], [$requestId, $newStatus]);
				break;
			}
		}

		public function getActivityLogList($params=[]) {

			return;

			$userId = (int)$params['userId'] ?? 0;
			$requestId = (int)$params['requestId'] ?? 0;
			$dateFrom = $params['dateFrom'] ?? null;
			$dateTo = $params['dateTo'] ?? null;
			$logList = [];

			if ($userId > 0) {
				$this->db->where('user_id', $userId);
			}

			if ($requestId > 0) {
				$this->db->where('request_id', $requestId);
			}

			if (!is_null($dateFrom)) {
				$this->db->where("created_at >= '$dateFrom'");
			}

			if (!is_null($dateTo)) {
				$this->db->where("created_at <= '$dateTo'");
			}

			$results = $this->db->get('log_activities');

			if (is_array($results) && !empty($results)) {
				foreach($results as $result) {
					$logRow = $this->filterActivityLog($result['activity_code'], json_decode($result['activity_params'], true));
					if ($logRow != '')
						$logList[] = $result['created_at'].' > '.$logRow;
				}
			}

			return $logList;
		}

		public function setStatusHistory($requestID=0, $statusCode='', $userId=0) {
			$this->updateDate($requestID);
			return $this->db->insert('requests_statuses_history', ['request_id'=>$requestID, 'user_id'=>$userId, 'status_code'=>$statusCode, 'created_at'=>date('Y-m-d H:i:s')]);
		}

		public function getCommentList($requestID=0, $ccID=0, $checkCC=true) {


			$groupedComments = [];
			$positions = [];
			//$userIsAuthor = $this->isUserTheAuthor($requestID, $this->user->getUserId());

			$comments = $this->db
				->where('rc.request_id', $requestID)
				->where('rc.is_visible', 1)
				->join('users u', 'u.id=rc.user_id', 'INNER')
				->orderBy('rc.created_at', 'asc')
				->get('requests_comments rc', null, ['rc.*', 'u.name user_name', 'u.surname user_surname', 'u.remarks_public', 'u.updated_at user_updated_at',

				 "(SELECT GROUP_CONCAT(ums.description SEPARATOR '|') FROM users_medical_specialties_to umst INNER JOIN users_medical_specialties ums ON ums.id=umst.specialty_id WHERE umst.user_id=rc.user_id ORDER BY ums.description ASC) medspec_list",

				 "(SELECT GROUP_CONCAT(cc.description SEPARATOR ', ') FROM users_clinical_centers_to ucct JOIN clinical_centers cc ON cc.id=ucct.center_id WHERE ucct.role_id=".REFERRER_ROLE_ID." AND ucct.user_id=rc.user_id ORDER BY cc.description ASC) cc_list",

				 "(SELECT GROUP_CONCAT(ucct.center_id SEPARATOR '|') FROM users_clinical_centers_to ucct WHERE ucct.role_id=".MODERATOR_ROLE_ID." AND ucct.user_id=rc.user_id) cc_list_moderator", "(SELECT GROUP_CONCAT(sub_urt.role_id SEPARATOR '|') FROM users_roles_to sub_urt WHERE sub_urt.user_id=rc.user_id) user_roles"]
			);

			if (is_array($comments)) {
				$prvUserId = 0;
				$prvPosition = 'left';
				foreach($comments as $index => $comment) {

					$comments[$index]['show_meta'] = false;
					$comments[$index]['show_specialties'] = false; //Default value
					$comments[$index]['is_responder'] = false;
					$comments[$index]['is_the_author'] = false;

					//Translate a stringify the Medical Specialties list
					$medSpecialties = strpos($comments[$index]['medspec_list'], '|') !== false ? explode('|', $comments[$index]['medspec_list']) : [$comments[$index]['medspec_list']];

					if (is_array($medSpecialties) && !empty($medSpecialties)) {
						foreach($medSpecialties as $i => $ms) {
							$medSpecialties[$i] = _($ms);
						}
						$comments[$index]['medspec_list'] = implode(', ', $medSpecialties);
					} else {
						$comments[$index]['medspec_list'] = !is_null($medSpecialties) ? _($medSpecialties) : '';
					}

					//Set the (chat) balloon position
					if ($prvUserId > 0 && $prvUserId !== $comment['user_id']) {
						if ($prvPosition == 'left') {
							$comments[$index]['position'] = 'right';
							$prvPosition = 'right';
						} else {
							$comments[$index]['position'] = 'left';
							$prvPosition = 'left';
						}

						$comments[$index]['show_meta'] = true;
					} else {
						$comments[$index]['position'] = $prvPosition; //Default
						if ($prvUserId == 0) $comments[$index]['show_meta'] = true; //Default
					}

					$prvUserId = $comment['user_id'];

					//Check whether this user is a moderator in the current clinical center or just check whether the user is a moderator or isn't
					if ($checkCC) {
						//Clinical centers in whitch the user is a moderator
						$ccModerator = explode('|', $comment['cc_list_moderator']);

						//Compare the current Clinical Center ID against the previouses ($ccModerator)
						if (in_array($ccID, $ccModerator)) {
							$comments[$index]['is_moderator'] = true;
						} else {
							$comments[$index]['is_moderator'] = false;
						}
					} else {
						$comments[$index]['is_moderator'] = false;
					}

					//Is Referral (show the Medical Specialties)
					if (in_array(REFERRER_ROLE_ID, explode('|', $comment['user_roles']))) {
						$comments[$index]['show_specialties'] = true;
						$comments[$index]['is_responder'] = true;
					}

					//If Moderator, overwrite the possible previouse value
					if ($comments[$index]['is_moderator']) {
						$comments[$index]['show_specialties'] = false;
					}

					$userIsAuthor = $this->isUserTheAuthor($requestID, $comments[$index]['user_id']);

					//If Author, overwrite the possible previouse values
					if ($userIsAuthor) {
						$comments[$index]['show_specialties'] = false;
						$comments[$index]['is_moderator'] = false; //Overwrite the previouse value
						$comments[$index]['is_the_author'] = $userIsAuthor;
					}

					$comments[$index]['request_cc'] = $ccID;

					$comments[$index]['attachments'] = $this->getAttachmentsByRequestId($requestID, $comment['id']);

					$tUserId = $comment['user_id'];

				}
			}

			return $comments;
		}

		public function getAttachmentsByRequestId($requestID=0, $commentID=0) {
			$this->db->where('ra.request_id', $requestID);

			if ($commentID > 0) {
				$this->db->where('ra.comment_id', $commentID);
			}

			$attachments = $this->db->join('users u', 'u.id=ra.user_id', 'left')
				->orderBy('ra.created_at', 'desc')
				->get('requests_attachments ra', null, ['ra.*', 'u.name', 'u.surname']);

			return $attachments;
		}

		public function updateDate($requestID=0) {
			return $this->db->where('id', $requestID)->update('requests', ['updated_at'=>date('Y-m-d H:i:s')]);
		}

		public function deleteRequest($requestId=0) {

			$request = $this->db->where('id', $requestId)->delete('requests');

			$attachments = $this->db->where('request_id', $requestId)->delete('requests_attachments');
			$comments = $this->db->where('request_id', $requestId)->delete('requests_comments');
			$languages = $this->db->where('request_id', $requestId)->delete('requests_languages_to');
			$specialties = $this->db->where('request_id', $requestId)->delete('requests_medical_specialties_to');
			$notifications = $this->db->where('request_id', $requestId)->where('sent_status', 0)->delete('requests_messages_queue');
			$recipients = $this->db->where('request_id', $requestId)->delete('requests_recipients');
			$registry = $this->db->where('request_id', $requestId)->delete('requests_registry');
			$statusHistory = $this->db->where('request_id', $requestId)->delete('requests_statuses_history');
			$symptoms = $this->db->where('request_id', $requestId)->delete('requests_symptoms_to');
			$wizards = $this->db->where('request_id', $requestId)->delete('requests_wizards_to');
			$wizardDermaPositions = $this->db->where('request_id', $requestId)->delete('requests_wizard_derma_position_to');
			$reportCounter = $this->db->where('request_id', $requestId)->delete('request_reports_counter');
			$centers = $this->db->where('request_id', $requestId)->delete('request_clinical_centers_to');

			//TODO: delete attachment files

			return $request;
		}

		public function updateUserToken($userId=0, $uniqueId=null) {
			$expireDays = $this->config['settings']['autologin-expire-days'];
			$expireDate = date('Y-m-d 00:00:00', strtotime("+$expireDays days", time()));
			$returnUniqueId = null;

			$check = $this->db->where('id', $userId)->getOne('users', 'autologin_token, autologin_expires_at');

			$this->db->where('id', $userId);

			if (!empty($check['autologin_expires_at'])) {
				$this->db->where("DATEDIFF(NOW(), autologin_expires_at) > $expireDays");
			}

			$this->db->update('users', ['autologin_token'=>$uniqueId, 'autologin_expires_at'=>$expireDate]);

			if ($this->db->count > 0) {
				$returnUniqueId = $uniqueId;
			} else {
				$returnUniqueId = $check['autologin_token'];
			}

			return $returnUniqueId;
		}

		public function getStatistics($field='triage_color', $roleId=0, $controller=null) {

			$returnData = [];
			$count = 0;
			$labels = [];
			$values = [];
			$perc = [];
			$colors = [];
			$borders = [];

			$colorList = ['white'=>'rgba(255, 255, 255, 1)', 'green'=>'rgba(36, 167, 83, 1)', 'yellow'=>'rgba(255, 192, 67, 1)', 'red'=>'rgba(221, 51, 72, 1)', '! referted'=>'rgba(255, 192, 67, 1)', 'referted'=>'rgba(36, 167, 83, 1)', 'pending'=>'rgba(227, 227, 227, 1)', 'opened'=>'rgba(108, 117, 124, 1)', 'reopened'=>'rgba(221, 51, 72, 1)', 'draft'=>'rgba(165, 165, 165, 1)'];
			$borderList = ['white'=>'rgba(0, 0, 0, 0.2)', 'green'=>'rgba(36, 167, 83, 1)', 'yellow'=>'rgba(255, 192, 67, 1)', 'red'=>'rgba(221, 51, 72, 1)'];

			switch ($roleId) {

				case ADMIN_ROLE_ID:
					$this->db->where('r.group_id', $controller->userGroupId);
				break;

				case MODERATOR_ROLE_ID:
				case REFERRER_ROLE_ID:
				case GUEST_ROLE_ID:

					$clinicalCenters = $controller->getUserClinicalCenters($this->user->getUserId(), $roleId); //In mainController
					$ccIds = array_keys($clinicalCenters);
					$this->db->where('r.center_id', $ccIds, 'IN');
					if ($field != 'triage_color') {
						$this->db->where('r.request_status', ['opened', 'reopened', '! referted', 'referted'], 'IN');
					}
				break;

					//Applicant
				default:
					$this->db->where('r.user_id', $this->user->getUserId());

			}

			$this->db->where('r.request_visibility', 'all');

			if ($field == 'triage_color') {
				$this->db->where('r.request_status', ['opened', 'reopened', '! referted'], 'IN');
				$this->db->groupBy('r.triage_color');
				$results = $this->db->get('requests r', null, ['COUNT(*) total', 'r.triage_color']);
			}

			if ($field == 'request_status') {
				$this->db->groupBy('r.request_status');
				$results = $this->db->get('requests r', null, ['COUNT(*) total', 'r.request_status']);
			}

			if (is_array($results)) {
				foreach($results as $index => $item) {
					$count = $count+$item['total'];
					$labels[$index] = _(ucfirst($item[$field])) ?? null;
					$labelsValues[$index] = _(ucfirst($item[$field])).' ('.$item['total'].')' ?? null;
					$values[$index] = $item['total'];
					$colors[$index] = $colorList[$item[$field]];
					$borders[$index] = $borderList[$item[$field]] ?? null;
				}

				foreach($results as $index => $item) {
					//$results[$index]['perc'] = round($item['total']*100/$count);
					$perc[$index] = number_format($item['total']*100/$count, 1);
					$labelsPerc[$index] = _(ucfirst($item[$field])).' ('.$perc[$index].'%)' ?? null;
				}

			}

			$returnData['labels'] = $labels;
			$returnData['labelsValues'] = $labelsValues;
			$returnData['labelsPerc'] = $labelsPerc;
			$returnData['colors'] = $colors;
			$returnData['borders'] = $borders;
			$returnData['values'] = $values;
			$returnData['perc'] = $perc;
			$returnData['query'] = $this->db->getLastQuery();

			return $returnData;
		}

		public function getDataForMessageQueue($requestID=0, $recipientID=0, $senderID=0, $msgCode='') {
			$currentLocale = setlocale(LC_ALL, 0);
			$supportedLocales = $this->config['settings']['supported-locales'];

			$request = $this->db
				->where('r.id', $requestID)
				->join('clinical_centers cc', 'cc.id=r.center_id', 'INNER')
				->join('continents cnt', 'cnt.code=cc.continent_code', 'INNER')
				->join('countries cntr', 'cntr.country_iso2_code=cc.country_code', 'INNER')
				->getOne('requests r', "r.id request_id, r.triage_color, (SELECT GROUP_CONCAT(rlt.language_code) FROM requests_languages_to rlt WHERE rlt.request_id=r.id) request_lang_list, (SELECT GROUP_CONCAT(ums.description SEPARATOR ', ') FROM requests_medical_specialties_to rmst JOIN users_medical_specialties ums ON ums.id=rmst.specialty_id WHERE rmst.request_id=r.id) specialties, cc.description cc_name, cntr.country_name, cnt.name continent_name");

			$sender = $this->db
				->where('u.id', $senderID)
				->getOne('users u');

			$recipient = $this->db
				->where('u.id', $recipientID)
				->getOne('users u');

			$recipientLang = isset($recipient['language_default']) ? $recipient['language_default'] : 'en';
			$recipientLocale = isset($supportedLocales[$recipientLang]) ? $supportedLocales[$recipientLang] : 'en_US';
			setlocale(LC_ALL, $recipientLocale);

			$langList = $this->stringifyLangCodes($request['request_lang_list']);
			$specialtyList = $this->translateSpecialties($request['specialties']);

			$newUniqueId = uniqid();
			$uniqueId = $this->updateUserToken($recipient['id'], $newUniqueId);
			$siteLink = $this->config['settings']['http-protocol'].$this->config['settings']['site-domain'].'/#/auto-login/'.$uniqueId.'/'.$request['request_id'];

			$msgData = $this->getLocalisedMsgData($msgCode, $recipient['language_default']);
			$subject = $msgData['msg_object'];
			$body = $this->replaceMsgPlaceholders($msgData['msg_body'], $msgCode,
				[
					'specialtyList' => $specialtyList,
					'code' => _(ucfirst($request['triage_color'])),
					'langList' => $langList,
					'requestId' => $request['request_id'],
					'center' => $request['cc_name'].' ('.$request['country_name'].', '.$request['continent_name'].')',
					'siteLink' => $siteLink
				]
			);

			$mailID = uniqid();
			$mailHTML = $this->getMessageTemplate('Email/template', ['mailID'=>$mailID, 'body'=>nl2br($body), 'showTemplate'=>true]);

			$queueEmailData = [
				'senderId' => $senderID,
				'recipientId' => $recipient['id'],
				'requestId' => $requestID,
				'mailId' => $mailID,
				'subject' => $subject,
				'content' => $mailHTML,
				'type' => 'email',
				'recipient' => $recipient['email'],
				'senderStatus' => $sender['status']
			];
			
			if ($recipient['language_default'] == 'it') {
				$sms_body = 'Controlla la richiesta #'.$request['request_id'].', clicca '.$siteLink;
			} else {
				$sms_body = 'Check request #'.$request['request_id'].', click '.$siteLink;
			}

			$queueSMSData = [
				'senderId' => $senderID,
				'recipientId' => $recipient['id'],
				'requestId' => $requestID,
				'mailId' => '',
				'subject' => '',
				'content' => $sms_body,
				'type' => 'sms',
				'recipient' => $recipient['mobile_number'],
				'senderStatus' => $sender['status']
			];

			setlocale(LC_ALL, $currentLocale);
			return ['email'=>$queueEmailData, 'sms'=>$queueSMSData];
		}

		public function notifyAllReferrals($requestID=0, $msgCode='', $sendSMS=true) {
			$request = $this->db
				->where('r.id', $requestID)
				->getOne('requests r', "r.id request_id, r.user_id applicant_id, (SELECT GROUP_CONCAT(rr.user_id) FROM requests_recipients rr WHERE rr.request_id=r.id) recipients_comma_list");

			$recipientIds = [];
			if (isset($request['recipients_comma_list'])) {
				$recipientIds = explode(',', $request['recipients_comma_list']);
			}

			$returns = [];
			if (is_array($recipientIds) && !empty($recipientIds)) {
				foreach($recipientIds as $recipientId) {
					$returns[] = $this->queueMessage($requestID, $recipientId, $request['applicant_id'], $msgCode, $sendSMS);
				}
			}

			return $returns;
		}

		public function queueMessage($requestID=0, $recipientID=0, $senderID=0, $msgCode='', $sendSMS=true) {
			$msgStructure = $this->getDataForMessageQueue($requestID, $recipientID, $senderID, $msgCode);
			$this->insertMsgInQueue($msgStructure['email']);

			if ($sendSMS)
				$this->insertMsgInQueue($msgStructure['sms']);

			return $msgStructure;
		}

		public function getMessageTemplate($path, $params=[]) {
			if (!empty($params)) extract($params);

			ob_start();
			include VIEWS_DIR.'Elements/Message/'.$path.'.part.php';
			$content = ob_get_clean();

			return $content;
		}

		public function getOpenedRequestsToNofify() {
			$groupedById = [];

			$recipients = $this->db
				->where('r.request_status', self::REQUEST_STATUS_OPENED)
				->where('r.opened_sent', 0)
				->join('requests r', 'r.id=rr.request_id', 'INNER')
				->join('users u', 'u.id=rr.user_id', 'INNER')
				->join('clinical_centers cc', 'cc.id=r.center_id', 'INNER')
				->join('continents cnt', 'cnt.code=cc.continent_code', 'INNER')
				->join('countries cntr', 'cntr.country_iso2_code=cc.country_code', 'INNER')
				->get('requests_recipients rr', null, [
				'r.id request_id',
				'r.user_id applicant_id',
				'rr.user_id recipient_id',
				'r.triage_color',
				'u.id recipient_id',
				'u.name',
				'u.surname',
				'u.language_default',
				'u.email',
				'u.mobile_number',
				'u.mobile_number_chat',
				'u.allow_phone_text',
				'u.allow_phone_chat',
				'u.allow_email_msgs',
				'cc.description cc_name',
				'cntr.country_name',
				'cnt.name continent_name',
				"(SELECT applicant_tb.status FROM users applicant_tb WHERE applicant_tb.id=r.user_id) applicant_status",
				"(SELECT applicant_ltb.language_default FROM users applicant_ltb WHERE applicant_ltb.id=r.user_id) applicant_lang",
				"(SELECT applicant_emtb.email FROM users applicant_emtb WHERE applicant_emtb.id=r.user_id) applicant_email",
				"(SELECT applicant_phtb.mobile_number FROM users applicant_phtb WHERE applicant_phtb.id=r.user_id) applicant_phone",

				"(SELECT GROUP_CONCAT(ums.description SEPARATOR ', ') FROM requests_medical_specialties_to rmst JOIN users_medical_specialties ums ON ums.id=rmst.specialty_id WHERE rmst.request_id=rr.request_id) specialties",
				"(SELECT GROUP_CONCAT(rlt.language_code) FROM requests_languages_to rlt WHERE rlt.request_id=rr.request_id) request_lang_list"
			]);

			//Group by request id
			if (is_array($recipients)) {
				foreach($recipients as $recipient) {
					$groupedById[$recipient['request_id']][] = $recipient;
				}
			}

			return $groupedById;
		}

		public function getLocalisedMsgData($msg_code='', $lang='', $msg_type='') {

			$searchLang = $lang != 'en' ? ['en', $lang] : ['en'];

			$this->db->where('rmt.msg_code', $msg_code);
			$this->db->where('rmt.lang_code', $searchLang, 'IN');

			if ($msg_type != '') {
				$this->db->where('rmt.msg_type', $msg_type);
			}

			$results = $this->db->get('requests_messages_text rmt');

			$msg = [];
			if (is_array($results)) {
				foreach($results as $result) {
					if ($result['lang_code'] == $lang) {
						$msg = $result;
						break;
					}
				}

				if (empty($msg)) {
					foreach($results as $result) {
						if ($result['lang_code'] == 'en') {
							$msg = $result;
							break;
						}
					}
				}
			}

			return $msg;
		}

		public function isRequestPreviouslyReopened($requestID=0) {
			$history = $this->db
				->where('rsh.request_id', $requestID)
				->where('rsh.status_code', 'reopened')
				->getOne('requests_statuses_history rsh', "COUNT(*) AS counter");

			return isset($history['counter']) && (int)$history['counter'] > 0 ? true : false;
		}

		public function translateSpecialties($commaList='') {
			$list = explode(',', $commaList);
			$specialties = [];
			$stringSpecialties = '';

			if (is_array($list)) {
				foreach($list as $item) {
					$specialties[] = _($item);
				}

				$stringSpecialties = implode(', ', $specialties);
			}

			return $stringSpecialties;
		}

		public function setOpenedRequestNotified($requestID=0) {
			return $this->db->where('id', $requestID)->update('requests', ['opened_sent'=>1, 'opened_sent_at'=>date('Y-m-d H:i:s')]);
		}

		/*public function insertMsgInQueue($msgInfo=[]) {
			return $this->db->insert('requests_messages_queue', [
				'sender_id' => $msgInfo['senderId'],
				'recipient_id' => $msgInfo['recipientId'],
				'request_id' => $msgInfo['requestId'],
				'mail_id' => $msgInfo['mailId'],
				'msg_subject' => $msgInfo['subject'],
				'msg_content' => $msgInfo['content'],
				'msg_type' => $msgInfo['type'],
				'msg_recipient' => $msgInfo['recipient'],
				'sender_status' => $msgInfo['senderStatus'],
				'created_at' => date('Y-m-d H:i:s'),
			]);
		}*/
		
		public function insertMsgInQueue($msgInfo=[]) {
			return $this->db->insert('requests_messages_queue', [
				'sender_id' => $msgInfo['senderId'],
				'recipient_id' => $msgInfo['recipientId'],
				'request_id' => $msgInfo['requestId'],
				'mail_id' => $msgInfo['mailId'],
				'msg_subject' => $msgInfo['subject'],
				'msg_content' => $msgInfo['content'],
				'msg_type' => $msgInfo['type'],
				'msg_recipient' => $msgInfo['recipient'],
				'sender_status' => $msgInfo['senderStatus'],
				'attachments' => isset($msgInfo['attachments']) ? $msgInfo['attachments'] : null,
				'delay_at' => isset($msgInfo['delay']) ? $msgInfo['delay'] : null,
				'created_at' => date('Y-m-d H:i:s'),
			]);
		}

		public function replaceMsgPlaceholders($text='', $msgCode='', $data=[]) {
			switch($msgCode) {

				case 'APPLICANT_CONFIRM':
					return vsprintf($text, [$data['specialtyList'], $data['code'], $data['langList'], $data['siteLink']]);
				break;

				case 'NEW_FWD_REQUEST':
					return vsprintf($text, [$data['specialtyList'], $data['code'], $data['langList'], $data['requestId'], $data['center'], $data['siteLink']]);
				break;

				case 'PARTIALLY_REPORTED':
					return vsprintf($text, [$data['specialtyList'], $data['code'], $data['langList'],  $data['requestId'], $data['siteLink']]);
				break;

				case 'REQUEST_UPDATE':
					return vsprintf($text, [$data['code'], $data['langList'],  $data['requestId'], $data['center'], $data['siteLink']]);
				break;

				case 'REQUEST_UPDATE_APPLICANT':
					return vsprintf($text, [$data['code'], $data['langList'],  $data['requestId'], $data['center'], $data['siteLink']]);
				break;

				case 'CLOSED_BY_MODERATOR':
					return vsprintf($text, [$data['specialtyList'], $data['code'], $data['langList'],  $data['requestId'], $data['siteLink']]);
				break;

				default:
					return '';
			}
		}

		public function stringifyLangCodes($langCodeList='') {
			$codes = explode(',', $langCodeList);
			$langs = [];
			$langString = '';
			$labels = ['en'=>_('english'), 'it'=>_('italian'), 'fr'=>_('french'), 'es'=>_('spanish'), 'pt'=>_('portoguese')];

			if (is_array($codes)) {
				foreach($codes as $code) {
					$langs[] = ucfirst(_($labels[$code]));
				}

				$langString = implode(', ', $langs);
			}

			return $langString;
		}

		public function getICD10Categories($lang='en') {
			$categories = [];
			$resultLangs = $this->db->getOne('icd10_languages');
			$supportedLangs = explode('|', $resultLangs['supported_langs']);
			$lang = in_array($lang, $supportedLangs) ? $lang : 'en';

			$this->db->rawQuery("SET SESSION group_concat_max_len = 1000000");

			$results = $this->db
				->where("c.parent_id = ''")
				->where('cl.lang_code', $lang)
				->join('icd10_categories_labels cl', 'cl.category_id=c.id', 'INNER')
				->orderBy('c.position', 'asc')
				->get('icd10_categories c', null, [
					'c.id',
					'cl.description',
					"(SELECT GROUP_CONCAT('\"', csub.id, '\"', ':', '\"', clsub.description, '\"' SEPARATOR ',') FROM icd10_categories csub JOIN icd10_categories_labels clsub ON clsub.category_id=csub.id WHERE clsub.lang_code = '$lang' AND csub.parent_id=c.id) subcategories"
				]);

			if (is_array($results)) {
				foreach($results as $index => $item) {
					$categories[$index]['id'] = $item['id'];
					$categories[$index]['label'] = $item['description'];
					//$categories[$index]['subcategories-raw'] = $item['subcategories'];
					$categories[$index]['subcategories'] = json_decode('{'.$item['subcategories'].'}', true);
				}
			}

			return $categories;
		}

		public function getDeseasesByICD10Category($category='', $lang='en', $selectedDeseases=[]) {
			$deseases = [];
			$resultLangs = $this->db->getOne('icd10_languages');
			$supportedLangs = explode('|', $resultLangs['supported_langs']);
			$lang = in_array($lang, $supportedLangs) ? $lang : 'en';

			$this->db->rawQuery("SET SESSION group_concat_max_len = 1000000");

			$results = $this->db
				->where('category_id', $category)
				->where('parent_id', '')
				->where('idl.lang_code', $lang)
				->join('icd10_desease_labels idl', 'idl.desease_id=d.id', 'INNER')
				->get('icd10_deseases d', null, [
					'd.id',
					'd.category_id',
					'd.description',
					"(SELECT GROUP_CONCAT('\"', dsub.id, '\"', ':', '\"', iclsub.description, '\"' SEPARATOR ',') FROM icd10_deseases dsub JOIN icd10_desease_labels iclsub ON iclsub.desease_id=dsub.id WHERE iclsub.lang_code = '$lang' AND dsub.parent_id=d.id) subdeseases"
				]);

			if (is_array($results)) {
				foreach($results as $index => $item) {
					$deseases[$index]['id'] = $item['id'];
					$deseases[$index]['label'] = $item['description'];
					$deseases[$index]['disabled'] = in_array($item['id'], $selectedDeseases) ? 'disabled' : '';

					$subdeseases = json_decode('{'.$item['subdeseases'].'}', true);

					if (is_array($subdeseases)) {
						foreach($subdeseases as $subId => $subLabel) {

							unset($subdeseases[$subId]);

							$subdeseases[$subId]['label'] = $subLabel;

							if (in_array($subId, $selectedDeseases)) {
								$subdeseases[$subId]['disabled'] = 'disabled';
							} else {
								$subdeseases[$subId]['disabled'] = '';
							}
						}

						$deseases[$index]['subdeseases'] = $subdeseases;

					} else {
						$deseases[$index]['subdeseases'] = [];
					}
				}
			}

			return $deseases;
		}

		public function getECD10ListByRequestId($requestId=0, $lang_code='en') {
			$resultLangs = $this->db->getOne('icd10_languages');
			$supportedLangs = explode('|', $resultLangs['supported_langs']);
			$lang_code = in_array($lang_code, $supportedLangs) ? $lang_code : 'en';

			$icd10 = $this->db
				->where('rst.request_id', $requestId)
				->where('idl.lang_code', $lang_code)
				->join('icd10_deseases icdd', 'icdd.id=rst.symptom_id', 'INNER')
				->join('icd10_desease_labels idl', 'idl.desease_id=rst.symptom_id', 'INNER')
				->get('requests_symptoms_to rst', null, [
				'icdd.id',
				'idl.description label',
				"(SELECT idlsub.description FROM icd10_desease_labels idlsub WHERE idlsub.desease_id = icdd.parent_id AND idlsub.lang_code = '$lang_code') parent_label"
				]);

			return $icd10;
		}

		public function getDeseaseByKeyword($keyword='', $langCode='en', $selectedDeseases=[]) {
			$deseases = [];

			$results = $this->db
				->where("idl.description LIKE '%$keyword%'")
				->where('idl.lang_code', $langCode)
				->where("d.parent_id <> ''")
				->join('icd10_desease_labels idl', 'idl.desease_id=d.id', 'INNER')
				->get('icd10_deseases d', 10, [
				'idl.description',
				'idl.desease_id',
				'd.parent_id',
				"(SELECT idlsub.description FROM icd10_desease_labels idlsub WHERE idlsub.desease_id = d.parent_id AND idlsub.lang_code = '$langCode') parent_label"
				]);

			if (is_array($results) && !empty($results)) {
				foreach($results as $index => $item) {
					$deseases[$item['parent_id']]['id'] = $item['parent_id'];
					$deseases[$item['parent_id']]['label'] = $item['parent_label'];
					$deseases[$item['parent_id']]['disabled'] = in_array($item['parent_id'], $selectedDeseases) ? 'disabled' : '';
					$deseases[$item['parent_id']]['subdeseases'][$item['desease_id']]['id'] = $item['desease_id'];
					$deseases[$item['parent_id']]['subdeseases'][$item['desease_id']]['label'] = $item['description'];
					$deseases[$item['parent_id']]['subdeseases'][$item['desease_id']]['disabled'] = in_array($item['desease_id'], $selectedDeseases) ? 'disabled' : '';;
				}
			}

			/*foreach($results as $index => $item) {
					$deseases[$index]['id'] = $item['parent_id'];
					$deseases[$index]['label'] = $item['parent_label'];
					$deseases[$index]['disabled'] = in_array($item['parent_id'], $selectedDeseases) ? 'disabled' : '';
					$deseases[$index]['subdeseases'][$item['desease_id']]['id'] = $item['desease_id'];
					$deseases[$index]['subdeseases'][$item['desease_id']]['label'] = $item['description'];
					$deseases[$index]['subdeseases'][$item['desease_id']]['disabled'] = in_array($item['desease_id'], $selectedDeseases) ? 'disabled' : '';;
			}*/

			return $deseases;
		}

		public function getExams($checkedExams=[]) {
			$axams = [];

			$this->db->rawQuery("SET SESSION group_concat_max_len = 1000000");

			$results = $this->db
				->get('requests_exams re', null, [
				're.id',
				're.standard_description',
				're.exam_type',
				"(SELECT GROUP_CONCAT('\"', resub.id, '\"', ':', '\"', resub.standard_description, '\"') FROM requests_exams resub WHERE resub.parent_id=re.id) children"
				]);

			if (is_array($results)) {
				foreach($results as $index => $item) {
					$axams[$item['standard_description']][$item['id']]['id'] = $item['id'];
					$axams[$item['standard_description']][$item['id']]['description'] = _($item['standard_description']);
					$axams[$item['standard_description']][$item['id']]['type'] = $item['exam_type'];
					$axams[$item['standard_description']][$item['id']]['checked'] = false; //Default

					if (isset($checkedExams[$item['exam_type']])) {
						foreach($checkedExams[$item['exam_type']] as $checkeds) {
							if ($checkeds['id'] == $item['id']) {
								$axams[$item['standard_description']][$item['id']]['checked'] = true;
								break;
							}
						}
					}

					$childrenData = json_decode('{'.stripslashes($item['children']).'}', true);
					$children = [];

					if (is_array($childrenData) && !empty($childrenData)) {
						foreach($childrenData as $childId => $childStandardLabel) {
							$children[$childId]['description'] = _($childStandardLabel);
							$children[$childId]['checked'] = false;

							if (isset($checkedExams[$item['exam_type']])) {
								foreach($checkedExams[$item['exam_type']] as $checkeds) {
									if ($checkeds['id'] == $childId) {
										$children[$childId]['checked'] = true;
										break;
									}
								}
							}

						}
					}

					$axams[$item['standard_description']][$item['id']]['children'] = $children;
				}
			}

			return $axams;
		}

		public function getWizardsByRequestId($requestId=0) {
			$wizards = [];

			$results = $this->db
				->where('request_id', $requestId)
				->join('requests_exams re', 're.id=rwt.exam_id', 'INNER')
				->get('requests_wizards_to rwt', null, [
					're.id',
					're.standard_description',
					'rwt.exam_type',
					"(SELECT re_parent.standard_description FROM requests_exams re_parent WHERE re_parent.id=re.parent_id) parent_name"
				]);

			if (is_array($results)) {
				foreach($results as $index => $item) {
					$wizards[$item['exam_type']][$index]['id'] = $item['id'];

					$description = $item['parent_name'] != '' ? _($item['parent_name']).' / '._($item['standard_description']) : _($item['standard_description']);

					$wizards[$item['exam_type']][$index]['description'] = $description;
				}
			}

			return $wizards;
		}

		public function getWizardsDermaPositions($requestId=0) {
			$positions = [];
			$results = $this->db
				->where('request_id', $requestId)
				->get('requests_wizard_derma_position_to');

			if (is_array($results) && !empty($results)) {
				foreach($results as $item) {
					$positions[$item['position_type']] = $item;
				}
			}

			return $positions;
		}

		public function getWizardsEarDeseases($requestId=0) {
			$deseases = [];
			$results = $this->db
				->where('request_id', $requestId)
				->get('requests_wizard_ear_deseases_to');

			if (is_array($results) && !empty($results)) {
				foreach($results as $item) {
					$deseases[$item['desease_type']] = $item;
				}
			}

			return $deseases;
		}

		public function checkPartialUploads() {
			$path = MEDIA_TMP_DIR;
			$infoFiles = glob($path.'*.info');

			return $infoFiles;
		}

		public function cron() {
			shell_exec('cd '.$this->config['job']['path'].'; /usr/local/bin/php cron.php > /dev/null 2>/dev/null &');
		}

	}
