<?php

use Authority\Repo\User\UserInterface;
use Authority\Repo\Group\GroupInterface;
use Authority\Service\Form\Register\RegisterForm;
use Authority\Service\Form\User\UserForm;
use Authority\Service\Form\Login\LoginForm;
use Authority\Service\Form\ResendActivation\ResendActivationForm;
use Authority\Service\Form\ForgotPassword\ForgotPasswordForm;
use Authority\Service\Form\ChangePassword\ChangePasswordForm;
use Authority\Service\Form\SuspendUser\SuspendUserForm;

class UserController extends BaseController {

	protected $user;
	protected $group;
	protected $registerForm;
	protected $userForm;
	protected $loginForm;
	protected $resendActivationForm;
	protected $forgotPasswordForm;
	protected $changePasswordForm;
	protected $suspendUserForm;

	/**
	 * Instantiate a new UserController
	 */
	public function __construct(
	UserInterface $user, GroupInterface $group, RegisterForm $registerForm, UserForm $userForm, LoginForm $loginForm, ResendActivationForm $resendActivationForm, ForgotPasswordForm $forgotPasswordForm, ChangePasswordForm $changePasswordForm, SuspendUserForm $suspendUserForm) {
		$this->user									 = $user;
		$this->group								 = $group;
		$this->registerForm					 = $registerForm;
		$this->userForm							 = $userForm;
		$this->loginForm						 = $loginForm;
		$this->resendActivationForm	 = $resendActivationForm;
		$this->forgotPasswordForm		 = $forgotPasswordForm;
		$this->changePasswordForm		 = $changePasswordForm;
		$this->suspendUserForm			 = $suspendUserForm;

		//Check CSRF token on POST
		$this->beforeFilter('csrf', array('on' => 'post'));

		if (Sentry::check()) {
			$user = User::find(Sentry::getUser()->id);
			
			if(!Request::is('users/'.Sentry::getUser()->id.'/change')){
				$this->beforeFilter('hasRole:' . Role::ROLE_USERS_EDITOR);
			} else if (Request::is('users/'.Sentry::getUser()->id.'/change')){ // смена своего пароля
				$id	= Request::segment(2);
				if( $id != Sentry::getUser()->id ){
					$this->beforeFilter('hasRole:' . Role::ROLE_USERS_EDITOR);
				}
			}
		}
		else {
			$this->beforeFilter('auth', array('except' => array('forgot', 'reset', 'change') ));
		}
	}

	protected function checkUser($user) {
		if ($user == null) {
			return false;
		}
		if ($user->id == Sentry::getUser()->id) {
			return true;
		}
		if (!Sentry::getUser()->hasAccess('admin') && $user->user_id != Sentry::getUser()->id) {
			return false;
		}
		return true;
	}

	/**
	 * Display a listing of the resource.
	 *
	 * @return Response
	 */
	public function index() {
		if ($this->user->hasAccess('admin')) {
			$users = User::allUsers();
		}
		else {
			$users = User::myUsers();
		}

		return View::make('users.index')->with('users', $users);
	}

	/**
	 * Show the form for creating a new user.
	 *
	 * @return Response
	 */
	public function create() {
		return View::make('users.create');
	}

	/**
	 * Store a newly created user.
	 *
	 * @return Response
	 */
	public function store() {
		// Form Processing
		$input		 = Input::all();
		$needLogin = false;
		if (!Sentry::getUser()) {
			$needLogin = true;
		}

		$input['phone']		 = $this->preparePhone($input['phone']);
		$input['user_id']	 = Sentry::getUser() ? Sentry::getUser()->id : DB::raw('NULL');
		$result						 = $this->registerForm->save($input);

		if ($result['success']) {
			Event::fire('user.signup', array(
					'email'			 => $result['mailData']['email'],
					'password'	 => $result['mailData']['password'],
					'first_name' => $result['mailData']['first_name'],
					'last_name'	 => $result['mailData']['last_name'],
			));

			// Success!
			Session::flash('success', $result['message']);

			if ($needLogin) {
				$result = $this->loginForm->save($input);
				if ($result['success']) {
					Event::fire('user.login', array(
							'userId'				 => $result['sessionData']['userId'],
							'userEmail'			 => $result['sessionData']['userEmail'],
							'userPhone'			 => $result['sessionData']['userPhone'],
							'userFirstName'	 => $result['sessionData']['userFirstName'],
							'userLastName'	 => $result['sessionData']['userLastName']
					));
					// Success!
					return Redirect::to('/');
				}
				else {
					return Redirect::route('home');
				}
			}
			else {
				return Redirect::to('/users');
			}
		}
		else {
			Session::flash('error', $result['message']);
			return Redirect::action('UserController@create')
											->withInput()
											->withErrors($this->registerForm->errors());
		}
	}

