<?php

namespace Engine\Logger;

/**
 * Class for logging errors
 */
class DirectPrintf extends GeneralAbstract
{
	/**
	 * Output handle
	 */
	protected $handler;

	protected $loggedErrorTypes = [];

	/**
	 * Constructor
	 */
	public function __construct()
	{
		parent::__construct();
		$this->handler = fopen('php://output', 'w');
	}

	/**
	 * Check if an error level was issue
	 * @param string $level
	 * @return boolean
	 */
	public function has($level)
	{
		return (bool)$this->loggedErrorTypes[$level];
	}

	/**
	 * Write the message to stdout
	 *
	 * (non-PHPdoc)
	 * @see \Engine\Logger\GeneralAbstract::writeRawMessage()
	 */
	public function writeRawMessage($fields)
	{
		$this->loggedErrorTypes[$fields['level']]++;

		$t = $fields['addTime'];
		$micro = sprintf("%06d",($t - floor($t)) * 1000000);
		$d = new \DateTime( date('Y-m-d H:i:s.'.$micro, (int)$t) );

		// print the message
		fwrite($this->handler, sprintf("\n<div class='type-%s' data-microtime='%s' data-memory='%s'><span class='time'>%s</span><span class='memory'>%.1fMb</span><span class='type'>%s</span><span class='msg'>%s</span></div>",
			$fields['level'],
			// data* fields
			$fields['addTime'],
			$fields['memory'],

			// formatted fields
			$d->format("Y-m-d H:i:s.u"),
			$fields['memory']/(1024*1024),
			$fields['level'],
			$fields['message']));
		return true;
	}

	/**
	 * The 'idle' log level(that is supposed to be used only when the cronjob didn't actualy do anything)
	 * @param array $context
	 */
	public function idle($message, array $context = [])
	{
		return $this->log('idle', $message, $context);
	}

	/**
	 * The 'success' log level
	 * @param array $context
	 */
	public function success($message, array $context = [])
	{
		return $this->log('success', $message, $context);
	}

	/**
	 * The 'wait' log level(that is supposed to be used only when the cronjob is waything for a resource)
	 * @param array $context
	 */
	public function waiting($message, array $context = [])
	{
		return $this->log('waiting', $message, $context);
	}

	/**
	 * Override the parent, and skip injecting context & stacktrace data
	 * {@inheritDoc}
	 * @see \Engine\Logger\GeneralAbstract::log()
	 */
	public function log($level, $message, array $context = [])
	{
		// check that the error level is valid
		if (!in_array($level, ['critical', 'error', 'warning', 'info', 'idle', 'waiting', 'success'])) {
			throw new \Exception("Invalid error level: {$level}");
		}

		// context is not supported
		if ($context) {
			throw  new \Exception("Context is not supported by this logging class");
		}

		return $this->writeRawMessage([
			'level' => 		$level,
			'message' => 	$message,
			'addTime' => 	microtime(true),
			'memory' => 	memory_get_usage(true),
			'logSession' => $this->getLogSession(true),
		]);
	}
}
