import { createContext, createEffect, createResource, createSignal, For, JSX, ParentComponent, Show, useContext, VoidComponent } from "solid-js";
import { createStore } from "solid-js/store";
import { createDateNow } from "@solid-primitives/date";
import { IconButton, Menu, MenuTrigger, MenuContent, MenuItem } from "@hope-ui/solid";
import { format } from "date-fns";

import { BusinessDataContext, BusinessDataStore } from "./businessData";
import { AppContextContext, AppContextStore } from "./appContext";

import { getTransportModeSrc, PositionedPanel } from "./utils";
import { PassagesPanel } from "./passagesPanel";
import { IconHamburgerMenu } from './extra/iconHamburgerMenu';

import "./passagesDisplay.scss";


interface PassagesDisplayStore {
	isPassagesRefreshEnabled: () => boolean;
	enablePassagesRefresh: () => void;
	disablePassagesRefresh: () => void;
	togglePassagesRefresh: () => void;

	getPanels: () => PositionedPanel[];
	setPanels: (panels: PositionedPanel[]) => void;

	getDisplayedPanelId: () => number;
	setDisplayedPanelId: (panelId: number) => void;
};

const PassagesDisplayContext = createContext<PassagesDisplayStore>();

function PassagesDisplayProvider(props: { children: JSX.Element }) {

	type Store = {
		refreshEnabled: boolean;
		panels: PositionedPanel[];
		displayedPanelId: number;
	};

	const [store, setStore] = createStore<Store>({ refreshEnabled: true, panels: [], displayedPanelId: 0 });

	const isPassagesRefreshEnabled = (): boolean => {
		return store.refreshEnabled;
	}

	const enablePassagesRefresh = (): void => {
		setStore('refreshEnabled', true);
	}

	const disablePassagesRefresh = (): void => {
		setStore('refreshEnabled', false);
	}

	const togglePassagesRefresh = (): void => {
		setStore('refreshEnabled', !store.refreshEnabled);
	}

	const getPanels = (): PositionedPanel[] => {
		return store.panels;
	}
	const setPanels = (panels: PositionedPanel[]): void => {
		setStore('panels', panels);
	}

	const getDisplayedPanelId = (): number => {
		return store.displayedPanelId;
	}
	const setDisplayedPanelId = (panelId: number): void => {
		setStore('displayedPanelId', panelId);
	}

	return (
		<PassagesDisplayContext.Provider value={{
			isPassagesRefreshEnabled, enablePassagesRefresh,
			disablePassagesRefresh, togglePassagesRefresh,
			getPanels, setPanels,
			getDisplayedPanelId, setDisplayedPanelId
		}}>
			{props.children}
		</PassagesDisplayContext.Provider>
	);
}

// TODO: Sort transport modes by weight
const Header: VoidComponent<{ title: string }> = (props) => {

	const businessDataStore: BusinessDataStore | undefined = useContext(BusinessDataContext);
	const passagesDisplayStore: PassagesDisplayStore | undefined = useContext(PassagesDisplayContext);

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

	const { getLine, passages } = businessDataStore;
	const { isPassagesRefreshEnabled, togglePassagesRefresh } = passagesDisplayStore;

	const [dateNow] = createDateNow(1000);

	const computeTransportModes = async (lineIds: string[]): Promise<string[]> => {
		const lines = await Promise.all(lineIds.map((lineId) => getLine(lineId)));
		const urls: Set<string> = new Set();
		for (const line of lines) {
			const src = getTransportModeSrc(line.transportMode, false);
			if (src !== undefined) {
				urls.add(src);
			}
		}
		return Array.from(urls);
	}
	const [linesIds, setLinesIds] = createSignal<string[]>([]);
	const [transportModeUrls] = createResource<string[], string[]>(linesIds, computeTransportModes);

	createEffect(() => {
		setLinesIds(Object.keys(passages()));
	});

	return (
		<div class="header">
			<Show when={transportModeUrls() !== undefined} >
				<For each={transportModeUrls()}>
					{(url) =>
						<div class="transportMode">
							<img src={url} />
						</div>
					}
				</For>
			</Show>
			<div class="title">
				<svg viewBox="0 0 1260 50">
					<text x="0" y="50%" dominant-baseline="middle" font-size="50" style="fill: #ffffff">
						{props.title}
					</text>
				</svg>
			</div>
			<div class="menu">
				<Menu>
					<MenuTrigger
						as={IconButton}
						icon=<IconHamburgerMenu />
					/>
					<MenuContent>
						<MenuItem onSelect={() => togglePassagesRefresh()}>{isPassagesRefreshEnabled() ? "Disable" : "Enable"}</MenuItem>
					</MenuContent>
				</Menu>
			</div>
			<div class="clock">
				<svg viewBox="0 0 115 43">
					<text x="50%" y="55%" dominant-baseline="middle" text-anchor="middle" font-size="43" style="fill: #ffffff">
						{format(dateNow(), "HH:mm")}
					</text>
				</svg>
			</div>
		</div >
	);
};

