<?php

class UOJProblemDataDisplayer {
	public UOJProblem $problem;
	public ZipArchive $data_zip;
	public string $data_zip_root;
	public finfo $finfo;

	public array $problem_conf = [];
	public array $rest_data_files = [];
	public array $tabs = [];

	public function __construct($problem) {
		$this->problem = $problem;
		$this->data_zip = new ZipArchive;
		$ret = $this->data_zip->open($this->problem->getDataZipPath(), ZipArchive::RDONLY);
		if ($ret !== true) {
			UOJLog::error('zip open failed: ', $this->problem->getDataZipPath(), $ret);
		}
		$this->data_zip_root = $this->problem->info['id'] . '/';
		$this->finfo = new finfo(FILEINFO_MIME_ENCODING);

		for ($i = 0; $i < $this->data_zip->count(); $i++) {
			$name = $this->data_zip->getNameIndex($i);
			if (strStartWith($name, $this->data_zip_root) && !strEndWith($name, '/')) {
				$this->rest_data_files[substr($name, strlen($this->data_zip_root))] = true;
			}
		}
	}

	public function setProblemConf(array $problem_conf) {
		foreach ($problem_conf as $key => $val) {
			$this->problem_conf[$key] = ['val' => $val];
		}
	}

	public function setProblemConfRowStatus($key, $status) {
		$this->problem_conf[$key]['status'] = $status;
		return $this;
	}

	public function addTab($file_name, $fun) {
		$this->tabs[$file_name] = $fun;
		return $this;
	}
	public function echoAllTabs($active_tab) {
		$rest = array_keys($this->rest_data_files);
		natsort($rest);
		foreach (array_merge(array_keys($this->tabs), $rest) as $tab) {
			if ($tab !== $active_tab) {
				echo '<li class="nav-item">', '<a class="nav-link" href="#">';
			} else {
				echo '<li class="nav-item">', '<a class="nav-link active" href="#">';
			}
			echo HTML::escape($tab), '</a>';
			echo '</li>';
		}
	}
	public function echoFileNotFound($file_name) {
		echo '<h4>', HTML::escape($file_name), '<sub class="text-danger"> ', '文件未找到', '</sub></h4>';
	}
	public function echoFilePre($file_name, $max_len = 1000) {
		$content = $this->getFile($file_name, $max_len + 4);
		if ($content === false) {
			$this->echoFileNotFound($file_name);
			return;
		}
		$mimetype = $this->finfo->buffer($content);
		if ($mimetype === false) {
			$this->echoFileNotFound($file_name);
			return;
		}

		echo '<h5 class="mb-1">', HTML::escape($file_name), '</h5>';
		echo '<div class="text-muted small mb-1 font-monospace">', $mimetype, '</div>';
		echo '<pre class="bg-light rounded uoj-pre">', "\n";
		$type = $mimetype == 'binary' ? 'binary' : 'text';
		echo HTML::escape(uojStringPreview($content, $max_len, $type));
		echo "\n</pre>";
	}
	public function echoProblemConfTable() {
		echo '<table class="table table-bordered text-center caption-top">';
		echo '<caption>problem.conf</caption>';
		echo '<thead>';
		echo '<tr>';
		echo '<th>key</th>';
		echo '<th>value</th>';
		echo '</tr>';
		echo '</thead>';
		echo '<tbody>';
		foreach ($this->problem_conf as $key => $info) {
			$val = isset($info['val']) ? $info['val'] : '';
			if (!isset($info['status'])) {
				echo '<tr>';
				echo '<td>', HTML::escape($key), '</td>';
				echo '<td>', HTML::escape($val), '</td>';
				echo '</tr>';
			} elseif ($info['status'] == 'danger') {
				echo '<tr class="text-danger">';
				echo '<td>', HTML::escape($key), '</td>';
				echo '<td>', HTML::escape($val), ' <span class="bi bi-x-large"></span>', '</td>';
				echo '</tr>';
			}
		}
		echo '</tbody>';
		echo '</table>';
	}

	public function displayFile($file_name) {
		if ($file_name === null) {
			$this->echoFileNotFound('');
		}
		if (isset($this->tabs[$file_name])) {
			($this->tabs[$file_name])($this);
		} elseif (isset($this->rest_data_files[$file_name])) {
			$this->echoFilePre($file_name);
		} else {
			$this->echoFileNotFound($file_name);
		}
	}

	public function isFile($name) {
		return $this->data_zip->statName($this->data_zip_root . $name);
	}

	public function getFile($name, $max_len = 0) {
		return $this->data_zip->getFromName($this->data_zip_root . $name, $max_len);
	}
}