<?php

/**
 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @package fusionLib
 * @copyright Copyright (c) 2012 - 2016 fusionLib. All rights reserved.
 * @link http://fusionlib.com
 */

/**
 * flBufferCode Class
 *
 * Buffers JavaScript and CSS for output in the applications view.
 * Inline code is grouped if possible.
 *
 * @package fusionLib
 */
class flBufferCode {

	/**
	 * Flags if core library required.
	 *
	 * @var bool
	 */
	private $requireCore;

	/**
	 * Flags if validator library required.
	 *
	 * @var bool
	 */
	private $requireValidator;

	/**
	 * Flags if to use jQuery.
	 *
	 * @var bool
	 */
	private $useJQuery = false;

	/**
	 * Flags if to include jQuery as well as fusionLib
	 *
	 * @var bool
	 */
	private $includeJQuery = false;

	/**
	 * The head JS.
	 *
	 * @var flBufferJs
	 */
	private $headJS;

	/**
	 * The body JS.
	 *
	 * @var flBufferJs
	 */
	private $bodyJS;

	/**
	 * Body JS inside $fl(document).ready
	 * @var flBufferJS
	 */
	private $readyJS;

	/**
	 * The CSS.
	 *
	 * @var flBufferCss
	 */
	private $css;

	/**
	 * Flags if to output development JavaScript
	 * @var bool
	 */
	static private $useDevJS = false;

	/**
	 * Flag if to use development JavaScript for output or production.
	 *
	 * @param bool $useDevJS true to enable development JS output or false for production.
	 */
	static function useDevJS($useDevJS = true) {
		self::$useDevJS = $useDevJS;
	}

	/**
	 * Construct the object.
	 */
	function __construct() {
		$this->clear();
	}

	/**
	 * Flags to use jQuery rather than fusionLibs own JavaScript libraries.
	 *
	 * @param bool $use true to use jQuery or false for fusionLib.
	 * @return flBufferCode This object.
	 */
	function useJQuery($use = true) {
		$this->useJQuery = $use;
		return $this;
	}

	/**
	 * Clear the internal buffers.
	 *
	 * @return flBufferCode This object.
	 */
	function clear() {
		$this->headJS = new flBufferJs();
		$this->bodyJS = new flBufferJs();
		$this->readyJS = new flBufferJs();
		$this->readyJS->setWrap("<script type=\"text/javascript\">\n//<![CDATA[\n\$fl(document).ready(function() {\n", "});\n//]]>\n</script>");
		$this->css = new flBufferCss();
		$this->requireValidator = $this->requireCore = false;
		return $this;
	}

	/**
	 * Flags to use the core JavaScript library.
	 *
	 * @return flBufferCode This object.
	 */
	function requireCore() {
		$this->requireCore = true;
		return $this;
	}

	/**
	 * Flags to use validation library.
	 *
	 * @return flBufferCode This object.
	 */
	function requireValidator() {
		$this->requireValidator = $this->requireCore = true;
		return $this;
	}

	/**
	 * Buffer the CSS.
	 *
	 * @param string $css A CSS file or inline CSS.
	 * @param string $media Optional media type.
	 * @return flBufferCode This object.
	 */
	function bufferCSS($css, $media = 'all') {
		$this->css->buffer($css, $media);
		return $this;
	}

	/**
	 * Buffer JavaScript for the head section.
	 *
	 * @param string $js A JavaScript file or inline JavaScript.
	 * @return flBufferCode This object.
	 */
	function bufferHeadJS($js) {
		$this->headJS->buffer($js);
		return $this;
	}

	/**
	 * Buffer JavaScript for the body.
	 *
	 * @param string $js A JavaScript file or inline JavaScript.
	 * @return flBufferCode This object.
	 */
	function bufferBodyJS($js) {
		$this->bodyJS->buffer($js);
		return $this;
	}

	/**
	 * Buffer JavaScript for the body ready event.
	 *
	 * @param string $js Inline JavaScript.
	 * @return flBufferCode This object.
	 */
	function bufferReadyJS($js) {
		$this->readyJS->buffer($js);
		return $this;
	}

	/**
	 * Set the list of JavaScript files to ignore.
	 *
	 * @param array $ignore List of JS files to ignore.
	 * @return flBufferCode This object.
	 */
	function setJSIgnoreList($ignore) {
		$this->headJS->setIgnoreList($ignore);
		$this->bodyJS->setIgnoreList($ignore);
		return $this;
	}

	/**
	 * Set the list of CSS files to ignore.
	 *
	 * @param array $ignore List of CSS files to ignore.
	 * @return flBufferCode This object.
	 */
	function setCSSIgnoreList($ignore) {
		$this->css->setIgnoreList($ignore);
		return $this;
	}

	/**
	 * Get the list of JavaScript files loaded.
	 *
	 * @return array List of files.
	 */
	function getJSFileList() {
		return array_merge($this->headJS->getFileList(), $this->bodyJS->getFileList());
	}

	/**
	 * Get the list of CSS files loaded.
	 *
	 * @return array List of files.
	 */
	function getCSSFileList() {
		return $this->css->getFileList();
	}

	/**
	 * Get the head CSS and JavaScript if any.
	 *
	 * @return string The CSS and JS to place in the head.
	 */
	function getHeadBuffer() {

		// If running with debug
		if(self::$useDevJS) {
			require FLLIBPATH . 'Buffer/outputDevJS.php';
		}
		else {
			// Validation
			if($this->requireValidator)
				$this->bodyJS->prepend('system/libs/js/fusionLib.validation.js');

			// Core
			if($this->requireCore) {
				if($this->useJQuery) {
					$this->headJS->prepend('system/libs/js/fusionLib.jQuery.js');
					$this->includeJQuery = true;
				}
				else
					$this->headJS->prepend('system/libs/js/fusionLib.js');
			}

			if($this->includeJQuery)
				$this->headJS->prepend('system/app/js/jquery.min.js');
		}

		return $this->css->getBuffer() . $this->headJS->getBuffer();
	}

	/**
	 * Get the body JavaScript if any.
	 *
	 * @return string The JS for the body.
	 */
	function getBodyBuffer() {
		return $this->bodyJS->getBuffer() . $this->readyJS->getBuffer();
	}

	/**
	 * Get the URI of the system JavaScript folder.
	 *
	 * @return string The system JS URI.
	 */
	function getSysJSURI() {
		return self::$useDevJS ? 'system/libs/js/src/' : 'system/libs/js/';
	}

	/**
	 * Include jQuery in the output.
	 *
	 * @return flBufferCode This object.
	 */
	function includeJQuery() {
		$this->includeJQuery = true;
		return $this;
	}

}
