<?php
class BaseUser extends AppModel {

	public $defaultModel = 'User';
	public $authenticationFields = array(
		'username' => 'username',
		'password' => 'password'
	);
	public $registrationFields = array('name', 'email', 'phone', 'address');
	public $changePassFields = array('old_pass', 'new_pass', 'repeated_pass');
	public $recoverPassFields = array('email');

# ~ Checks if there are all fields provided  - - - - - - - - - - - - - - - - - #
	private function validateData($data, $fields) {
		$validInput = true;

		foreach($fields as $field) {
			if(!isset($data[$this->defaultModel][$field]) || empty($data[$this->defaultModel][$field])) {
				$validInput = false;
				break;
			}
		}

		return $validInput;
	}

# ~ Logs in user with provided data  - - - - - - - - - - - - - - - - - - - - - #
	public function login($data) {

		# Check for all fields
		if(!$this->validateData($data, $this->authenticationFields)) {
			return array(
				'status' => 'failed',
				'message' => __('Niste uneli sve podatke.')
			);
		}

		# Generate conditions from all fields.
		$conditions = array();
		foreach($this->authenticationFields as $field) {
			$conditions["{$this->defaultModel}.{$field}"] = $data[$this->defaultModel][$field];
		}

		# Check if there is a user with that data
		$user = $this->find('first', compact('conditions'));

		# If there is one, trigger onLogInOK function.
		if(!empty($user)) {
			CakeSession::write(strtolower($this->defaultModel), $user);
			return $this->onLogInOK();

		} else {
			return $this->onLogInFailed();
		}

	}

# ~ Registars user with provided data  - - - - - - - - - - - - - - - - - - - - #
	public function register($data) {

		# Validate registration fields
		$validationStatus = $this->validateRegistrationFields($data);
		if($validationStatus !== true) {
			return $validationStatus;
		}


		# Check if there is user with same keyfield
		$check = $this->find('first', array('conditions' => array("{$this->defaultModel}.{$this->authenticationFields['username']}" => $data[$this->defaultModel][$this->authenticationFields['username']])));
		if(!empty($check)) {
			return array(
				'status' => 'failed',
				'message' => __('Već postoji korisnik sa tim email-om u našoj bazi.')
			);
		}

		# Generate random password and save user to database
		$password = getRandomString(8);
		$data[$this->defaultModel][$this->authenticationFields['password']] = $password;
		if($this->save($data)) {
			$email = new CakeEmail();
			$email->from(array('gateway@intellex.rs' => 'Kockica'))
				->to($data[$this->defaultModel]['email'])
				->subject('Registracija korisnika')
				->template('registration')
				->emailFormat('html')
				->viewVars(array('data' => $data, 'generatedPass' => $password))
				->send();

			return $this->onRegistrationOK();
		} else {
			return $this->onRegistrationFailed();
		}
	}


# ~ Changes user passwordd - - - - - - - - - - - - - - - - - - - - - - - - - - #
	public function changePass($data) {

		# Validate changePassFields fields
		$validationStatus = $this->validateChangePassFields($data);
		if($validationStatus !== true) {
			return $validationStatus;
		}

		# Find user with old password and change it
		$check = $this->find('first', array('conditions' => array("{$this->defaultModel}.{$this->authenticationFields['password']}" => $data[$this->defaultModel]['old_pass'])));
		$key = strtolower($this->defaultModel) . "." . $this->defaultModel . ".{$this->authenticationFields['password']}";

		if(!empty($check) && CakeSession::read($key) == $data[$this->defaultModel]['old_pass']) {
			$check[$this->defaultModel][$this->authenticationFields['password']] = $data[$this->defaultModel]['new_pass'];
			if($this->save($check)) {
				CakeSession::write(strtolower($this->defaultModel). ".{$this->defaultModel}.{$this->authenticationFields['password']}", $data[$this->defaultModel]['new_pass']);
				return $this->onChangePassOK();
			}
		}
		return $this->onChangePassFailed();
	}


# ~ Forgog password logics - - - - - - - - - - - - - - - - - - - - - - - - - - #
	public function recoverPass($data) {

		# Validate changePassFields fields
		$validationStatus = $this->validateRecoverPassFields($data);
		if($validationStatus !== true) {
			return $validationStatus;
		}

		# Generate conditions based on provided fields
		$conditions = array();
		foreach($this->recoverPassFields as $field) {
			$conditions["{$this->defaultModel}.{$field}"] = $data[$this->defaultModel][$field];
		}

		# Find user
		$check = $this->find('first', compact('conditions'));

		# Generate new password for user, save it and send email
		if(!empty($check)) {
			$newPass = getRandomString(8);
			$check[$this->defaultModel][$this->authenticationFields['password']] = $newPass;
			if($this->save($check)) {
				$email = new CakeEmail();
				$email->from(array('gateway@intellex.rs' => 'Kockica'))
					->to($check[$this->defaultModel]['email'])
					->subject('Nova šifra')
					->template('passrecovery')
					->emailFormat('html')
					->viewVars(array('data' => $check, 'newPass' => $newPass))
					->send();

				return $this->onPassRecoverOK();
			}

		} else {
			return $this->onPassRecoverFailed();
		}
	}


# Resend pass  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
	public function resendPass($data) {
		# Validate resendPass fields
		$validationStatus = $this->validateMissing($data, array($this->authenticationFields['username']));
		if($validationStatus !== true) {
			return $validationStatus;
		}

		# Generate conditions based on provided fields
		$conditions = array();
		$conditions["{$this->defaultModel}.{$this->authenticationFields['username']}"] = $data[$this->defaultModel][$this->authenticationFields['username']];

		# Find user
		$check = $this->find('first', compact('conditions'));

		# Generate new password for user, save it and send email
		if(!empty($check)) {
			$generatedPass = getRandomString(8);
			$check[$this->defaultModel][$this->authenticationFields['password']] = $generatedPass;
			if($this->save($check)) {
				$email = new CakeEmail();
				$email->from(array('gateway@intellex.rs' => 'Kockica'))
					->to($check[$this->defaultModel]['email'])
					->subject('Registracija korisnika')
					->template('registration')
					->emailFormat('html')
					->viewVars(array('data' => $check, 'generatedPass' => $generatedPass))
					->send();

				return $this->onPassResendOK();
			}

		} else {
			return $this->onPassResendFailed();
		}
	}

# ~ Callback functions   - - - - - - - - - - - - - - - - - - - - - - - - - - - #
	public function onLogInOK() {
		$key = strtolower($this->defaultModel) . "." . $this->defaultModel . ".name";
		return array(
				'status' => 'succeded',
				'message' => __('Uspešno ste se ulogovali kao'). ": " . CakeSession::read("{$key}")
			);
	}


