<?php
use lithium\storage\Session;
use lithium\security\Auth;
use lithium\util\String;
use app\models\User;
use lithium\core\Libraries;
use lithium\action\Dispatcher;
use lithium\net\http\Router;
use lithium\action\Response;
use lithium\security\Password;

Session::config(array(
	'cookie' => array('adapter' => 'Cookie'),
	'default' => array('adapter' => 'Php'),
	'flash_message' => array('adapter' => 'Php')
));

Auth::config(array(
	'default' => array(
		'adapter'  => 'Form',
		'model'    => 'User',
		'cookie'   => '',
		'fields'   => array('username', 'password'),
		//'scope'    => array('active' => 'true'), //The active field must be true otherwise they can't auth, though we need
		//to eventually send them to a page that explains they are banned.
		'session'  => array('options' => array('name' => 'default')),
		'validators' => array(
			'password' => function($form, $data) {
				return password::check($form, $data);
		}))
));

$secret = "cake";

// Adds remember feature for form-based authentications.
Auth::applyFilter('check', function($self, $params, $chain) use ($secret)
{
	$query = 'first';
	$scope = array();
	extract($self::invokeMethod('_config', array($params['name'])));
	if ($result = $chain->next($self, $params, $chain))
	{
		$request = $params['credentials'];
		if ($request && $adapter == 'Form' && !empty($request->data['remember']))
		{
			$data = array_intersect_key($result, array_combine($fields, $fields));
			$data = serialize($data);
			Session::write(
				"Auth.{$params['name']}",
				base64_encode($data),
				array('name' => 'cookie')
			);
		}
		return $result;
	}
	if ($adapter == 'Form')
	{
		$data = Session::read("Auth.{$params['name']}", array('name' => 'cookie'));
		if ($data)
		{
			$data = base64_decode($data);
			$data = unserialize($data);
			if (array_keys($data) == $fields)
			{
				$model = Libraries::locate('models', $model);
				$data = array_map('strval', $data);
				$user = $model::$query($scope + $data);
				if ($user) {
					return $self::set($params['name'], $user->data());
				}
			}
		}
	}
	return $result;
});

// Removes remember cookie after sign out.
Auth::applyFilter('clear', function($self, $params, $chain)
{
	$config = $self::invokeMethod('_config', array($params['name']));
	if ($config['adapter'] == 'Form')
	{
		if (Session::read("Auth.{$params['name']}", array('name' => 'cookie')))
		{
			Session::delete("Auth.{$params['name']}", array('name' => 'cookie'));
		}
	}
	return $chain->next($self, $params, $chain);
});

//So that we can filter a bunch of methods in one
Dispatcher::applyFilter('_callable', function($self, $params, $chain)
{
	//Invoke the _callable method, then execute the logic below
	$ctrl = $chain->next($self, $params, $chain);

	//if the user is logged in
	$user = Auth::check('default');
	if($user)
	{
		//check if they are accessing an admin function
		if ($ctrl->request->controller == 'admin' && !($user['level'] == 'root' || $user['level'] == 'admin'))
		{
			return function() use ($request)
			{
				//Users / index isn't public derp.
				return new Response(compact('request') + array('location' => '/'));
			};
		}

		//If they aren't trying to access admin, return
		return $ctrl;
	}
	//If they are performing a public action continue,
	if (isset($ctrl->publicActions) && in_array($params['request']->action, $ctrl->publicActions))
	{
		return $ctrl;
	}

	//Save the location they are going to
	$value = array('controller' => $ctrl->request->controller, 'action' => $ctrl->request->action, 'args' => $ctrl->request->args);
	Session::write('url', $value);
	//Redirect them to the login page
	return function() use ($request)
	{
		return new Response(compact('request') + array('location' => '/login'));
	};


});

?>
