<?php

class UOJSubmissionHistory {
	use UOJDataTrait;

	public $submission = null;
	public $n_versions;

	public static $fields_without_result = [
		'tid' => 'id', 'message' => 'judge_reason', 'time' => 'judge_time',
		'judger', 'status', 'result_error',
		'actual_score' => 'score', 'used_time', 'used_memory',
		'type' => 'if(major, "major", "minor")'
	];

	public static $fields = [
		'tid' => 'id', 'message' => 'judge_reason', 'time' => 'judge_time',
		'judger', 'result', 'status', 'result_error',
		'actual_score' => 'score', 'used_time', 'used_memory',
		'type' => 'if(major, "major", "minor")'
	];

	public static function query(UOJSubmission $submission, $cfg = []) {
		$cfg += [
			'minor' => false,
			'system' => true
		];

		$q = [
			"select", DB::fields([
				'tid' => DB::value(0),
				'message' => 'judge_reason',
				'time' => DB::if_func(['judge_time' => null], UOJTime::MAX_TIME, DB::raw('judge_time')),
				'judger', 'status', 'result_error',
				'actual_score' => UOJSubmission::sqlForActualScore(), 'used_time', 'used_memory',
				'type' => DB::value('major'),
				'priority' => 1000,
			]), "from submissions",
			"where", ["id" => $submission->info['id']],
			"union all",
			"select", DB::fields(
				UOJSubmissionHistory::$fields_without_result + [
					'priority' => 100
				]
			),
			"from submissions_history",
			"where", [
				'submission_id' => $submission->info['id'],
				['judge_time', 'is not', null]
			] + ($cfg['minor'] ? [] : ['major' => true]),
			"union all",
			"select", DB::fields([
				'tid' => DB::value(-1),
				'message',
				'time',
				'judger' => DB::value(null), 'status' => DB::value(null), 'result_error' => DB::value(null),
				'actual_score' => DB::value(null), 'used_time' => DB::value(null), 'used_memory' => DB::value(null),
				'type',
				'priority' => 99
			]), "from system_updates",
			"where", [
				'type' => 'problem',
				'target_id' => $submission->info['problem_id']
			],
			"union all",
			"select", DB::fields([
				'tid' => DB::value(-1),
				'message' => DB::value(''),
				'time' => 'submit_time',
				'judger' => DB::value(null), 'status' => DB::value(null), 'result_error' => DB::value(null),
				'actual_score' => DB::value(null), 'used_time' => DB::value(null), 'used_memory' => DB::value(null),
				'type' => DB::value('submit'),
				'priority' => 10
			]), "from submissions",
			"where", ["id" => $submission->info['id']],
		];
		if ($cfg['system']) {
			$q = array_merge($q, [
				"union all",
				"select", DB::fields([
					'tid' => DB::value(-1),
					'message',
					'time',
					'judger' => DB::value(null), 'status' => DB::value(null), 'result_error' => DB::value(null),
					'actual_score' => DB::value(null), 'used_time' => DB::value(null), 'used_memory' => DB::value(null),
					'type',
					'priority' => 10
				]), "from system_updates",
				"where", [
					['type', 'in', DB::rawtuple(['judge', 'submissions_history'])]
				]
			]);
		}
		$q = array_merge($q, [
			"order by time, priority asc"
		]);

		$ret = DB::selectAll($q);
		if ($ret === false) {
			return null;
		}

		$st = null;
		$ed = null;
		foreach ($ret as $idx => &$his) {
			if ($his['type'] == 'major' || $his['type'] == 'minor' || $his['type'] == 'submit') {
				$ed = $idx;
				if ($his['type'] == 'submit') {
					$st = $idx;
				}
			}
			if ($his['time'] == UOJTime::MAX_TIME) {
				$his['time'] = null;
			}
			UOJSubmission::roundScoreInArray($his, 'actual_score');
		}

		$res = [];
		foreach ($ret as $idx => &$his) {
			if ($st !== null && $idx >= $st) {
				$res[] = $his;
			}
		}
		$res = array_reverse($res);
		return new UOJSubmissionHistory($res, $submission);
	}

