<template>
	<transition appear name="fade">
		<div v-if="tmdbId !== undefined" class="modal p-8 overflow-auto items-center z-50" @click.self="close">
			<transition name="slide" appear
				@before-enter="lockScroll(true)" @enter-cancelled="lockScroll(false)"
				@leave="lockScroll(false)" @leave-cancelled="lockScroll(true)">
				<div v-if="movie !== undefined" class="relative w-full max-w-6xl bg-white md:bg-none overflow-hidden rounded-xl flex-col flex-shrink-0 shadow-xl">
					<div class="bg-center bg-cover bg-no-repeat" :class="{ 'text-white': isDark }"
						:style="movie.backdropPath ? `background: url('/api/tmdb/image/w1280${movie.backdropPath}')` : ''">
						<div class="movie-modal-content z-10" :style="backdropOverlayStyle">
							<div class="flex p-4 items-center">
								<movie-poster v-if="movie.posterPath" :src="movie.posterPath"
									class="w-3/12 flex-shrink-0 rounded-xl shadow-md md:shadow-xl" @onLoad="onPosterLoad"/>
								<div class="p-4 flex flex-col justify-center">
									<h2 class="text-lg md:text-4xl">
										<span class="font-bold">{{ movie.title }}</span>
										<span class="opacity-70" v-if="releaseYear"> ({{ releaseYear }})</span>
									</h2>
									<div class="flex font-light dot-separated">
										<span v-if="releaseDate">{{ releaseDate }}</span>
										<span v-if="runtime">{{ runtime }}</span>
									</div>
									<div v-if="movie?.overview" class="mt-4 hidden md:block">
										<p class="">{{movie?.overview}}</p>
									</div>
									<div class="mt-4 hidden md:block">
										<a class="inline-block py-2 px-6 rounded-full shadow-md hover:shadow-lg focus:outline-none ring-0 transition-transform transform hover:scale-105" :class="{ 'bg-white text-black': isDark, 'bg-black text-white': !isDark }"
											v-if="movie.plexLink !== null" :href="movie.plexLink" target="_blank">Watch Now</a>
										<template v-else-if="movie.requestedBy !== null">
											<button class="inline-block py-2 px-6 rounded-full shadow-md hover:shadow-lg disabled:opacity-50 disabled:cursor-default focus:outline-none ring-0 transition-transform transform hover:scale-105" :class="{ 'bg-white text-black': isDark, 'bg-black text-white': !isDark }"
												v-if="movie.requestedBy.id == userId" @click="cancel">Cancel Request</button>
											<button class="inline-block py-2 px-6 rounded-full shadow-md hover:shadow-lg disabled:opacity-50 disabled:cursor-default focus:outline-none ring-0 transition-transform transform hover:scale-105" :class="{ 'bg-white text-black': isDark, 'bg-black text-white': !isDark }"
												v-else disabled>Requested by Another User</button>
										</template>
										<button v-else class="inline-block py-2 w-36 rounded-full shadow-md hover:shadow-lg disabled:opacity-50 disabled:cursor-default focus:outline-none ring-0 transition-transform transform hover:scale-105" :class="{ 'bg-white text-black': isDark, 'bg-black text-white': !isDark }"
											:disabled="isRequesting" @click="request">{{isRequesting ? "Processing..." : "Request"}}</button>
									</div>
								</div>
							</div>
						</div>
					</div>
					<div class="p-4 space-y-4 md:hidden z-20" style="box-shadow: 0px -10px 10px rgba(0, 0, 0, 0.10);" >
						<div v-if="movie?.overview">
							<h3 class="font-bold mb-2">Overview</h3>
							<p>{{ movie.overview }}</p>
						</div>
						<div class="text-center">
							<a class="inline-block py-2 px-8 rounded-full shadow-sm bg-red-500 hover:bg-black transition-colors text-white focus:outline-none ring-0"
								v-if="movie.plexLink !== null" :href="movie.plexLink">Watch Now</a>
							<template v-if="movie.requestedBy !== null">
								<button class="inline-block py-2 px-8 rounded-full bg-red-500 text-white disabled:opacity-50" @click="cancel"
									v-if="movie.requestedBy.id == userId">Cancel Request</button>
								<button class="inline-block py-2 px-8 rounded-full bg-red-500 text-white disabled:opacity-50" disabled
									v-else>Requested by Another User</button>
							</template>
							<button v-else class="inline-block py-2 px-8 rounded-full shadow-sm bg-red-500 hover:bg-black transition-colors text-white disabled:opacity-50 disabled:cursor-default focus:outline-none ring-0 disabled:bg-black"
								:disabled="isRequesting" @click="request">{{isRequesting ? "Processing..." : "Request"}}</button>
						</div>
					</div>
				</div>
			</transition>
		</div>
	</transition>
</template>

<script lang="ts">
import type { IMovieDetails } from "@autoplex-api/request";
import { Status } from "@autoplex/restful";
import { defineComponent } from "vue";
import { getAverageRgb } from "../../util";
import { useStore, Mutation, Action } from "../../store";
import MoviePoster from "../MoviePoster.vue";
import { mapGetters } from "vuex";

