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

/**
 * flLogHandler Interface
 *
 * Log handlers interface.
 *
 * @package fusionLib
 */
interface flLogHandler {

	/**
	 * @param array $record The record to log.
	 */
	public function write($record);
}

/**
 * flLog Class
 *
 * Static class to provide logging functionality.
 *
 * @package fusionLib
 */
abstract class flLog {
	/**#@+
	 * Logging levels.
	 */
	const DEBUG = 100;
	const INFO = 200;
	const NOTICE = 300;
	const WARNING = 400;
	const ERROR = 500;
	const CRITICAL = 600;
	const ALERT = 700;
	const EMERGENCY = 800;
	/**#@-*/

	/**
	 * Map of levels to level names.
	 *
	 * @var array
	 */
	static protected $levels = array(
		self::DEBUG => 'DEBUG',
		self::INFO => 'INFO',
		self::NOTICE => 'NOTICE',
		self::WARNING => 'WARNING',
		self::ERROR => 'ERROR',
		self::CRITICAL => 'CRITICAL',
		self::ALERT => 'ALERT',
		self::EMERGENCY => 'EMERGENCY'
	);

	/**
	 * Array of log handlers.
	 *
	 * @var array
	 */
	static protected $handlers = array();

	/**
	 * The name of the channel.
	 * @var string
	 */
	static protected $name = '';

	/**
	 * Add a log handler to the system.
	 *
	 * @param flLogHandler $hander The log handler to add to the system.
	 * @param int $level The level at which messages will be sent to the handler.
	 */
	static public function pushHandler($hander, $level = self::DEBUG) {
		self::$handlers[] = array(
			'level' => $level,
			'handler' => $hander
		);
	}

	/**
	 * Set the channel name.
	 *
	 * @param string $name The channel name.
	 */
	static public function setName($name) {
		self::$name = $name;
	}

	/**
	 * Write a log entry.
	 *
	 * @param mixed $object The object to log.
	 * @param int $level The log level.
	 */
	static public function write($object, $level = self::WARNING) {

		// Build the record to log
		$record = array(
			'message' => $object,
			'level' => $level,
			'level_name' => self::$levels[$level],
			'channel' => self::$name
		);

		// Send to handlers
		foreach(self::$handlers as $h) {
			if($level >= $h['level'])
				$h['handler']->write($record);
		}
	}

	/**
	 * Write a debug message to the log.
	 *
	 * @param mixed $object The object to log.
	 */
	static public function debug($object) {
		self::write($object, self::DEBUG);
	}

	/**
	 * Write a info message to the log.
	 *
	 * @param mixed $object The object to log.
	 */
	static public function info($object) {
		self::write($object, self::INFO);
	}

	/**
	 * Write a notice message to the log.
	 *
	 * @param mixed $object The object to log.
	 */
	static public function notice($object) {
		self::write($object, self::NOTICE);
	}

	/**
	 * Write a warning message to the log.
	 *
	 * @param mixed $object The object to log.
	 */
	static public function warning($object) {
		self::write($object, self::WARNING);
	}

	/**
	 * Write a error message to the log.
	 *
	 * @param mixed $object The object to log.
	 */
	static public function error($object) {
		self::write($object, self::ERROR);
	}

	/**
	 * Write a critical message to the log.
	 *
	 * @param mixed $object The object to log.
	 */
	static public function critical($object) {
		self::write($object, self::CRITICAL);
	}

	/**
	 * Write a alert message to the log.
	 *
	 * @param mixed $object The object to log.
	 */
	static public function alert($object) {
		self::write($object, self::ALERT);
	}

	/**
	 * Write a emergency message to the log.
	 *
	 * @param mixed $object The object to log.
	 */
	static public function emergency($object) {
		self::write($object, self::EMERGENCY);
	}
}