	public function onLogInFailed() {
		return array(
				'status' => 'failed',
				'message' => __('Uneti podaci ne odgovaraju nijednom korisniku u našoj bazi. Molimo pokušajte opet.')
			);
	}

	public function onRegistrationOK() {
		return array(
				'status' => 'succeded',
				'message' => __('Uspešno ste se registrovali. Šifra je poslata na Vašu email adresu')
			);
	}

	public function onRegistrationFailed() {
		return array(
				'status' => 'failed',
				'message' => __('Došlo je do problema, molimo pokušajte sa registracijom kasnije')
			);
	}

	public function onChangePassOK() {
		return array(
				'status' => 'succeded',
				'message' => __('Šifra je uspešno promenjena')
			);
	}

	public function onChangePassFailed() {
		return array(
				'field' => 'old_pass',
				'message' => __('Niste uneli ispravnu staru šifru')
			);
	}

	public function onPassRecoverOK() {
		return array(
					'status' => 'succeded',
					'message' => __('Na Vašu e-mail adresu je poslata Vaša nova šifra')
				);
	}

	public function onPassRecoverFailed() {
		return array(
					'status' => 'failed',
					'message' => __('Nije pronađen nijedan korisnik sa tim podacima')
				);
	}

	public function onPassResendOK() {
		return array(
					'status' => 'succeded',
					'message' => __('Na Vašu e-mail adresu je poslat nov email')
				);
	}

	public function onPassResendFailed() {
		return array(
					'status' => 'failed',
					'message' => __('Nije pronađen nijedan korisnik sa tim podacima')
				);
	}

	public function validateRegistrationFields($data) {

		# Get missing values
		$missing = $this->validateMissing($data, $this->registrationFields);
		if($missing !== true) {
			return $missing;
		}

		# Validate email field
		if(!Validation::email($data[$this->defaultModel]['email'])) {
			return array('field' => "data[{$this->defaultModel}][email]" , 'message' => __('Email nije u dobrom formatu'));
		}

		return true;
	}


/* Validate fields for password change */
	public function validateChangePassFields($data) {

		# Get missing values
		$missing = $this->validateMissing($data, $this->changePassFields);
		if($missing !== true) {
			return $missing;
		}

		# New pass field must have same value as repeated pass field
		if($data[$this->defaultModel]['new_pass'] != $data[$this->defaultModel]['repeated_pass']) {
			return array(
				'field' => "repeated_pass",
				'message' => __('Unešene šifre se ne poklapaju')
			);
		}
		return true;
	}


/* Return fields with empty values */
	public function validateRecoverPassFields($data) {

		# Get missing values
		$missing = $this->validateMissing($data, $this->recoverPassFields);
		if($missing !== true) {
			return $missing;
		}

		# Validate email field
		if(!Validation::email($data[$this->defaultModel]['email'])) {
			return array(
				'field' => "data[{$this->defaultModel}][email]",
				'message' => __('Email nije u dobrom formatu')
			);
		}

		# Validate pib field
		if(!is_numeric($data[$this->defaultModel]['pib'])) {
			return array(
				'field' => "data[{$this->defaultModel}][pib]",
				'message' => __('PIB mora biti celobrojan')
			);
		}
		return true;
	}


/* Return fields with empty values */
	private function validateMissing($data, $fields) {
		foreach($fields as $field) {
			if(!isset($data[$this->defaultModel][$field]) || empty($data[$this->defaultModel][$field])) {
				return array('field' => "data[{$this->defaultModel}][{$field}]" , 'message' => __('Ovo polje je obavezno'));
			}
		}

		return true;
	}


}