const Footer: VoidComponent<{}> = () => {

	const passagesDisplayStore: PassagesDisplayStore | undefined = useContext(PassagesDisplayContext);

	if (passagesDisplayStore === undefined)
		return <div />;

	const { getDisplayedPanelId, getPanels } = passagesDisplayStore;

	return (
		<div class="footer">
			<For each={getPanels()}>
				{(panel) => {
					const position = panel.position;
					return (
						<div>
							<svg viewBox="0 0 29 29">
								<circle cx="50%" cy="50%" r="13" stroke="#ffffff" stroke-width="3"
									style={{ fill: `var(--idfm-${position == getDisplayedPanelId() ? "white" : "black"})` }}
								/>
							</svg>
						</div>
					);
				}}
			</For>
		</div>
	);
}

const Body: ParentComponent<{ maxPassagesPerPanel: number, syncPeriodMsec: number, panelSwitchPeriodMsec: number }> = (props) => {

	const businessDataStore: BusinessDataStore | undefined = useContext(BusinessDataContext);
	const appContextStore: AppContextStore | undefined = useContext(AppContextContext);
	const passagesDisplayStore: PassagesDisplayStore | undefined = useContext(PassagesDisplayContext);

	if (businessDataStore === undefined || appContextStore === undefined || passagesDisplayStore === undefined) {
		return <div />;
	}

	const { getLineDestinations, passages, getPassagesLineIds, clearPassages, refreshPassages } = businessDataStore;
	const { isPassagesRefreshEnabled, getDisplayedPanelId, setDisplayedPanelId, getPanels, setPanels } = passagesDisplayStore;
	const { getDisplayedStops } = appContextStore;

	setInterval(() => {
		let nextPanelId = getDisplayedPanelId() + 1;
		if (nextPanelId >= getPanels().length) {
			nextPanelId = 0;
		}
		setDisplayedPanelId(nextPanelId);
	}, props.panelSwitchPeriodMsec);

	setInterval(
		async () => {
			if (isPassagesRefreshEnabled()) {
				const stops = getDisplayedStops();
				if (stops.length > 0) {
					refreshPassages(stops[0].id);
				}
			}
			else {
				console.log("Passages refresh disabled... skip it.");
			}
		},
		props.syncPeriodMsec
	);

	createEffect(() => {
		console.log("######### onStopIdUpdate #########");
		// Track local.stopIp to force dependency.
		console.log("getDisplayedStop=", getDisplayedStops());
		clearPassages();
	});

	createEffect(async () => {
		console.log(`## OnPassageUpdate ${passages()} ##`);
		const stops = getDisplayedStops();
		if (stops.length > 0) {
			refreshPassages(stops[0].id);
		}
	});

	return (
		<div class="body">
			{() => {
				setPanels([]);

				let newPanels = [];
				let positioneds: PositionedPanel[] = [];
				let index = 0;

				let lineIds: string[] = [];
				let destinationsNb = 0;

				for (const lineId of getPassagesLineIds()) {
					const lineDestinations = getLineDestinations(lineId);

					if (lineDestinations.length <= props.maxPassagesPerPanel - destinationsNb) {
						lineIds.push(lineId);
						destinationsNb += lineDestinations.length;
					}
					else {
						const panelid = index++;
						const panel = <PassagesPanel stopId={getDisplayedStops()[0].id} lineIds={lineIds} show={panelid == getDisplayedPanelId()} />;
						newPanels.push(panel);
						positioneds.push({ position: panelid, panel: panel });

						lineIds = [lineId];
						destinationsNb = lineDestinations.length;
					}
				}
				if (destinationsNb) {
					const panelId = index++;
					const panel = <PassagesPanel stopId={getDisplayedStops()[0].id} lineIds={lineIds} show={panelId == getDisplayedPanelId()} />;
					newPanels.push(panel);
					positioneds.push({ position: panelId, panel: panel });
				}

				setPanels(positioneds);

				return newPanels;
			}}
		</div>
	);
}

export const PassagesDisplay: ParentComponent = () => {

	const MAX_PASSAGES_PER_PANEL = 5;

	// TODO: Use props.
	const syncPeriodMsec = 20 * 1000;
	const panelSwitchPeriodMsec = 4 * 1000;

	return (
		<div class="passagesDisplay">
			<PassagesDisplayProvider>
				<Header title="Prochains passages" />
				<Body maxPassagesPerPanel={MAX_PASSAGES_PER_PANEL} syncPeriodMsec={syncPeriodMsec} panelSwitchPeriodMsec={panelSwitchPeriodMsec} />
				<Footer />
			</PassagesDisplayProvider>
		</div>
	);
};