	/**
	 * Display the specified resource.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function show($id) {
		$user = $this->user->byId($id);

		if (!$this->checkUser($user)) {
			// @codeCoverageIgnoreStart
			return \App::abort(404);
			// @codeCoverageIgnoreEnd
		}

		return View::make('users.show')->with('user', $user)->with('userProjects', User::find($id)->projects->toArray());
	}

	/**
	 * Show the form for editing the specified resource.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function edit($id) {
		$user = $this->user->byId($id);

		if (!$this->checkUser($user)) {
			// @codeCoverageIgnoreStart
			return \App::abort(404);
			// @codeCoverageIgnoreEnd
		}

		$currentGroups = $user->getGroups()->toArray();
		$userGroups		 = array();
		foreach ($currentGroups as $group) {
			array_push($userGroups, $group['name']);
		}
		$allGroups = $this->group->all();

		$currentRoles	 = User::find($id)->roles->toArray();
		$userRoles		 = array();
		foreach ($currentRoles as $role) {
			array_push($userRoles, $role['id']);
		}
		$allRoles = Role::orderBy('id', 'ASC')->get();

		$currentProjects = User::find($id)->projects->toArray();
		$userProjects		 = array();
		foreach ($currentProjects as $project) {
			array_push($userProjects, $project['id']);
		}

		$allProjects = false;
		if (Sentry::getUser()->hasAccess('admin') || User::find(Sentry::getUser()->id)->hasRole(Role::ROLE_USERS_EDITOR)) {
			$allProjects = Project::orderBy('name', 'ASC')->get();
		}
		elseif (Sentry::getUser()->hasAccess('moderator')) {
			$allProjects = Project::my()->orderBy('name', 'ASC')->get();
		}

		return View::make('users.edit')
										->with('user', $user)
										->with('userGroups', $userGroups)
										->with('allGroups', $allGroups)
										->with('userRoles', $userRoles)
										->with('allRoles', $allRoles)
										->with('userProjects', $userProjects)
										->with('allProjects', $allProjects);
	}

	/**
	 * Update the specified resource in storage.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function update($id) {
		if (!is_numeric($id)) {
			// @codeCoverageIgnoreStart
			return \App::abort(404);
			// @codeCoverageIgnoreEnd
		}

		$input					 = Input::all();
		$input['phone']	 = $this->preparePhone($input['phone']);
		// Form Processing
		$result					 = $this->userForm->update($input);

		// Update project memberships
		$input = Input::all();
		$user	 = User::find($id);
		if (!$this->checkUser($user)) {
			return \App::abort(404);
		}
		$operator = User::find(Sentry::getUser()->id);
		if ($operator->hasAccess('admin') || User::find(Sentry::getUser()->id)->hasRole(Role::ROLE_USERS_EDITOR)) {
			if (isset($input['projects'])) {
				$user->projects()->sync(array_keys($input['projects']));
			}
			else {
				$user->projects()->detach();
			}
			if (isset($input['roles'])) {
				$user->roles()->sync(array_keys($input['roles']));
			}
			else {
				$user->roles()->detach();
			}
		}

//		if (isset($input['roles'][Role::ROLE_FRANCHISEES])) {
//			$user->user_id = DB::raw('NULL');
//			$user->save();
//		}

		if ($result['success']) {
			// Success!
			Session::flash('success', $result['message']);
			return Redirect::action('UserController@index');
		}
		else {
			Session::flash('error', $result['message']);
			return Redirect::action('UserController@edit', array($id))
											->withInput()
											->withErrors($this->userForm->errors());
		}
	}

	/**
	 * Remove the specified resource from storage.
	 *
	 * @param  int  $id
	 * @return Response
	 */
	public function destroy($id) {
		if (!is_numeric($id)) {
			// @codeCoverageIgnoreStart
			return \App::abort(404);
			// @codeCoverageIgnoreEnd
		}

		$user = User::withTrashed()->find($id);
		if (!$this->checkUser($user)) {
			return \App::abort(404);
		}

		if ($user->deleted_at) {
			$user->restore();
			Session::flash('success', 'Пользователь восстановлен');
			return Redirect::to('/users');
		}
		else {
			$user->delete();
			Session::flash('success', 'Пользователь удален');
			return Redirect::to('/users');
		}
	}

