import { VoidComponent, createResource, onMount, ParentComponent, ParentProps, Show, useContext, For } from 'solid-js';
import { createDateNow, getTime } from '@solid-primitives/date';

import { timeline } from '@motionone/dom';
import { AnimationOptions } from '@motionone/types';
import { Motion } from "@motionone/solid";

import { Line, TrafficStatus } from './types';
import { renderLineTransportMode, renderLinePicto } from './utils';
import { BusinessDataContext, BusinessDataStore } from "./businessData";

import styles from './passagesPanel.module.css';


const UnavailablePassage: VoidComponent<{ style: string }> = (props) => {
	const textStyle = { fill: "#000000" };

	return (
		<div class={props.style}>
			<svg viewBox="0 0 230 110">
				<text x="100%" y="26" font-size="25" text-anchor="end" style={textStyle}>Information</text>
				<text x="100%" y="63" font-size="25" text-anchor="end" style={textStyle}>non</text>
				<text x="100%" y="100" font-size="25" text-anchor="end" style={textStyle}>disponible</text>
			</svg>
		</div>
	);
}

const TtwPassage: VoidComponent<{ line: Line, destination: string, index: number, style: string, fontSize: number, fallbackStyle: string }> = (props) => {

	const businessDataContext: BusinessDataStore | undefined = useContext(BusinessDataContext);
	if (businessDataContext === undefined)
		return <div />;

	const { getDestinationPassages } = businessDataContext;

	const [dateNow] = createDateNow(10000);

	const transition: AnimationOptions = { duration: 3, repeat: Infinity };

	return (() => {
		const passage = getDestinationPassages(props.line.id, props.destination)[props.index];

		const refTs = passage !== undefined ? (passage.expectedDepartTs !== null ? passage.expectedDepartTs : passage.expectedArrivalTs) : 0;
		const ttwSec = refTs - (getTime(dateNow()) / 1000);
		const isApproaching = ttwSec <= 60;

		return (
			<Show when={passage !== undefined} fallback=<UnavailablePassage style={props.fallbackStyle} />>
				<div class={props.style}>
					<svg viewBox={`0 0 215 ${props.fontSize}`}>
						<Motion.text
							x="100%" y="55%"
							dominant-baseline="middle" text-anchor="end"
							font-size={props.fontSize} style={{ fill: "#000000" }}
							initial={isApproaching ? undefined : false}
							animate={{ opacity: [1, 0, 1] }}
							transition={transition}>
							{Math.floor(ttwSec / 60)} min
						</Motion.text>
					</svg>
				</div>
			</Show>
		);
	});
}

/* TODO: Manage end of service */
const DestinationPassages: VoidComponent<{ line: Line, destination: string }> = (props) => {

	/* TODO: Find where to get data to compute traffic status. */
	const trafficStatusColor = new Map<TrafficStatus, string>([
		[TrafficStatus.UNKNOWN, "#ffffff"],
		[TrafficStatus.FLUID, "#00643c"],
		[TrafficStatus.DISRUPTED, "#ffbe00"],
		[TrafficStatus.VERY_DISRUPTED, "#ff5a00"],
		[TrafficStatus.BYPASSED, "#ffffff"]
	]);

	// TODO: Manage traffic status
	// const trafficStatusStyle = { fill: trafficStatusColor.get(props.line.trafficStatus) };
	const trafficStatusStyle = { fill: trafficStatusColor.get(TrafficStatus.UNKNOWN) };

	let destinationViewboxRef: SVGSVGElement | undefined = undefined;
	let destinationTextRef: SVGTextElement | undefined = undefined;

	onMount(() => {
		if (destinationViewboxRef !== undefined && destinationTextRef !== undefined) {
			const overlap = destinationTextRef.getComputedTextLength() - destinationViewboxRef.viewBox.baseVal.width;
			if (overlap > 0) {
				timeline(
					[
						[destinationTextRef, { x: [-overlap] }, { duration: 5 }],
						[destinationTextRef, { x: [0] }, { duration: 2 }],
					],
					{ repeat: Infinity },
				);
			}
		}
	});

	return (
		<div class={styles.line}>
			<div class={styles.transportMode}>
				{renderLineTransportMode(props.line)}
			</div>
			{renderLinePicto(props.line, styles)}
			<div class={styles.destination}>
				<svg ref={destinationViewboxRef} viewBox="0 0 600 40">
					<text ref={destinationTextRef} x="0" y="50%"
						dominant-baseline="middle"
						font-size="40"
						style={{ fill: "#000000" }}>
						{props.destination}
					</text>
				</svg>
			</div>
			<div class={styles.trafficStatus}>
				<svg viewBox="0 0 51 51">
					<circle cx="50%" cy="50%" r="24" stroke="#231f20" stroke-width="3" style={trafficStatusStyle} />
				</svg>
			</div>
			<TtwPassage line={props.line} destination={props.destination} index={0} style={styles.firstPassage}
				fontSize={50} fallbackStyle={styles.unavailableFirstPassage} />
			<TtwPassage line={props.line} destination={props.destination} index={1} style={styles.secondPassage}
				fontSize={45} fallbackStyle={styles.unavailableSecondPassage} />
		</div >
	);
}

export type PassagesPanelComponentProps = ParentProps & { stopId: number, lineIds: string[], show: boolean };
export type PassagesPanelComponent = ParentComponent<PassagesPanelComponentProps>;
export const PassagesPanel: PassagesPanelComponent = (props) => {

	const businessDataContext: BusinessDataStore | undefined = useContext(BusinessDataContext);
	if (businessDataContext === undefined)
		return <div />;

	const { getLine, getLineDestinations } = businessDataContext;

	const getLines = async (lineIds: string[]): Promise<Line[]> => {
		const lines = await Promise.all<Promise<Line>[]>(lineIds.map((lineId) => getLine(lineId)));
		return lines;
	}
	const [lines] = createResource<Line[], string[]>(props.lineIds, getLines);

	return (
		<div classList={{ [styles.passagesContainer]: true, [styles.displayed]: props.show }} >
			<Show when={lines() !== undefined} >
				<For each={lines()}>
					{(line) =>
						<Show when={getLineDestinations(line.id) !== undefined}>
							<For each={getLineDestinations(line.id)}>
								{(destination) =>
									<DestinationPassages line={line} destination={destination} />
								}
							</For>
						</Show>
					}
				</For>
			</Show>
		</div >
	);
}
