<?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) 2007 - 2013 fusionLib. All rights reserved.
 * @link http://fusionlib.com
 */

/**
 * flConfig Class
 *
 * Class to provide access to configuration data held in arrays.
 *
 * @package fusionLib
 */
class flConfig implements Iterator, Countable {

	/**
	 * The configuration data.
	 *
	 * @var array
	 */
	protected $data = array();

	/**
	 * The configs namespace.
	 *
	 * @var string
	 */
	protected $namespace = null;

	/**
	 * Construct a new configuration object.
	 *
	 * @param string $namespace The namespace/filename for the configuration data.
	 * @param array $data The optional array of data, if given the config is not loaded from the file.
	 */
	function __construct($namespace, $data = null) {
		$this->namespace = $namespace;
		$this->data = $data;
	}

	/**
	 * Return the namespace for the config data.
	 *
	 * @return string The namespace.
	 */
	function getNamespace() {
		return $this->namespace;
	}

	/**
	 * Set a configuration item.
	 *
	 * Configurations are read only therefore this throws an exception.
	 *
	 * @param string $key The name of the configuration item to set.
	 * @param mixed $value The value to set for the item.
	 * @throws flConfigException
	 */
	function __set($key, $value) {
		throw new flConfigException("Attempt made to write configuration item '$key' in config '$this->namespace'.");
	}

	/**
	 * Unset a configuration item.
	 *
	 * Configurations are read only therefore this throws an exception.
	 *
	 * @param string $key The name of the configuration item to unset.
	 * @throws flConfigException
	 */
	function __unset($key) {
		throw new flConfigException("Attempt made to delete configuration item '$key' in config '$this->namespace'.");
	}

	/**
	 * Get the configuration item.
	 *
	 * If the items is not present then the default value is returned.
	 *
	 * @param string $key The name of the item to get.
	 * @param mixed $default The default value to use if the item is not present.
	 * @return mixed The value assigned to the key or the default value.
	 */
	function get($key, $default = null) {
		return isset($this->data[$key]) ? $this->data[$key] : $default;
	}

	/**
	 * Read a configuration value.
	 *
	 * If the value is not present then an error is reported and the function never returns.
	 *
	 * @param string $key The name of the configuration item to get.
	 * @return mixed The value assigned to the item.
	 * @throws flConfigException
	 */
	function __get($key) {
		if(!isset($this->data[$key]))
			throw new flConfigException("Unknown configuration entry '$key' in config '$this->namespace'.");
		return $this->data[$key];
	}

	/**
	 * Test if a configuration key is set.
	 *
	 * @param string $name The name of the configuration key to test for.
	 * @return bool True if the key is present; else false.
	 */
	function __isset($name) {
		return isset($this->data[$name]);
	}

	/**
	 * The number of config items.
	 *
	 * @return int Number of items.
	 */
	function count() {
		return count($this->data);
	}

	/**
	 * Get the next item.
	 *
	 * @return mixed|void The item.
	 */
	function next() {
		return next($this->data);
	}

	/**
	 * Move to the first item.
	 *
	 * @return mixed|void The item.
	 */
	function rewind() {
		return reset($this->data);
	}

	/**
	 * Get the key.
	 *
	 * @return mixed The key.
	 */
	function key() {
		return key($this->data);
	}

	/**
	 * Get the current item.
	 *
	 * @return mixed The item.
	 */
	function current() {
		return current($this->data);
	}

	/**
	 * Test if the position in the array is valid.
	 *
	 * @return bool true if valid; else false.
	 */
	function valid() {
		return current($this->data) !== false;
	}
}
