<script setup>
import { inject, onMounted, ref } from 'vue';

import AddActor from '#/components/actors/add.vue';
import MergeActors from '#/components/actors/merge.vue';
import Admin from '#/components/admin/admin.vue';
import Checkbox from '#/components/form/checkbox.vue';

import getPath from '#/src/get-path.js';
import navigate from '#/src/navigate.js';
// import { get } from '#/src/api.js';

const { pageProps, urlParsed } = inject('pageContext');

const actors = ref(pageProps.actors);
const selectedActors = ref(new Set([]));
const activeActor = ref(null);
const actorQuery = ref(urlParsed.search.q || null);
const showAliased = ref(Object.hasOwn(urlParsed.search, 'alias'));

const lastSelectedIndex = ref(null);
const holdingShift = ref(false);
const showMergeDialog = ref(false);
const showAddDialog = ref(false);

function selectActors(selectedActor, isChecked, index) {
	const [start, end] = holdingShift.value
		? [index, lastSelectedIndex.value].toSorted((indexA, indexB) => indexA - indexB)
		: [index, index];

	const actorIds = actors.value
		.slice(start, end + 1)
		.map((actor) => actor.id);

	actorIds.forEach((actorId) => {
		if (isChecked) {
			selectedActors.value.add(actorId);
		}
		else {
			selectedActors.value.delete(actorId);
		}
	});

	lastSelectedIndex.value = index;
}

async function searchActors() {
	navigate('/admin/actors', {
		q: actorQuery.value || undefined,
		alias: showAliased.value || undefined,
	}, { redirect: true });
}

onMounted(() => {
	window.addEventListener('keydown', (event) => {
		if (event.key === 'Shift') {
			holdingShift.value = true;
		}
	});

	window.addEventListener('keyup', (event) => {
		if (event.key === 'Shift') {
			holdingShift.value = false;
		}
	});

	window.addEventListener('blur', () => {
		holdingShift.value = false;
	});
});
</script>

<template>
	<Admin class="page">
		<div class="header">
			<form
				class="search"
				@submit.prevent="searchActors"
			>
				<input
					v-model="actorQuery"
					type="input"
					placeholder="Search actors"
					class="input search-input"
				>

				<button
					v-if="actorQuery?.length"
					type="button"
					class="search-cancel nobutton"
					@click="actorQuery = ''; searchActors()"
				>
					<Icon icon="cross2" />
				</button>
			</form>

			<Checkbox
				label="Show aliased"
				:checked="showAliased"
				@change="(checked) => { showAliased = checked; searchActors(); }"
			/>

			<div class="header-actions">
				<button
					class="button"
					:disabled="selectedActors.size === 0"
					@click="selectedActors = new Set()"
				><Icon icon="cancel-square" />Deselect</button>

				<button
					class="button"
					:disabled="selectedActors.size === 0"
					@click="showMergeDialog = true"
				><Icon icon="make-group" />Merge</button>

				<button
					class="button"
					@click="showAddDialog = true"
				><Icon icon="plus3" />Add actor</button>
			</div>
		</div>

		<table class="actors">
			<thead class="actors-header">
				<tr>
					<th class="actor-id">ID</th>
					<th class="actor-name">Entity</th>
					<th class="actor-avatar">Avatar</th>
					<th class="actor-name">Name</th>
				</tr>
			</thead>

			<tbody class="actors-body">
				<tr
					v-for="(actor, index) in actors"
					:key="`actor-${actor.id}`"
					class="actor"
				>
					<td class="actor-id ellipsis">
						<a
							:href="`/actor/${actor.id}/${actor.slug}?inspect`"
							target="_blank"
							class="nolink"
						>{{ actor.id }}</a>
					</td>

					<td
						v-tooltip="{ content: actor.alias ? `#${actor.alias.id} ${actor.alias.name}` : (actor.entity?.name || 'Global'), ariaId: `actor-entity-${actor.id}` }"
						class="actor-entity ellipsis"
					>
						<Icon
							v-if="actor.alias"
							icon="at-sign"
							class="actor-alias"
						/>

						<img
							v-else-if="actor.entity"
							:src="`/logos/${actor.entity.slug}/favicon_dark.png`"
							class="actor-favicon"
						>

						<Icon
							v-else
							icon="device_hub"
							class="actor-global"
						/>
					</td>

					<td class="actor-avatar">
						<img
							v-if="actor.avatar"
							:src="getPath(actor.avatar, 'lazy')"
							loading="lazy"
							class="avatar"
						>

						<img
							v-if="actor.avatar"
							:src="getPath(actor.avatar)"
							loading="lazy"
							class="avatar-zoom"
						>
					</td>

					<td class="actor-name ellipsis">{{ actor.name }}</td>

					<td class="actor-actions">
						<div class="actions">
							<Checkbox
								:checked="selectedActors.has(actor.id)"
								@change="(isChecked) => selectActors(actor, isChecked, index)"
							/>

							<a
								:href="`/actor/edit/${actor.id}/${actor.slug}`"
								target="_blank"
							>
								<Icon
									v-tooltip="{ content: 'Edit bio', ariaId: `actor-edit-${actor.id}` }"
									icon="pencil5"
									class="actor-action action-merge"
								/>
							</a>

							<Icon
								v-tooltip="{ content: 'Merge', ariaId: `actor-merge-${actor.id}` }"
								icon="make-group"
								class="actor-action action-merge"
								@click="activeActor = actor; showMergeDialog = true;"
							/>

							<!--
							<Icon
								v-tooltip="'Delete'"
								icon="bin"
								class="actor-action action-delete"
							/>
							-->
						</div>
					</td>
				</tr>
			</tbody>
		</table>

		<MergeActors
			v-if="showMergeDialog"
			:actors="activeActor ? [activeActor] : actors.filter((actor) => selectedActors.has(actor.id))"
			@close="showMergeDialog = false; activeActor = null;"
		/>

		<AddActor
			v-if="showAddDialog"
			@close="showAddDialog = false"
		/>
	</Admin>
