<?php

use Gregwar\Captcha\PhraseBuilder;

requirePHPLib('form');

Auth::check() || redirectToLogin();
UOJUser::checkPermission(Auth::user(), 'users.upload_image') || UOJResponse::page403();

$extra = UOJUser::getExtra($user);
$limit = $extra['image_hosting']['total_size_limit'];
$used = DB::selectSingle([
	"select sum(size)",
	"from users_images",
	"where", [
		"uploader" => Auth::id(),
	],
]);
$count = DB::selectCount([
	"select count(*)",
	"from users_images",
	"where", [
		"uploader" => Auth::id(),
	],
]);

function throwError($msg) {
	dieWithJsonData(['status' => 'error', 'message' => $msg]);
}

$allowedTypes = [IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_WEBP];
if ($_POST['image_upload_file_submit'] == 'submit') {
	if (!crsf_check()) {
		throwError('expired');
	}

	if (!isset($_SESSION['phrase']) || !PhraseBuilder::comparePhrases($_SESSION['phrase'], $_POST['captcha'])) {
		unset($_SESSION['phrase']);

		throwError("bad_captcha");
	}

	unset($_SESSION['phrase']);

	if ($_FILES["image_upload_file"]["error"] > 0) {
		throwError($_FILES["image_upload_file"]["error"]);
	}

	if ($_FILES["image_upload_file"]["size"] > 5242880) { // 5 MB
		throwError('too_large');
	}

	if ($used + $_FILES["image_upload_file"]["size"] > $limit) {
		throwError('storage_limit_exceeded');
	}

	$size = getimagesize($_FILES['image_upload_file']['tmp_name']);

	if (!$size || !in_array($size[2], $allowedTypes)) {
		throwError('not_a_image');
	}

	list($width, $height, $type) = $size;
	$hash = hash_file("sha256", $_FILES['image_upload_file']['tmp_name']) . Auth::id();
	$scale = ceil($width / 600.0);

	$watermark_text = UOJConfig::$data['profile']['oj-name-short'];
	if (isSuperUser(Auth::user()) && $_POST['watermark'] == 'no_watermark') {
		$watermark_text = "";
		$hash .= "__no_watermark";
	} elseif ($_POST['watermark'] == 'site_shortname_and_username') {
		$watermark_text .= ' @' . Auth::id();
		$hash .= "__id";
	}

	$existing_image = DB::selectFirst("SELECT * FROM users_images WHERE `hash` = '$hash'");

	if ($existing_image) {
		dieWithJsonData(['status' => 'success', 'path' => $existing_image['path']]);
	}

	$image = new Imagick($_FILES["image_upload_file"]["tmp_name"]);
	$draw = new ImagickDraw();
	$draw->setFont(UOJContext::documentRoot() . '/fonts/roboto-mono/RobotoMono-Bold.ttf');
	$draw->setFontSize($scale * 14);
	$draw->setGravity(Imagick::GRAVITY_SOUTHEAST);
	$draw->setFillColor("rgba(100,100,100,0.5)");
	$image->annotateImage($draw, 15, 10, 0, $watermark_text);
	$draw->setFillColor("rgba(255,255,255,0.65)");
	$image->annotateImage($draw, 15 + $scale, 10 + $scale, 0, $watermark_text);
	$image->setImageFormat('png');
	$image->writeImage();

	if (($size = filesize($_FILES["image_upload_file"]["tmp_name"])) > 5242880) { // 5 MB
		throwError('too_large');
	}

	$filename = uojRandAvaiableFileName('/image_hosting/', 10, '.png');
	if (!move_uploaded_file($_FILES["image_upload_file"]["tmp_name"], UOJContext::storagePath() . $filename)) {
		throwError('unknown error');
	}

	DB::insert([
		"insert into users_images",
		DB::bracketed_fields(["path", "uploader", "width", "height", "upload_time", "size", "hash"]),
		"values", DB::tuple([
			$filename,
			Auth::id(),
			$width,
			$height,
			DB::now(),
			$_FILES["image_upload_file"]["size"],
			$hash,
		]),
	]);

	dieWithJsonData(['status' => 'success', 'path' => $filename]);
} elseif ($_POST['image_delete_submit'] == 'submit') {
	crsf_defend();

	$id = $_POST['image_delete_id'];
	if (!validateUInt($id)) {
		becomeMsgPage('ID 不合法。<a href="' . UOJContext::requestURI() . '">返回</a>');
	} else {
		$result = DB::selectFirst("SELECT * from users_images WHERE id = $id");
		if (!$result) {
			becomeMsgPage('图片不存在。<a href="' . UOJContext::requestURI() . '">返回</a>');
		} else {
			unlink(UOJContext::storagePath() . $result['path']);
			DB::delete("DELETE FROM users_images WHERE id = $id");

			header("Location: " . UOJContext::requestURI());
			die();
		}
	}
}
?>

