<template>
	<div class="filter actors-container">
		<div
			v-if="isAggActorsLimited"
			class="filter-disclaimer"
		>Some actors may not be listed, apply a filter or search to narrow down results.</div>

		<div class="filters-sort">
			<input
				v-model="search"
				type="search"
				:placeholder="`Filter ${availableActors.length} actors`"
				class="input input-inline filters-search"
			>

			<div
				class="filter-sort noselect"
				@click="selectGender"
			>
				<div
					v-if="!selectedGender"
					class="gender-unselected"
				><Icon icon="genders" /></div>

				<Gender
					v-else
					:gender="selectedGender"
					class="gender"
				/>
			</div>

			<div
				v-show="order === 'name'"
				class="filter-sort order noselect"
				@click="order = 'count'"
			>
				<Icon
					icon="sort-alpha-asc"
				/>
			</div>

			<div
				v-show="order === 'count'"
				class="filter-sort order noselect"
				@click="order = 'name'"
			>
				<Icon
					icon="sort-numeric-desc"
				/>
			</div>
		</div>

		<div
			v-if="availableActors.length === 0 && selectedActors.length === 0"
			class="filter-empty"
		>No actors</div>

		<template v-else>
			<ul
				v-for="(actor, index) in selectedActors"
				:key="`actor-${actor.id}`"
				class="filter-items nolist"
			>
				<Actor
					:actor="actor"
					:index="index"
					:filters="filters"
					:toggle-actor="(actor) => toggleActor(actor, true)"
					type="selected"
					@actor="(actor) => toggleActor(actor, false)"
				/>
			</ul>

			<UseVirtualList
				:list="availableActors"
				:options="{ itemHeight: 30 }"
				style="height: 20rem;"
				class="filter-items nolist"
			>
				<template #default="{ data: actor, index }">
					<Actor
						:actor="actor"
						:index="index"
						:filters="filters"
						:toggle-actor="(actor) => toggleActor(actor, true)"
						type="available"
						@actor="(actor) => toggleActor(actor, false)"
					/>
				</template>
			</UseVirtualList>
		</template>
	</div>
</template>

<script setup>
import { ref, computed, inject } from 'vue';
import { UseVirtualList } from '@vueuse/components';

import Actor from '#/components/filters/actor.vue';
import Gender from '#/components/actors/gender.vue';

const props = defineProps({
	filters: {
		type: Object,
		default: null,
	},
	actors: {
		type: Array,
		default: () => [],
	},
});

const emit = defineEmits(['update']);

const search = ref('');
const searchRegexp = computed(() => new RegExp(search.value, 'i'));
const selectedGender = ref(null);
const order = ref('count');

const pageContext = inject('pageContext');
const pageProps = pageContext.pageProps;
const { actor: pageActor } = pageProps;

const selectedActors = computed(() => props.filters.actors.map((filterActor) => props.actors.find((actor) => actor.id === filterActor.id)).filter(Boolean));

const availableActors = computed(() => props.actors
	.filter((actor) => !props.filters.actors.some((filterActor) => filterActor.id === actor.id)
		&& actor.id !== pageActor?.id
		&& searchRegexp.value.test(actor.name)
		&& (!selectedGender.value || actor.gender === selectedGender.value))
	.sort((actorA, actorB) => {
		if (order.value === 'count') {
			return actorB.count - actorA.count;
		}

		return actorA.name.localeCompare(actorB.name);
	}));

const genders = computed(() => [null, ...['female', 'male', 'transsexual', 'other'].filter((gender) => props.actors.some((actor) => actor.gender === gender))]);
const isAggActorsLimited = computed(() => props.actors.length >= pageContext.env.maxAggregateSize);

function toggleActor(actor, combine) {
	if (props.filters.actors.some((filterActor) => filterActor.id === actor.id)) {
		emit('update', 'actors', props.filters.actors.filter((filterActor) => filterActor.id !== actor.id));
		return;
	}

	if (combine) {
		emit('update', 'actors', props.filters.actors.concat(actor));
	} else {
		emit('update', 'actors', [actor]);
	}
}

function selectGender() {
	const genderIndex = genders.value.indexOf(selectedGender.value);

	if (genderIndex >= genders.value.length - 1) {
		selectedGender.value = genders.value[0];
		return;
	}

	selectedGender.value = genders.value[genderIndex + 1];
}
</script>

<style scoped>
.filter {
	padding: 0;
}

.filter-item.first {
	border-top: solid 1px var(--shadow-weak-30);
}

.filter-items {
	max-height: unset;
}
</style>
