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

/**
 * This class provides the default template controller for rendering pages.
 *
 * @package    lnApp
 * @subpackage Page/Template
 * @category   Controllers
 * @author     Deon George
 * @copyright  (c) 2010 Deon George
 * @license    http://dev.leenooks.net/license.html
 */
abstract class Controller_lnApp_TemplateDefault extends Controller_Template {
	/**
	 * @var string page template
	 */
	public $template = 'lnapp/default';
	/**
	 * @var object meta object information as per [meta]
	 */
	protected $meta;
	/**
	 * Controls access to this controller.
	 * Can be set to a string or an array, for example 'login' or array('login', 'admin')
	 * Note that in second(array) example, user must have both 'login' AND 'admin' roles set in database
	 *
	 * @var boolean is authenticate required with this controller
	 */
	protected $auth_required = FALSE;
	/**
	 * If redirecting to a login page, which page to redirect to
	 */
	protected $noauth_redirect = 'login';
	/**
	 * Controls access for separate actions, eg:
	 * 'adminpanel' => 'admin' will only allow users with the role admin to access action_adminpanel
	 * 'moderatorpanel' => array('login', 'moderator') will only allow users with the roles login and moderator to access action_moderatorpanel
	 *
	 * @var array actions that require a valid user
	 */
	protected $secure_actions = array(
		'menu' => FALSE,
	);

	/**
	 * Check and see if this controller needs authentication
	 *
	 * if $this->auth_required is TRUE, then the user must be logged in only.
	 * if $this->auth_required is FALSE, AND $this->secure_actions has an array of
	 * methods set to TRUE, then the user must be logged in AND a member of the
	 * role.
	 *
	 * @return boolean
	 */
	protected function _auth_required() {
		// If our global configurable is disabled, then continue
		if (! Kohana::Config('config.method_security'))
			return FALSE;

		return (($this->auth_required !== FALSE && Auth::instance()->logged_in(NULL,get_class($this).'|'.__METHOD__) === FALSE) ||
			(is_array($this->secure_actions) && array_key_exists($this->request->action(),$this->secure_actions) &&
			Auth::instance()->logged_in($this->secure_actions[$this->request->action()],get_class($this).'|'.__METHOD__) === FALSE));
	}

	/**
	 * Loads the template [View] object.
	 *
	 * Page information is provided by [meta].
	 * @uses meta
	 */
	public function before() {
		// Do not template media files
		if ($this->request->action() === 'media') {
			$this->auto_render = FALSE;
			return;
		}

		parent::before();

		// Check user auth and role
		if ($this->_auth_required()) {
			if (Kohana::$is_cli)
				throw new Kohana_Exception('Cant run :method, authentication not possible',array(':method'=>$this->request->action()));

			// If auth is required and the user is logged in, then they dont have access.
			// (We have already checked authorisation.)
			if (Auth::instance()->logged_in(NULL,get_class($this).'|'.__METHOD__)) {
				if (Config::sitemode() == Kohana::DEVELOPMENT)
					SystemMessage::add(array(
						'title'=>_('Insufficient Access'),
						'type'=>'debug',
						'body'=>Debug::vars(array('required'=>$this->auth_required,'action'=>$this->request->action(),'user'=>Auth::instance()->get_user()->username)),
					));

				// @todo Login No Access redirects are not handled in JS?
				if ($this->request->is_ajax()) {
					echo _('You dont have enough permissions.');
					die();
				} else
					Request::current()->redirect('login/noaccess');

			} else {
				Session::instance()->set('afterlogin',Request::detect_uri());
				Request::current()->redirect($this->noauth_redirect);
			}
		}

		// For AJAX calls, we dont need to render the complete page.
		if ($this->request->is_ajax()) {
			$this->auto_render = FALSE;
			return;
		}

		// Bind our template meta variable
		$this->meta = new meta;
		View::bind_global('meta',$this->meta);

		// Our default style sheet
		Style::add(array(
			'type'=>'file',
			'data'=>'css/default.css',
		));

		// Our default scripts
		// This is in a reverse list, since we push them to the beginging of the scripts to render.
		foreach (array('file'=>array(
			'js/jquery.cookie.js',
			'js/jquery.jstree-1.0rc3.js',
			'js/jquery-1.4.2.js',
			)) as $type => $datas) {

			foreach ($datas as $data) {
				Script::add(array(
					'type'=>$type,
					'data'=>$data,
				),TRUE);
			}
		}

		// Initialise our content
		$this->template->left = '';
		$this->template->content = '';
		$this->template->right = '';
	}