<?php echoUOJPageHeader(UOJLocale::get('image hosting')) ?>

<style>
	.drop {
		display: flex;
		align-items: center;
		flex-direction: column;
		justify-content: center;
		align-self: center;
		flex-grow: 0 !important;
		width: 9em;
		height: 8.75em;
		user-select: none;
		cursor: pointer;
		margin-left: 0;
		background: #fafafa;
		border: 1px solid #e8e8e8;
		box-sizing: border-box;
		border-radius: 4px;
	}

	.drop:hover {
		border-color: #89d1f5;
	}
</style>

<h1>
	<?= UOJLocale::get('image hosting') ?>
</h1>

<div class="card card-default">
	<div class="card-body">
		<form class="row m-0" id="image-upload-form" method="post" enctype="multipart/form-data">
			<div class="col-12 col-md-3 col-lg-3 order-1 drop mx-auto mx-md-0" id="image-upload-form-drop">
				<svg aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" width="56" class="mb-2">
					<g>
						<path fill="#3498db" d="M424.49 120.48a12 12 0 0 0-17 0L272 256l-39.51-39.52a12 12 0 0 0-17 0L160 272v48h352V208zM64 336V128H48a48 48 0 0 0-48 48v256a48 48 0 0 0 48 48h384a48 48 0 0 0 48-48v-16H144a80.09 80.09 0 0 1-80-80z"></path>
						<path fill="#89d1f5" d="M528 32H144a48 48 0 0 0-48 48v256a48 48 0 0 0 48 48h384a48 48 0 0 0 48-48V80a48 48 0 0 0-48-48zM208 80a48 48 0 1 1-48 48 48 48 0 0 1 48-48zm304 240H160v-48l55.52-55.52a12 12 0 0 1 17 0L272 256l135.52-135.52a12 12 0 0 1 17 0L512 208z"></path>
					</g>
				</svg>
				<span id="select-image-text" class="small">点击此处选择图片</span>
			</div>
			<input id="image_upload_file" name="image_upload_file" type="file" accept="image/*" style="display: none;" />
			<div class="modal fade" id="image-upload-modal" tabindex="-1" aria-hidden="true">
				<div class="modal-dialog">
					<div class="modal-content">
						<div class="modal-header">
							<h1 class="modal-title fs-5" id="exampleModalLabel">上传图片</h1>
							<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
						</div>
						<div class="modal-body">
							<div class="mb-3">
								您确定要上传图片吗?
							</div>
							<div class="mb-3" id="modal-file-info"></div>
							<div class="input-group">
								<input type="text" class="form-control" id="input-captcha" name="captcha" placeholder="<?= UOJLocale::get('enter verification code') ?>" maxlength="20" />
								<span class="input-group-text p-0 overflow-hidden rounded-0" style="border-bottom-right-radius: var(--bs-border-radius) !important">
									<img id="captcha" class="col w-100 h-100" src="/captcha">
								</span>
							</div>
							<div class="mt-3" id="modal-help-message" style="display: none"></div>
						</div>
						<div class="modal-footer">
							<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id="cancel-upload">取消</button>
							<button type="submit" class="btn btn-primary">确定</button>
						</div>
					</div>
				</div>
			</div>
			<div class="col-12 col-md-4 col-lg-2 order-2 mt-3 mt-md-0 ms-md-2">
				<h2 class="h3">水印</h2>
				<?php if (isSuperUser($myUser)) : ?>
					<div class="form-check d-inline-block d-md-block me-2">
						<input class="form-check-input" type="radio" name="watermark" id="watermark-no_watermark" data-value="no_watermark">
						<label class="form-check-label" for="watermark-no_watermark">
							无水印
						</label>
					</div>
				<?php endif ?>
				<div class="form-check d-inline-block d-md-block me-2">
					<input class="form-check-input" type="radio" name="watermark" id="watermark-site_shortname" data-value="site_shortname" checked>
					<label class="form-check-label" for="watermark-site_shortname">
						<?= UOJConfig::$data['profile']['oj-name-short'] ?>
					</label>
				</div>
				<div class="form-check d-inline-block d-md-block me-2">
					<input class="form-check-input" type="radio" name="watermark" id="watermark-site_shortname_and_username" data-value="site_shortname_and_username">
					<label class="form-check-label" for="watermark-site_shortname_and_username">
						<?= UOJConfig::$data['profile']['oj-name-short'] ?> @<?= Auth::id() ?>
					</label>
				</div>
			</div>
			<div class="col order-3 order-md-4 order-lg-3 mt-3 mt-lg-0 ms-lg-2">
				<h2 class="h3">上传须知</h2>
				<ul>
					<li>上传的图片必须符合法律与社会道德;</li>
					<li>图床仅供 S2OJ 站内使用,校外用户无法查看;</li>
					<li>图片上传后会被自动转码为 PNG 格式;</li>
					<li>在合适的地方插入图片即可引用。</li>
				</ul>
				<p class="small">更多信息可以查看 <a href="https://s2oj.github.io/#/user/apps/image_hosting" target="_blank">使用文档</a>。</p>
			</div>
			<div class="col-12 col-md-5 col-lg-3 order-4 order-md-3 order-lg-4 mt-3 mt-md-0 ms-md-2">
				<h2 class="h3">使用统计</h2>
				<div class="d-flex justify-content-between">
					<span class="small">已用空间</span>
					<span><?= round($used * 1.0 / 1024 / 1024, 2) ?> MB / <?= round($limit * 1.0 / 1024 / 1024, 2) ?> MB</span>
				</div>
				<div class="d-flex justify-content-between">
					<span class="small">上传总数</span>
					<span><?= $count ?> 张</span>
				</div>
			</div>
		</form>
	</div>