	/**
	 * Activate a new user
	 * @param  int $id
	 * @param  string $code
	 * @return Response
	 */
	public function activate($id, $code) {
		if (!is_numeric($id)) {
			// @codeCoverageIgnoreStart
			return \App::abort(404);
			// @codeCoverageIgnoreEnd
		}

		$user = User::find($id);
		if (!$this->checkUser($user)) {
			return \App::abort(404);
		}

		$result = $this->user->activate($id, $code);

		if ($result['success']) {
			// Success!
			Session::flash('success', $result['message']);
			return Redirect::route('home');
		}
		else {
			Session::flash('error', $result['message']);
			return Redirect::route('home');
		}
	}

	/**
	 * Process resend activation request
	 * @return Response
	 */
	public function resend() {
		// Form Processing
		$result = $this->resendActivationForm->resend(Input::all());

		if ($result['success']) {
			Event::fire('user.resend', array(
					'email'					 => $result['mailData']['email'],
					'userId'				 => $result['mailData']['userId'],
					'activationCode' => $result['mailData']['activationCode']
			));

			// Success!
			Session::flash('success', $result['message']);
			return Redirect::route('home');
		}
		else {
			Session::flash('error', $result['message']);
			return Redirect::route('profile')
											->withInput()
											->withErrors($this->resendActivationForm->errors());
		}
	}

	/**
	 * Process Forgot Password request
	 * @return Response
	 */
	public function forgot() {
		// Form Processing
		$result = $this->forgotPasswordForm->forgot(Input::all());

		if ($result['success']) {
			Event::fire('user.forgot', array(
					'email'			 => $result['mailData']['email'],
					'userId'		 => $result['mailData']['userId'],
					'resetCode'	 => $result['mailData']['resetCode']
			));

			// Success!
			Session::flash('success', $result['message']);
			return Redirect::route('home');
		}
		else {
			Session::flash('error', $result['message']);
			return Redirect::route('forgotPasswordForm')
											->withInput()
											->withErrors($this->forgotPasswordForm->errors());
		}
	}

	/**
	 * Process a password reset request link
	 * @param  [type] $id   [description]
	 * @param  [type] $code [description]
	 * @return [type]       [description]
	 */
	public function reset($id, $code) {
		if (!is_numeric($id)) {
			// @codeCoverageIgnoreStart
			return \App::abort(404);
			// @codeCoverageIgnoreEnd
		}

		$user = User::find($id);
		/*if (!$this->checkUser($user)) {
			return \App::abort(404);
		}*/

		if ($user == null) {
			return \App::abort(404);
		}
		
		$result = $this->user->resetPassword($id, $code);

		if ($result['success']) {
			Event::fire('user.newpassword', array(
					'email'				 => $result['mailData']['email'],
					'newPassword'	 => $result['mailData']['newPassword']
			));

			// Success!
			Session::flash('success', $result['message']);
			return Redirect::route('home');
		}
		else {
			Session::flash('error', $result['message']);
			return Redirect::route('home');
		}
	}