	public function __construct($info, UOJSubmission $submission) {
		$this->info = $info;
		$this->submission = $submission;

		$this->n_versions = 0;
		foreach ($this->info as $his) {
			if ($his['type'] == 'major' || $his['type'] == 'minor') {
				$this->n_versions++;
			}
		}
	}

	public function echoTimeline() {
		echo '<div class="list-group timeline">';
		if ($this->submission->isLatest()) {
			echo '<p class="text-success"><i class="bi bi-check-circle"></i> 你现在查看的是最新测评结果</p>';
		} else if (UOJSubmission::info('judge_time') !== null) {
			if ($this->submission->isMajor()) {
				echo '<p class="text-danger"><i class="bi bi-exclamation-circle"></i> 你现在查看的是测评时间为 ', UOJSubmission::info('judge_time'), ' 的历史记录</p>';
			} else {
				echo '<p class="text-warning"><i class="bi bi-exclamation-circle"></i> 你现在查看的是测评时间为 ', UOJSubmission::info('judge_time'), ' 的隐藏记录</p>';
			}
		}
		$h = clone $this->submission;
		$cfg = [
			'show_actual_score' => true
		];
		foreach ($this->info as $his) {
			$message = json_decode($his['message'], true);
			$show_result = true;

			$extra = null;

			if ($his['type'] == 'major' || $his['type'] == 'minor') {
				$h->loadHistory($his);
				$cls = 'list-group-item rounded-0';
				if ($h->info['tid'] == $this->submission->getTID()) {
					$cls .= ' list-group-item-warning';
				}
				echo '<div class="', $cls, '">';
				$extra = '<a class="text-decoration-none" href="' . $h->getUri() . '"><i class="bi bi-info-circle"></i> 查看</a>';
				$split_cls = ['col-sm-10', 'col-sm-2'];
			} else {
				$show_result = false;
				echo '<div class="list-group-item rounded-0">';
			}

			if ($extra) {
				echo '<div class="row align-items-center">';
				echo '<div class="', $split_cls[0], '">';
			}

			echo '<ul class="list-group-item-text list-inline text-primary mb-1">';
			echo '<li class="list-inline-item">';
			if ($his['time'] !== null) {
				echo '<strong>[', $his['time'], ']</strong>';
			} else {
				$show_result = false;
				if ($his['type'] == 'major' || $his['type'] == 'minor') {
					echo '<strong>[', $h->echoStatusBarTD('result', $cfg), ']</strong>';
				} else {
					echo '<strong>[error]</strong>';
				}
			}
			echo '</li>';

			echo '<li class="list-inline-item">';
			if (empty($message['text'])) {
				if ($his['type'] == 'submit') {
					echo '提交';
				} else {
					echo '评测';
				}
			} else {
				echo HTML::escape($message['text']);
			}
			echo '</li>';

			echo '<li class="list-inline-item">';
			if (!empty($message['url'])) {
				echo '(', HTML::autolink($message['url']), ')';
			}
			echo '</li>';
			echo '</ul>';

			if ($show_result) {
				echo '<ul class="-text list-inline mb-0">';
				echo '<li class="list-inline-item">';
				echo '<strong>测评结果:</strong>';
				echo $h->echoStatusBarTD('result', $cfg);
				echo '</li>';
				echo '<li class="list-inline-item">';
				echo '<strong>用时:</strong>';
				echo $h->echoStatusBarTD('used_time', $cfg);
				echo '</li>';
				echo '<li class="list-inline-item">';
				echo '<strong>内存:</strong>';
				echo $h->echoStatusBarTD('used_memory', $cfg);
				echo '</li>';
				echo '</ul>';
			}

			if ($extra) {
				echo '</div>'; // col-md-9
				echo '<div class="', $split_cls[1], ' text-end">', $extra, '</div>';
				echo '</div>'; // row
			}

			echo '</div>'; // 
		}
		echo '</div>';
	}
}