</div>
<div class="toast-container position-fixed bottom-0 start-0 ms-3 mb-4" style="z-index: 999999">
	<div id="image-upload-toast" class="toast text-bg-danger align-items-center border-0" role="alert" aria-live="assertive" aria-atomic="true">
		<div class="d-flex">
			<div class="toast-body">
				文件非法:不是有效的图片格式。
			</div>
			<button type="button" class="btn-close me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
		</div>
	</div>
</div>
<script>
	var image_upload_modal = new bootstrap.Modal('#image-upload-modal');
	var image_upload_toast = new bootstrap.Toast('#image-upload-toast', {
		delay: 2000
	});
	var droppedFiles = false;

	function refreshCaptcha() {
		var timestamp = new Date().getTime();
		$("#captcha").attr("src", "/captcha" + '?' + timestamp);
	}

	$("#captcha").click(function(e) {
		refreshCaptcha();
	});

	$('#image-upload-form').submit(function(event) {
		event.preventDefault();

		var data = new FormData();
		data.append('_token', "<?= crsf_token() ?>");
		data.append('image_upload_file_submit', 'submit');
		data.append('image_upload_file', $('#image_upload_file').prop('files')[0]);
		data.append('watermark', $('input[name=watermark]:checked', this).data('value'));
		data.append('captcha', $('#input-captcha').val());

		if ($('#image_upload_file').prop('files')[0].size > 5242880) {
			$('#modal-help-message').html('图片大小不能超过 5 MB。').show();

			return false;
		}

		$('#modal-help-message').html('上传中...').show();

		$.ajax({
			method: 'POST',
			processData: false,
			contentType: false,
			data: data,
			success: function(data) {
				if (data.status === 'success') {
					image_upload_modal.hide();
					location.reload();
				} else {
					if (data.message === 'bad_captcha') {
						refreshCaptcha();
						$('#modal-help-message').html('验证码错误。').show();
					} else if (data.message === 'expired') {
						$('#modal-help-message').html('页面过期,请刷新重试。').show();
					} else if (data.message === 'storage_limit_exceeded') {
						$('#modal-help-message').html('存储超限,请联系管理员提升限制。').show();
					} else if (data.message === 'not_a_image') {
						$('#modal-help-message').html('文件格式不受支持。').show();
					} else if (data.message === 'too_large') {
						$('#modal-help-message').html('图片大小不能超过 5 MB。').show();
					}
				}
			},
			error: function() {
				$('#modal-help-message').html('上传失败,请刷新页面重试。').addClass('text-danger').show();
			}
		});

		return false;
	});
	$('#image-upload-form-drop').click(function() {
		$('#image_upload_file').click();
	});
	$('#image-upload-form-drop').on('drag dragstart dragend dragover dragenter dragleave drop', function(e) {
		e.preventDefault();
		e.stopPropagation();
	}).on('dragover dragenter', function() {
		$('#select-image-text').html('松开以上传');
	}).on('dragleave dragend drop', function() {
		$('#select-image-text').html('点击此处选择图片');
	}).on('drop', function(e) {
		$('#image_upload_file').prop('files', e.originalEvent.dataTransfer.files);
		$('#image_upload_file').trigger('change');
	});
	$(document).on('paste', function(e) {
		if (e.originalEvent.clipboardData) {
			$('#image_upload_file').prop('files', e.originalEvent.clipboardData.files);
		}

		$('#image_upload_file').trigger('change');
	});
	$('#image-upload-modal').on('hide.bs.modal', function() {
		$('#image-upload-form').trigger('reset');
	});
	$('#image_upload_file').change(function() {
		var items = $(this).prop('files');
		var file = null;

		if (items && items.length) {
			for (var i = 0; i < items.length; i++) {
				if (items[i].type.indexOf('image') !== -1) {
					file = items[i];
					break;
				}
			}
		}

		if (file) {
			refreshCaptcha();
			var watermark_type = $('input[name=watermark]:checked', '#image-upload-form').data('value');
			var html = '';

			html += '<p><img src="' + URL.createObjectURL(file) + '" height="150" style="object-fit: contain"></p>';
			html += '<p class="small">大小:<b>' + (file.size / 1024).toFixed(2) + '</b> KB。';

			if (watermark_type === 'no_watermark') {
				html += '不添加水印。';
			} else if (watermark_type === 'site_shortname_and_username') {
				html += '使用水印:<?= UOJConfig::$data['profile']['oj-name-short'] ?> @<?= Auth::id() ?>。';
			} else {
				html += '使用水印:<?= UOJConfig::$data['profile']['oj-name-short'] ?>。';
			}

			html += '</p>';

			$('#modal-file-info').html(html);
			$('#modal-help-message').html('').hide();
			image_upload_modal.show();
		} else {
			image_upload_toast.show();
		}
	});
