<?php

namespace Planaday\Utility\Debug\Log;

class LogScriptBuilder {
	/**
	 * @param Logger $logger
	 * @param string[] $allowedTypes
	 * @param bool $includeData
	 * @param string $version
	 *
	 * @return string
	 */
	public function getScript(Logger $logger, array $allowedTypes = ['all'], bool $includeData = true, string $version = ''): string {
		$logs = $this->filterLogs($logger, $allowedTypes, $includeData);

		$rawLogs = [];

		foreach ($logs as $log) {
			$rawLogs[] = [
				'type' => $log->getType(),
				'class' => $log->getClass(),
				'message' => $log->getMessage(),
				'relativeTime' => $log->getRelativeTime(),
				'time' => $log->getTime(),
				'data' => $log->getData(),
				'scopeId' => $log->getScopeId()
			];
		}

		foreach ($rawLogs as &$log) {
			if (json_encode($log['data']) === false) {
				if (isset($log['data']['trace'])) {
					unset($log['data']['trace']);
					continue;
				}

				if (json_encode($log['data']) === false)
					unset($log['data']);
			}
		}

		$jsonString = json_encode($rawLogs);
		if ($jsonString === false) {
			return "<script> console.log('Logs of planaday not available due to inability to convert logs to json, sorry.') </script>";
		}

		return '<script>' . file_get_contents(__DIR__ . '/LogScripts.js') . " \n" .
		       "const planadayLog = new PlanadayLogger( $jsonString, '$version' ) </script> " .
		       "<script> console.log('Logs of planaday available at planadayLog, for info type planadayLog.help') </script>";
	}

	/**
	 * @param Logger $logger
	 * @param string[] $allowedTypes
	 * @param bool $includeData
	 *
	 * @return LogEntry[]
	 */
	private function filterLogs(Logger $logger, array $allowedTypes = ['all'], bool $includeData = true): array{
		$logs = $logger->getLogs();

		usort($logs, function(LogEntry $a, LogEntry $b) {
			return $a->getRawTime() <=> $b->getRawTime();
		});

		if (isset($logs[0])) $earliestTime = $logs[0]->getRawTime();

		$allowDebug = in_array('debug', $allowedTypes) || in_array('all' , $allowedTypes);

		foreach ($logs as $key => $log) {
			if ( in_array($log->getType() , $allowedTypes) || in_array('all' , $allowedTypes)) {
				if (!$includeData || !($allowDebug || $log->getType() === 'warning' || $log->getType() === 'error')) {
					$log->clearData();
				}

				$log->setRelativeTime($log->getRawTime() - ($earliestTime ?? 0));
			} else {
				unset($logs[$key]);
			}
		}

		return $logs;
	}
}