</template>

<style scoped>
.search {
	display: flex;
	align-items: center;
	max-width: 20rem;
	flex-grow: 1;
}

.search-input {
	flex-grow: 1;
}

.header {
	display: flex;
	gap: 1rem;
	margin-bottom: 1rem;
}

.header-actions {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: .5rem;
	flex-grow: 1;
}

.actors-header tr {
	text-align: left;
}

.actors, .actors th, .actors td {
	border-collapse: collapse;
	padding: .5rem;
	border: 0;
}

.actor {
	&:nth-child(2n) {
		background: var(--glass-weak-50);
	}

	&:hover {
		background: var(--glass-weak-40);
	}
}

.actor-id {
	width: 6rem;
	font-family: monospace;
	font-size: 1rem;
	user-select: all;
}

.actor-entity {
	width: 2rem;
}

.actor-favicon {
	width: 1rem;
	margin-left: .5rem;
}

.actor-global {
	background: var(--primary);
	fill: var(--text-light);
	padding: .5rem;
	border-radius: 1rem;
}

.actor-alias {
	fill: var(--primary);
	padding: .5rem;
}

th.actor-actions {
	display: flex;
	align-items: center;
	gap: .5rem;

	.button:first-child {
		margin-left: .5rem;
	}
}

.actor-actions {
	width: 1%;
	white-space: nowrap;
}

.actions {
	display: flex;
	align-items: center;
}

.actor-action {
	padding: .5rem .75rem;
	fill: var(--glass);

	&:hover {
		cursor: pointer;
		fill: var(--primary);
	}

	&:hover.action-delete {
		fill: var(--error);
	}
}

.actor-avatar {
	width: 5rem;
	position: relative;
	line-height: 0;

	&:hover .avatar-zoom,
	&:active .avatar-zoom {
		display: inline-block;
	}
}

.avatar {
	height: 3.5rem;
	max-width: 100%;
}

.avatar-zoom {
	display: none;
	height: 50vh;
	position: absolute;
	top: 0;
	left: 0;
	z-index: 10;
	box-shadow: 0 0 3px var(--shadow-weak-30);
	pointer-events: none;
}

.check-container {
	display: inline-flex;
	padding: .5rem .75rem;
}
</style>