	/**
	 * Process a password change request
	 * @param  int $id
	 * @return redirect
	 */
	public function change($id) {
		if (!is_numeric($id)) {
			// @codeCoverageIgnoreStart
			return \App::abort(404);
			// @codeCoverageIgnoreEnd
		}

		$user = User::find($id);
		/*if (!$this->checkUser($user)) {
			return \App::abort(404);
		}*/
/*
		if (!Sentry::getUser()->hasAccess('admin') && $user->id != Sentry::getUser()->id) {
			return false;
		}*/
		
		$data				 = Input::all();
		$data['id']	 = $id;

		// Form Processing
		$result = $this->changePasswordForm->change($data);

		if ($result['success']) {
			// Success!
			Session::flash('success', $result['message']);
			return Redirect::route('home');
		}
		else {
			Session::flash('error', $result['message']);
			return Redirect::action('UserController@edit', array($id))
											->withInput()
											->withErrors($this->changePasswordForm->errors());
		}
	}

	/**
	 * Process a suspend user request
	 * @param  int $id
	 * @return Redirect
	 */
	public function suspend($id) {
		if (!is_numeric($id)) {
			// @codeCoverageIgnoreStart
			return \App::abort(404);
			// @codeCoverageIgnoreEnd
		}

		$user = User::find($id);
		if (!$this->checkUser($user)) {
			return \App::abort(404);
		}

		// Form Processing
		$result = $this->suspendUserForm->suspend(Input::all());

		if ($result['success']) {
			// Success!
			Session::flash('success', $result['message']);
			return Redirect::to('users');
		}
		else {
			Session::flash('error', $result['message']);
			return Redirect::action('UserController@suspend', array($id))
											->withInput()
											->withErrors($this->suspendUserForm->errors());
		}
	}

	/**
	 * Unsuspend user
	 * @param  int $id
	 * @return Redirect
	 */
	public function unsuspend($id) {
		if (!is_numeric($id)) {
			// @codeCoverageIgnoreStart
			return \App::abort(404);
			// @codeCoverageIgnoreEnd
		}

		$user = User::find($id);
		if (!$this->checkUser($user)) {
			return \App::abort(404);
		}

		$result = $this->user->unSuspend($id);

		if ($result['success']) {
			// Success!
			Session::flash('success', $result['message']);
			return Redirect::to('users');
		}
		else {
			Session::flash('error', $result['message']);
			return Redirect::to('users');
		}
	}

	/**
	 * Ban a user
	 * @param  int $id
	 * @return Redirect
	 */
	public function ban($id) {
		if (!is_numeric($id)) {
			// @codeCoverageIgnoreStart
			return \App::abort(404);
			// @codeCoverageIgnoreEnd
		}

		$user = User::find($id);
		if (!$this->checkUser($user)) {
			return \App::abort(404);
		}

		$result = $this->user->ban($id);

		if ($result['success']) {
			// Success!
			Session::flash('success', $result['message']);
			return Redirect::to('users');
		}
		else {
			Session::flash('error', $result['message']);
			return Redirect::to('users');
		}
	}

	public function unban($id) {
		if (!is_numeric($id)) {
			// @codeCoverageIgnoreStart
			return \App::abort(404);
			// @codeCoverageIgnoreEnd
		}

		$user = User::find($id);
		if (!$this->checkUser($user)) {
			return \App::abort(404);
		}

		$result = $this->user->unBan($id);

		if ($result['success']) {
			// Success!
			Session::flash('success', $result['message']);
			return Redirect::to('users');
		}
		else {
			Session::flash('error', $result['message']);
			return Redirect::to('users');
		}
	}

	public function addMoney() {
		$input = Input::all();
		if (!isset($input['add_money_user_id']) || !is_numeric($input['add_money_user_id']) || !isset($input['add_money_amount']) || !is_numeric($input['add_money_amount']) || !isset($input['add_money_comment'])) {
			return App::to('users');
		}
		$id = $input['add_money_user_id'];

		$user = User::find($id);
		if (!$this->checkUser($user)) {
			return App::abort(404);
		}

		$user->changeMoney($input['add_money_amount'], $input['add_money_comment']);

		Session::flash('success', "Баланс пользователя изменен");
		return Redirect::to('users');
	}

}
