<?php
class Auth_Controller extends Base_Controller {
	public $restful = true;

	public function __construct() {
		$this->filter( 'before', 'guest' )->except( array( 'logout', 'validate' ) );

		// Note: We may not always require CSRF on login for system based logins so ignore it here.
		$this->filter( 'before', 'csrf' )->on( 'post' )->except( array( 'login' ) );
	}
	/**
	 * No direct access needed
	 *
	 * @return NULL
	 */
	public function get_index() {
		return Redirect::to( 'home' );
	}
	/**
	 * Verify login information and authenticate the client
	 *
	 * @param array
	 * @return Redirect
	 */
	public function post_login( $data = NULL ) {
		if( !empty( $data ) ) // Directly set the data so we can use it as normal
			Input::$input = $data;
		else // If this is a non-system call require CSRF
			$this->filter( 'before', 'csrf' );

		$rules = array(
			'email_address' => 'required|email',
			'password'		=> 'required|min:6',
		);
		// Validate all input
		$validator = Validator::make( Input::all(), $rules );

		// Send them back with errors
		if( ! $validator->valid() )
			return Redirect::to( 'home' )->with( 'errors', $validator->errors ); // Add errors to the view

		// Attempt to authenticate
		if( Auth::attempt( Input::get( 'email_address' ), Input::get( 'password' ) ) )
		{
			// Trigger log in event.
			Locker::trigger_event( 1, 'logged in', Auth::user()->id );

			// Send them to their locker
			return Redirect::to( 'locker' );
		}
		return Redirect::to( 'home' );
	}
	/**
	 * Handle logout requests by cleaning up the session
	 *
	 * @return Redirect
	 */
	public function get_logout() {
		// Trigger log out event
		Locker::trigger_event( 1, 'logged out', Auth::user()->id );

		// Destory the session
		Auth::logout();

		// Send them home
		return Redirect::to( 'home' );
	}
	/**
	 * Handle redirect from FB and save the users profile data.
	 *
	 * @return Redirect
	 */
	public function get_fb() {
		// Re-build object
		$facebook = new Facebook\SDK( array(
			'appId'  => Config::get( 'facebook.app_id' ),
			'secret' => Config::get( 'facebook.secret' ),
			'cookie' => true
		) );

		// Auth request params
		$params = array(
			'scope' => Config::get( 'facebook.scope' ),
			'redirect_uri' => Config::get( 'facebook.redirect_uri' ),
		);

		// Build the FB user
		$user = $facebook->getUser();
		if( $user ) {
			// Request FB profile data
			$fb_user = $facebook->api( '/me' );
		}

		// Something went wrong
		if( ! $fb_user )
			return Redirect::to( 'home' )->with( 'errors', 'Unable to connect with Facebook.' );

		// Restucture FB data to our own
		$lk_user['first_name'] = $fb_user['first_name'];
		$lk_user['last_name'] = $fb_user['last_name'];
		$lk_user['email_address'] = $fb_user['email'];
		$lk_user['nickname'] = $fb_user['username'];

		if( $fb_user['gender'] === 'male' )
			$lk_user['gender'] = 1;
		else
			$lk_user['gender'] = 0;

		// Reverse the encrypted password
		$lk_user['password'] = Crypter::decrypt( Session::get( 'password' ) );

		// This is for compatability with post_register() validation
		$lk_user['password_confirmation'] = $lk_user['password'];

		// Flag from_facebook
		$lk_user['from_facebook'];

		// Remove the session password
		Session::forget( 'password' );

		// Register the user, do not require email validation
		$this->post_register( $lk_user, false );

		return Redirect::to( 'home' );
	}
	/**
	 * Choose a password to use with FB profile data.
	 * POST will have the users password in it and redirect to FB for auth request.
	 *
	 * @return Redirect
	 */
	public function post_fb() {
		// Give a form to set a password
		$rules = array(
			'password' => 'required|confirmed|min:6',
		);
		// Validate all input
		$validator = Validator::make( Input::all(), $rules );

		// Send them back with errors
		if( ! $validator->valid() )
			return Redirect::to( 'home' )->with( 'errors', $validator->errors ); // Add errors to the view

		// Store the password temporary in our session, use some encryption in case non-SSL
		Session::put( 'password', Crypter::encrypt( Input::get( 'password' ) ) );

		// Re-build object
		$facebook = new Facebook\SDK( array(
			'appId'  => Config::get( 'facebook.app_id' ),
			'secret' => Config::get( 'facebook.secret' ),
			'cookie' => true
		) );

		// Auth request params
		$params = array(
			'scope' => Config::get( 'facebook.scope' ),
			'redirect_uri' => Config::get( 'facebook.redirect_uri' ),
		);
		return Redirect::to( $facebook->getLoginUrl( $params ) );
	}
	/**
	 * Validate registration data for our system
	 *
	 * @param array
	 * @param boolean
	 * @return Redirect with array
	 */
	public function post_register( $data = NULL, $email_confirm = true ) {
		if( !empty( $data ) )
			Input::$input = $data;

		$rules = array(
			'first_name'     => 'required|alpha|max:80',
			'last_name'      => 'required|alpha|max:120',
			'gender'         => 'required|in:0,1',
			'email_address'  => 'required|email|unique:users',
			'password'       => 'required|confirmed|min:6'
		);
		// Validate all input
		$validator = Validator::make( Input::all(), $rules );

		// Send them back with errors
		if( ! $validator->valid() )
			return Redirect::to( 'home' )
				->with( 'errors', $validator->errors )
				->with_input( 'except', array( 'password', 'password_confirm' ) ); // Add errors to the view

		// Create a new user
		$user = new User;

		// Fill in the details
		$user->fill( Input::all() );

		// Filter unused fields.
		unset( $user->password_confirmation );
		unset( $user->csrf_token );

		// Hash the password
		$user->password = Hash::make( $user->password );

		// Require e-mail confirmation
		if( ! $mail_confirm )
		{
			// Invalidate the account
			$user->validated = 0;

			// Save the user so we can grab their ID.
			$user->save();

			// Generate a validate key
			$user->validation_code = Str::random( array_get( $arguments, 0, 32 ) );

			$mailer = IoC::resolve( 'mailer' );

			$message = Swift_Message::newInstance( 'Welcome to Yoursite.com' )
				->setFrom( array( Config::get( 'email.from' ) => Config::get( 'email.name' ) ) )
				->setTo( array( $user->email_address => $user->first_name . ' ' . $user->last_name ) )
				->setBody(
					'<html>'.
					'<body>'.
					'<h2>Welcome to Yoursite.com</h2>'.
					'<p>You need to confirm your e-mail in order to participate.</p>'.
					'<p>Please <a href="http://www.yoursite.com/auth/validate/' .
					$user->id.
					'/'.
					htmlentities( $user->validation_code ) .
					'">click here</a>.</p>'.
					'</body>'.
					'</html>',
					'text/html' // Mark the content-type as HTML
					)
			;
			$result = $mailer->send($message);
		}
		else
			$user->validated = 1;

		// Send to the database
		$user->save();

		$_POST['csrf_token'] = Session::token();

		// Try to authenticate by passing the data to the login object.
		$this->post_login( Input::all() );
		
		return Redirect::to( 'home' );
	}
	/**
	 * Validate email_address
	 *
	 * @return redirect
	 */
	public function get_validate( $id, $code ) {

		$key = html_entity_decode( $code );
		$validation_code = DB::table( 'users' )->where( 'id', '=', $id )->only( 'validation_code' );

		if( $validation_code === $key )
		{
			$affected = DB::table( 'users' )
				->where( 'id', '=', $id )
				->update( array(
					'validated' => 1,
					'validation_code' => NULL, // Clear the validation code so we do waste space
				) );
		}
		else
			return Redirect::to( 'home' )->with( 'errors', 'Invalid validation code.' );

		// Notify the user it worked
		Session::flash( 'notice', 'You have confirmed your e-mail.' );
		return Redirect::to( 'home' );
	}
}