import { createEffect, For, JSX, lazy, ParentComponent, useContext, Show, VoidComponent } from 'solid-js';
import { lazily } from 'solidjs-lazily';
import { createScrollPosition } from "@solid-primitives/scroll";

import { Stop } from '../types';
import { PositionedPanel } from '../utils';

import { BusinessDataContext, BusinessDataStore } from "../businessData";
import { SearchContext, SearchProvider, SearchStore } from "./searchStore";
import { StopsPanel } from "./stopPanel";

const { Map } = lazily(() => import("./map"));


import "./stopsSearchMenu.scss";


const StopNameInput: VoidComponent<{ onInput: JSX.EventHandler<HTMLInputElement, InputEvent>, leftAddon: string, placeholder: string }> = (props) => {
	return (
		<div class="stopNameInput">
			<div class="leftAddon">{props.leftAddon}</div>
			<input type="text" oninput={props.onInput} placeholder={props.placeholder} />
		</div>);
};


const Header: VoidComponent<{ title: string, minCharsNb: number }> = (props) => {
	const businessDataStore: BusinessDataStore | undefined = useContext(BusinessDataContext);
	const searchStore: SearchStore | undefined = useContext(SearchContext);

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

	const { setSearchText } = searchStore;

	const onStopNameInput: JSX.EventHandler<HTMLInputElement, InputEvent> = async (event): Promise<void> => {
		const stopName = event.currentTarget.value;
		if (stopName.length >= props.minCharsNb) {
			await setSearchText(stopName, businessDataStore);
		}
	}

	return (
		<div class="header">
			<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>
			<StopNameInput onInput={onStopNameInput} leftAddon="🚉 🚏" placeholder="Stop name..." />
		</div >
	);
};


const StopsPanels: ParentComponent<{ maxStopsPerPanel: number }> = (props) => {
	const searchStore: SearchStore | undefined = useContext(SearchContext);

	if (searchStore === undefined) {
		return <div />;
	}

	const { getDisplayedPanelId, getFoundStops, getPanels, setDisplayedPanelId, setPanels } = searchStore;
	let stopsPanelsRef: HTMLDivElement | undefined = undefined
	const stopsPanelsScroll = createScrollPosition(() => stopsPanelsRef);
	const yStopsPanelsScroll = () => stopsPanelsScroll.y;

	createEffect(() => {
		yStopsPanelsScroll();

		for (const panel of getPanels()) {
			const panelDiv = panel.panel();
			const panelDivClientRect = panelDiv.getBoundingClientRect();
			if (panelDivClientRect.y > 0) {
				setDisplayedPanelId(panel.position);
				break;
			}
		}
	});

	return (
		<div ref={stopsPanelsRef} class="stopsPanels">
			{() => {
				setPanels([]);

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

				let stops: Stop[] = [];

				for (const stop of getFoundStops()) {
					if (stops.length < props.maxStopsPerPanel) {
						stops.push(stop);
					}
					else {
						const panelId = newPanels.length;
						const panel = <StopsPanel stops={stops} show={panelId == getDisplayedPanelId()} />;
						newPanels.push(panel);
						positioneds.push({ position: panelId, panel: panel });
						stops = [stop];
					}
				}
				if (stops.length) {
					const panelId = newPanels.length;
					const panel = <StopsPanel stops={stops} show={panelId == getDisplayedPanelId()} />;
					newPanels.push(panel);
					positioneds.push({ position: panelId, panel: panel });
				}

				setPanels(positioneds);

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


const MapPlaceholder: VoidComponent<{}> = () => {
	const searchStore: SearchStore | undefined = useContext(SearchContext);

	if (searchStore === undefined) {
		return <div />;
	}

	const { enableMap } = searchStore;

	const onDoubleClick = (): void => {
		console.log('!!! ON DOUBLE CLICK');
		enableMap(true);
	}

	return <div
		class="mapPlaceholder" ondblclick={() => onDoubleClick()}>
		Double-clic pour activer la carte
	</div>;
};


const Body: VoidComponent<{}> = () => {
	const searchStore: SearchStore | undefined = useContext(SearchContext);
	if (searchStore === undefined) {
		return <div />;
	}

	const { isMapEnabled } = searchStore;

	const maxStopsPerPanel = 5;

	return <div class="body">
		<StopsPanels maxStopsPerPanel={maxStopsPerPanel} />
		<Show when={isMapEnabled()} fallback={<MapPlaceholder />}>
			<Map />
		</Show>
	</div>;
};


const Footer: VoidComponent<{}> = () => {
	const searchStore: SearchStore | undefined = useContext(SearchContext);
	if (searchStore === undefined) {
		return <div />;
	}

	const { getDisplayedPanelId, getPanels } = searchStore;

	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>
	);
};


export const StopsSearchMenu: VoidComponent = () => {
	return (
		<div class="stopSearchMenu">
			<SearchProvider>
				<Header title="Recherche de l'arrêt..." minCharsNb={4} />
				<Body />
				<Footer />
			</SearchProvider>
		</div>
	);
};
