import { createResource, For, JSX, ParentComponent, Show, useContext, VoidComponent } from 'solid-js';

import { Stop } from '../types';
import { renderLineTransportMode, renderLinePicto, ScrollingText, TransportModeWeights } from '../utils';
import { AppContextContext, AppContextStore } from "../appContext";
import { BusinessDataContext, BusinessDataStore } from "../businessData";
import { SearchContext, SearchStore } from "./searchStore";


import "./stopPanel.scss";


const StopRepr: VoidComponent<{ stop: Stop }> = (props) => {
	const fontSize: number = 40;

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

	const { getLine } = businessDataStore;

	const fetchLinesRepr = async (lineIds: string[]): Promise<JSX.Element[]> => {
		const reprs = [];
		for (const lineId of lineIds) {
			const line = await getLine(lineId);
			if (line !== undefined) {
				reprs.push(<div class="transportMode">{renderLineTransportMode(line)}</div>);
				reprs.push(renderLinePicto(line));
			}
		}
		return reprs;
	}

	const [lineReprs] = createResource<JSX.Element[], string[]>(props.stop.lines, fetchLinesRepr);

	return (
		<div class="stop">
			<svg class="name" viewBox={`0 0 215 ${fontSize}`}>
				<text
					x="100%" y="55%"
					dominant-baseline="middle" text-anchor="end"
					font-size={fontSize}>
					{props.stop.name}
				</text>
			</svg>
			<For each={lineReprs()}>{(line: JSX.Element) => line}</For>
		</div>
	);
}


type ByTransportModeReprs = {
	mode: JSX.Element | undefined;
	lines: Record<string, JSX.Element | JSX.Element[] | undefined>;
}


const StopAreaRepr: VoidComponent<{ stop: Stop }> = (props) => {
	const fontSize: number = 10;

	const businessDataStore: BusinessDataStore | undefined = useContext(BusinessDataContext);
	const appContextStore: AppContextStore | undefined = useContext(AppContextContext);
	const searchStore: SearchStore | undefined = useContext(SearchContext);

	if (businessDataStore === undefined || appContextStore === undefined || searchStore === undefined)
		return <div />;

	const { getLine } = businessDataStore;
	const { setDisplayedStops } = appContextStore;
	const { setHighlightedStop, resetHighlightedStop } = searchStore;


	const fetchLinesRepr = async (stop: Stop): Promise<JSX.Element> => {
		const lineIds = new Set(stop.lines);
		const stops = stop.stops;
		for (const stop of stops) {
			stop.lines.forEach(lineIds.add, lineIds);
		}

		const byModeReprs: Record<string, ByTransportModeReprs> = {};
		for (const lineId of lineIds) {
			const line = await getLine(lineId);
			if (line !== undefined) {
				if (!(line.transportMode in byModeReprs)) {
					byModeReprs[line.transportMode] = {
						mode: <div class="transportMode">{renderLineTransportMode(line)}</div>,
						lines: {}
					};
				}
				byModeReprs[line.transportMode].lines[line.shortName] = renderLinePicto(line);
			}
		}

		const sortedTransportModes = Object.keys(byModeReprs).sort((x, y) => TransportModeWeights[x] <
			TransportModeWeights[y] ? 1 : -1);

		return (
			<div class="lineRepr">
				<For each={sortedTransportModes}>{(transportMode) => {
					const reprs = byModeReprs[transportMode];
					const lineNames = Object.keys(reprs.lines).sort((x, y) => x.localeCompare(y));
					return <>
						{reprs.mode}
						<div class="linesRepresentationMatrix">
							<For each={lineNames}>{(lineName) => reprs.lines[lineName]}</For>
						</div>
					</>
				}}
				</For>
			</div >
		);
	}
	const [lineReprs] = createResource(props.stop, fetchLinesRepr);

	return (
		<div
			class="stop"
			onClick={() => setDisplayedStops([props.stop])}
			onMouseEnter={() => setHighlightedStop(props.stop)}
			onMouseLeave={resetHighlightedStop}
		>
			<div class="name" >
				<ScrollingText height={fontSize} width={100} content={props.stop.name} />
			</div>
			{lineReprs()}
		</div>
	);
}

export const StopsPanel: ParentComponent<{ stops: Stop[], show: boolean }> = (props) => {

	return (
		<div classList={{ "stopPanel": true, "displayed": props.show }}>
			<For each={props.stops.sort((x, y) => x.name.localeCompare(y.name))}>
				{(stop) => {
					return <Show when={stop.stops !== undefined} fallback={<StopRepr stop={stop} />}>
						<StopAreaRepr stop={stop} />
					</Show>;
				}}
			</For>
		</div>
	);
}