	public function after() {
		if (! is_string($this->template) AND empty($this->template->content))
			$this->template->content = Block::factory();

		if ($this->auto_render) {
			// Application Title
			$this->meta->title = Kohana::Config('config.appname');
			$this->template->title = '';

			// Language
			$this->meta->language = Config::instance()->so->language_id;

			// Copyright
			$this->meta->copywrite = Config::instance()->so->site_name;

			// Copyright
			$this->meta->description = sprintf('%s::%s',$this->request->controller(),$this->request->action());

			// Style Sheets Properties
			$this->meta->styles = Style::factory();

			// Script Properties
			$this->meta->scripts = Script::factory();

			// Application logo
			$this->template->logo = Config::logo();

			// Link images on the header line
			$this->template->headimages = $this->_headimages();

			// Control Line
			$this->template->control = $this->_control();

			// System Messages line
			$this->template->sysmsg = $this->_sysmsg();

			// Left Item
			$this->template->left = $this->_left();

			// Right Item
			$this->template->right = $this->_right();

			// Footer
			$this->template->footer = $this->_footer();

		// For any ajax rendered actions, we'll need to capture the content and put it in the response
		} elseif ($this->request->is_ajax() && isset($this->template->content) && ! $this->response->body()) {
			// @todo move this formatting to a view?
			if ($s = $this->_sysmsg() AND (string)$s)
				$this->response->body(sprintf('<table class="sysmsg"><tr><td>%s</td></tr></table>',$s));

			// In case there any style sheets for this render.
			$this->response->bodyadd(Style::factory());

			// In case there any javascript for this render.
			$this->response->bodyadd(Script::factory());

			// Get the response body
			$this->response->bodyadd(sprintf('<table class="content"><tr><td>%s</td></tr></table>',$this->template->content));
		}

		parent::after();

		// Generate and check the ETag for this file
		if (Kohana::$environment === Kohana::PRODUCTION)
			$this->response->check_cache(NULL,$this->request);
	}

	/**
	 * Default Method to call from the tree menu
	 */
	public function action_menu() {
		$this->template->content = _('Please choose from the menu on the left - you may need to expand the items by pressing on the plus.');
	}

	protected function _headimages() {
		HeadImages::add(array(
			'url'=>'http://dev.leenooks.net',
			'img'=>'img/forum-big.png',
			'attrs'=>array('onclick'=>"target='_blank';",'title'=>'Link')
		));

		return HeadImages::factory();
	}

	/**
	 * Render our control menu bar
	 */
	protected function _control() {
		return Breadcrumb::factory();
	}

	protected function _sysmsg() {
		return SystemMessage::factory();
	}

	protected function _left() {
		return empty($this->template->left) ? Controller_Tree::js() : $this->template->left;
	}

	protected function _right() {
		return empty($this->template->right) ? '' : $this->template->right;
	}

	public function _footer() {
		return sprintf('&copy; %s',Config::SiteName());
	}

	/**
	 * This action will render all the media related files for a page
	 * @return void
	 */
	final public function action_media() {
		// Get the file path from the request
		$file = $this->request->param('file');

		// Find the file extension
		$ext = pathinfo($file, PATHINFO_EXTENSION);

		// Remove the extension from the filename
		$file = substr($file, 0, -(strlen($ext) + 1));
		$f = '';

		// If our file is pathed with session, our file is in our session.
		if ($fd = Session::instance()->get_once($this->request->param('file'))) {
			$this->response->body($fd);

		// First try and find media files for the site_id
		} elseif ($f = Kohana::find_file(sprintf('media/%s',Config::siteid()), $file, $ext)) {
			// Send the file content as the response
			$this->response->body(file_get_contents($f));

		// If not found try a default media file
		} elseif ($f = Kohana::find_file('media', $file, $ext)) {
			// Send the file content as the response
			$this->response->body(file_get_contents($f));

		} else {
			// Return a 404 status
			$this->response->status(404);
		}

		// Generate and check the ETag for this file
		$this->response->check_cache(NULL,$this->request);

		// Set the proper headers to allow caching
		$this->response->headers('Content-Type',File::mime_by_ext($ext));
		$this->response->headers('Content-Length',(string)$this->response->content_length());
		$this->response->headers('Last-Modified',date('r', $f ? filemtime($f) : time()));
	}
}
?>