</script>

<?php
$pag_config = [
	'page_len' => 40,
	'col_names' => ['*'],
	'table_name' => 'users_images',
	'cond' => "uploader = '{$myUser['username']}'",
	'tail' => 'order by upload_time desc',
];
$pag = new Paginator($pag_config);
?>

<h2 class="mt-4 mb-3">
	我的图片
</h2>

<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 row-cols-lg-4 g-4">
	<?php foreach ($pag->get() as $idx => $row) : ?>
		<div class="col">
			<div class="card">
				<img src="<?= $row['path'] ?>" class="card-img-top object-fit-contain" height="200" loading="lazy" decoding="async">
				<div class="card-footer bg-transparent small px-2">
					<div class="d-flex flex-wrap justify-content-between">
						<time><?= $row['upload_time'] ?></time>
						<span>
							<?php if ($row['size'] < 1024 * 512) : ?>
								<?= round($row['size'] * 1.0 / 1024, 1) ?> KB
							<?php else : ?>
								<?= round($row['size'] * 1.0 / 1024 / 1024, 1) ?> MB
							<?php endif ?>
						</span>
					</div>
					<div class="d-flex flex-wrap justify-content-between mt-2">
						<form method="post" onsubmit="return confirm('您确定要删除这张图片吗?');">
							<input type="hidden" name="image_delete_submit" value="submit">
							<input type="hidden" name="image_delete_id" value="<?= $row['id'] ?>">
							<input type="hidden" name="_token" value="<?= crsf_token() ?>">
							<button class="btn btn-sm btn-outline-danger image-delete-button" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="删除">
								<i class="bi bi-trash3"></i>
							</button>
						</form>
						<div class="btn-group">
							<button class="btn btn-sm btn-outline-secondary image-copy-url-button" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="复制链接" data-image-path="<?= $row['path'] ?>">
								<i class="bi bi-clipboard"></i>
							</button>
							<button class="btn btn-sm btn-outline-secondary image-copy-md-button" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="复制 Markdown 源码" data-image-path="<?= $row['path'] ?>">
								<i class="bi bi-markdown"></i>
							</button>
						</div>
					</div>
				</div>
			</div>
		</div>
	<?php endforeach ?>
</div>

<?php if ($pag->isEmpty()) : ?>
	<div class="mt-4 text-muted">
		<?= UOJLocale::get('none') ?>
	</div>
<?php endif ?>

<div class="text-end">
	<?= $pag->pagination() ?>
</div>

<script>
	$('.image-copy-url-button').click(function() {
		var _this = this;
		var url = new URL($(this).data('image-path'), location.origin);

		navigator.clipboard.writeText(url).then(function() {
			$(_this).addClass('btn-success');
			$(_this).removeClass('btn-outline-secondary');
			$(_this).html('<i class="bi bi-check2"></i>');

			setTimeout(function() {
				$(_this).addClass('btn-outline-secondary');
				$(_this).removeClass('btn-success');
				$(_this).html('<i class="bi bi-clipboard"></i>');
			}, 1000);
		});
	});

	$('.image-copy-md-button').click(function() {
		var _this = this;
		var url = new URL($(this).data('image-path'), location.origin);

		navigator.clipboard.writeText('![](' + url + ')').then(function() {
			$(_this).addClass('btn-success');
			$(_this).removeClass('btn-outline-secondary');
			$(_this).html('<i class="bi bi-check2"></i>');

			setTimeout(function() {
				$(_this).addClass('btn-outline-secondary');
				$(_this).removeClass('btn-success');
				$(_this).html('<i class="bi bi-markdown"></i>');
			}, 1000);
		});

	});
</script>

<?php echoUOJPageFooter() ?>