<?php defined('SYSPATH') or die('No direct access allowed.');

/**
 * This class extends Auth_ORM to enable external authentication
 *
 * @package    OAuth
 * @category   Classes
 * @author     Deon George
 * @copyright  (c) 2009-2013 Deon George
 * @license    http://dev.leenooks.net/license.html
 */
abstract class Auth_ORM_External_OAuth2 extends Auth_ORM_External {
	// OAuth Objects
	protected $client;
	protected $provider;
	protected $token;

	public function __construct(Model_Oauth $oo) {
		// If our user refused, then no point continuing
		if ($problem = Arr::get($_REQUEST,'error'))
			switch ($problem) {
				case 'access_denied':
					HTTP::redirect('login');

				default:
					throw HTTP_Exception::factory(501,'Unknown OAuth Problem :problem',array(':problem'=>$problem));
			}

		parent::__construct($oo);

		// Load the provider
		$this->provider = OAuth2_Provider::factory($this->oo->name);

		// Load the client for this provider
		$this->client = OAuth2_Client::factory(array(
			'id'=>$this->oo->app_id,
			'secret'=>$this->oo->secret,
		));
	}

	/**
	 * Is user currently log in??
	 * If we have a valid token, then we are.
	 */
	public function logged_in($role=NULL,$debug=NULL) {
		// Attempt to complete signin
		if ($code = Arr::get($_REQUEST,'code')) {
			$state = Arr::get($_REQUEST,'state');
			if (! $state OR $state != Session::instance()->get_once('oauth.state'))
				return FALSE;

			// Add the callback URL to the consumer
			$this->client->callback(URL::site('oauth/login/'.$this->oo->name,TRUE));

			// Exchange the authorization code for an access token
			$this->token = $this->provider->access_token($this->client,$code);
			Session::instance()->set('oauth.token',$this->token);

		// Otherwise try and get our token from our session.
		} else {
			$this->token = Session::instance()->get_once('oauth.token');
		}

		// @todo We need to check that the token is still valid.
		return $this->token ? TRUE : FALSE;
	}

	/**
	 * Our URL that starts the login process
	 */
	public function login_url() {
		$state = sha1($this->oo->name.time());
		Session::instance()->set('oauth.state',$state);

		// Add the callback URL to the consumer
		$this->client->callback(URL::site('oauth/login/'.$this->oo->name,TRUE));

		// Get the login URL from the provider
		return $this->provider->authorize_url($this->client,array('state'=>$state));
	}

	public function user_id() {
		return $this->provider->user_details($this->client,array('access_token'=>$this->token))->id();
	}
}
?>