export default defineComponent({
	components: {
		MoviePoster
	},
	computed: {
		...mapGetters(["userId"]),
		backdropOverlayStyle(): string {
			let { r, g, b } = this.rgb;
			return `background-image: linear-gradient(to right, rgba(${r}, ${g}, ${b}, 1.0), rgba(${r}, ${g}, ${b}, 0.84)`;
		},
		isDark(): boolean {
			let { r, g, b } = this.rgb;
			return (r*0.299 + g*0.587 + b*0.114) <= 186;
			// r /= 255;
			// g /= 255;
			// b /= 255;
			// r = r <= 0.03928 ? r/12.92 : Math.pow((r+0.055)/1.055, 2.4);
			// g = g <= 0.03928 ? r/12.92 : Math.pow((r+0.055)/1.055, 2.4);
			// b = b <= 0.03928 ? r/12.92 : Math.pow((r+0.055)/1.055, 2.4);
			// let L = 0.2126*r + 0.7152*g + 0.0722*b;
			// return L <= 0.179;
		},
		releaseYear(): string {
			if (!this.movie || !this.movie.releaseDate) {
				return "";
			}
			return this.movie.releaseDate.slice(0, 4);
		},
		releaseDate(): string {
			if (!this.movie || !this.movie.releaseDate) {
				return "";
			}
			let [year, month, day] = this.movie.releaseDate.split('-');
			return `${month}/${day}/${year}`;
		},
		runtime(): string {
			if (!this.movie || !this.movie.runtime) {
				return "";
			}
			let hours = Math.floor(this.movie.runtime / 60);
			let minutes = Math.floor(this.movie.runtime % 60);
			return (hours > 0 ? `${hours}h ` : "") + `${minutes}m`;
		}
	},
	data() {
		return {
			rgb: {r: 0, g: 0, b: 0},
			movie: <IMovieDetails|undefined>undefined,
			isPosterLoaded: false,
			isRequesting: false
		}
	},
	methods: {
		lockScroll(lock: boolean) {
			useStore().commit(Mutation.LockScroll, lock);
		},
		close() {
			this.movie = undefined;
			this.$emit("onClose");
		},
		onKeyPress(event: KeyboardEvent) {
			if (event.key != "Escape") {
				return;
			}
			this.close();
		},
		onPosterLoad(img: HTMLImageElement) {
			this.isPosterLoaded = true;
			this.computeBackdropColor(img);
		},
		computeBackdropColor(img: HTMLImageElement) {
			// This is being weird and this is the only way I can fix it...
			let rgb: {[k: string]: number} = {r: 0, g: 0, b: 0};
			try {
				rgb = getAverageRgb(img);
			} catch(e) {
				return { r: 0, g: 0, b: 0 };
			}

			// Adjust contrast
			let c = 60;
			let f = 259*(c + 255) / (255*(259 - c));
			for (let k in rgb) {
				rgb[k] = Math.min(Math.max(f*(rgb[k] - 128) + 128, 0), 255);
			}

			// Adjust brightness
			for (let k in rgb) {
				rgb[k] *= 0.90;
			}

			this.rgb = <any>rgb;
		},
		async fetchMovieDetails() {
			if (this.tmdbId === undefined) {
				return;
			}
			let [status, response] = await this.$store.dispatch(Action.MovieDetails, this.tmdbId);
			if (status != Status.Ok) {
				this.close();
				return;
			}
			this.movie = response.result;
		},
		async cancel() {
			if (this.isRequesting || this.movie == null || this.movie.ticketId == null || this.movie.requestedBy?.id != this.userId) {
				return;
			}
			this.isRequesting = true;
			let [status, response] = await this.$store.dispatch(Action.CancelMovieRequest, this.movie.ticketId);
			this.isRequesting = false;
			if (status != Status.Ok) {
				console.error("Failed to cancel movie request");
				return;
			}
			this.movie.ticketId = null;
			this.movie.requestedBy = null;
			this.$emit("onCancel", this.movie);
		},
		async request() {
			if (this.isRequesting || this.movie == null || this.movie.tmdbId == null) {
				return;
			}
			this.isRequesting = true;
			let [status, response] = await this.$store.dispatch(Action.CreateMovieRequest, this.movie.tmdbId);
			this.isRequesting = false;
			if (status == Status.Forbidden) {
				console.error("Failed to add movie: quota has been met");
				return;
			}
			this.movie.ticketId = response.result.ticketId;
			this.movie.requestedBy = {
				id     : this.$store.state.user!.id,
				isAdmin: this.$store.state.user!.isAdmin,
				name   : this.$store.state.user!.name,
			}
		}
	},
	mounted() {
		document.addEventListener("keydown", this.onKeyPress);
		this.fetchMovieDetails();
	},
	beforeUnmount() {
		document.removeEventListener("keydown", this.onKeyPress);
	},
	props: {
		tmdbId: {
			type: [Number, String],
			required: false
		}
	},
	watch: {
		tmdbId() {
			this.fetchMovieDetails();
		}
	}
});
</script>

<style lang="postcss">
.dot-separated > *:not(:first-child)::before {
	@apply px-2;
	content: '\2022'
}

.modal button {
	@apply ring-0;
}

.modal button:focus-visible {
	@apply ring-2 ring-indigo-500 ring-offset-2;
}

</style>
