<?php
/**
 *
 * @copyright Copyright (c) Miroslav Marek <mirek.marek@web-jet.cz>
 * @license http://www.php-jet.net/license/license.txt
 * @author Miroslav Marek <mirek.marek@web-jet.cz>
 */

use Jet\Debug_Profiler_Run;
use Jet\Debug_Profiler_Run_Block;
use Jet\Debug_Profiler_Run_SQLQueryData;


/**
 * @var Debug_Profiler_Run $run
 */

$blocks = $run->getBlocks();

$renderer = new class($run) {
	
	/**
	 * @var Debug_Profiler_Run_Block[]
	 */
	public array $slowest_block = [];
	/**
	 * @var Debug_Profiler_Run_Block[]
	 */
	public array $hungriest_block = [];
	
	public ?Debug_Profiler_Run_SQLQueryData $slowest_sql_query = null;
	public int $number_of_queries = 0;
	public float $queries_duration = 0.0;
	
	
	public function __construct( Debug_Profiler_Run $run )
	{
		$this->slowest_block = [];
		foreach($run->getBlocks() as $block) {
			$level = $block->getLevel();
			
			if(
				!isset($this->slowest_block[$level]) ||
				$block->getDuration()> $this->slowest_block[$level]->getDuration()
			) {
				$this->slowest_block[$level] = $block;
			}
			
			if(
				!isset($this->hungriest_block[$level]) ||
				$block->getMemoryUsageDiff()> $this->hungriest_block[$level]->getMemoryUsageDiff()
			) {
				$this->hungriest_block[$level] = $block;
			}
			
		}
		
		foreach( $run->getSqlQueries() as $query ) {
			if( $this->slowest_sql_query===null ) {
				$this->slowest_sql_query = $query;
				continue;
			}
			
			if( $query->getDuration() > $this->slowest_sql_query->getDuration() ) {
				$this->slowest_sql_query = $query;
			}
		}


		$this->number_of_queries = 0;
		$this->queries_duration = 0.0;
		
		foreach ($run->getSqlQueries() as $q) {
			$this->number_of_queries++;
			$this->queries_duration += $q->getDuration();
		}
	}
	
	public function blockDuration( Debug_Profiler_Run_Block $block ) : string
	{
		$level = $block->getLevel();
		
		if(
			!$block->getIsRoot() &&
			$this->slowest_block[$level]->getId()==$block->getId()
		) {
			return '<span class="warning">'.$this->formatDuration( $block->getDuration() ).'</span>';
			
		} else {
			return $this->formatDuration( $block->getDuration() );
		}
	}
	
	public function getMemoryUsageDiff( Debug_Profiler_Run_Block $block ) : string
	{
		$level = $block->getLevel();
		
		if(
			!$block->getIsRoot() &&
			$this->slowest_block[$level]->getId()==$block->getId()
		) {
			return '<span class="warning">'.$this->formatBytes( $block->getMemoryUsageDiff() ).'</span>';
			
		} else {
			return $this->formatBytes( $block->getMemoryUsageDiff() );
		}
		
	}
	
	public function SQLQueryDuration( Debug_Profiler_Run_SQLQueryData $q ) : string
	{
		if($q->getDuration()>=$this->slowest_sql_query->getDuration()*0.8):
			return '<span class="warning">'.$this->formatDuration($q->getDuration()).'</span>';
		else:
			return $this->formatDuration($q->getDuration());
		endif;
	}
	
	protected function formatBytes(int $b) : string
	{
		return round(($b / 1024), 3) . '&nbsp;KiB';
	}
	
	public function formatDuration(float $duration) : string
	{
		$duration = round($duration * 1000, 3);
		
		return $duration . '&nbsp;ms';
	}
	
	public function formatQuery(string $query, array $query_data = []) : string
	{
		
		if (!$query_data) {
			return $query;
		}
		
		
		$replacements = [];
		
		foreach ($query_data as $key => $value) {
			
			if ($value === null) {
				$value = 'NULL';
			} else {
				if (is_bool($value)) {
					$value = $value ? 1 : 0;
				} else {
					if( !(is_int($value) || is_float($value)) ) {
						$value = "'".addslashes((string)$value)."'";
					}
				}
			}
			
			$replacements[':' . $key] = $value;
		}
		
		krsort($replacements, SORT_STRING);
		
		return str_replace(
			array_keys($replacements),
			array_values($replacements),
			$query
		);
		
	}
	
	public function showRunBlockTree( Debug_Profiler_Run_Block $block ) : void
	{
		require __DIR__.'/result/run-block/tree-item.phtml';
	}
	
	public function showRunBlock( Debug_Profiler_Run_Block $block ) : void
	{
		require __DIR__.'/result/run-block/item.phtml';
	}
	
};

?>
<html>
<head>

</head>
<body>

	<?php require 'result/css.phtml'; ?>
	<?php require 'result/js.phtml'; ?>

	<div class="header">
		<div class="header-logo"><img src="https://php-jet.net/images/logo-st.svg"></div>
		<div class="header-title">Profiler result</div>
	</div>
	
	<div class="basic-info">
		<div class="basic-info-table">
			<div>Run id:</div>
			<div><?= $run->getId(); ?></div>
	
			<div>Request URL:</div>
			<div><?= $run->getRequestURL(); ?></div>
	
			<div>Date and time:</div>
			<div><?= $run->getDateAndTime(); ?></div>
		</div>
		
		<div>
			<?php if ($run->getXHPData()): ?>
				<a href="?JPR=<?= $run->getId(); ?>&callgraph" target="_blank" class="xhprof-link">&#x1f441; XHProf Call Graph</a>
			<?php else: ?>
				<strong class="xhprof-na">XHProf data not available</strong>
			<?php endif; ?>
		</div>
	</div>

	<div id="nav-tabs">
		<button id="run-blocks-tab" type="button" class="nav-tab nav-tab-selected" onclick="ProfilerResult.selectTab('run-blocks')">Run blocks</button>
		<button id="sql-queries-tab" type="button" class="nav-tab" onclick="ProfilerResult.selectTab('sql-queries')">SQL queries (<?=count( $run->getSqlQueries() )?>)</button>
	</div>

	<div id="nab-tabs-content">
		<div id="run-blocks-content" class="nab-tab-content nab-tab-content-selected">
			<div class="run-blocks">
				<div class="run-blocks-tree" id="run-blocks-tree">
					<?php $renderer->showRunBlockTree($blocks[0]); ?>
				</div>
				<div class="run-blocks-details" id="run-blocks-details">
					<?php foreach($run->getBlocks() as $block):
						$renderer->showRunBlock( $block );
					endforeach; ?>
				</div>
			</div>
		</div>

		<div id="sql-queries-content" class="nab-tab-content">
			<div class="sql-queries-summary">
				<div>Number of executed SQL queries:</div>
				<div><?=$renderer->number_of_queries?></div>
				<div>Duration of executed SQL queries:</div>
				<div><?= $renderer->formatDuration($renderer->queries_duration); ?></div>
			</div>
			
			
			<div>
				
				<?php foreach ($run->getSqlQueries() as $i=>$q):?>
					<div class="sql-queries-item">
						<div class="sql-queries-item-query"><?= $renderer->formatQuery($q->getQuery(), $q->getQueryParams()); ?></div>
						
						<div class="sql-queries-item-info">
							<div>Duration:
								<?=$renderer->SQLQueryDuration( $q )?>
							</div>
							<div>Rows count: <?= $q->getRowsCount(); ?></div>
							<div>
								<button type="button" onclick="ProfilerResult.showSQLQueryBt('<?=$i?>');" class="bt-btn">&#x1F50E; Where's the query coming from?</button>
							</div>
							<div>Run block <button type="button" onclick="ProfilerResult.showRumBlock('<?= $q->getBlockId(); ?>');ProfilerResult.selectTab('run-blocks');"><?= $blocks[$q->getBlockId()]->getLabel(); ?></button></div>
						</div>
					</div>


				<?php endforeach; ?>
			</div>
		</div>
	</div>


	<div id="backtraces-dialog" style="display:none;">
		<div class="backtraces-dialog-title">
			<b>🛈</b>
			<button type="button" onclick="document.getElementById('backtraces-dialog').style.display='none';">&#x2715;</button>
		</div>
		
		<div id="backtraces">
		
		</div>
	</div>

	

</body>
</html>