import {JSX} from "preact";
import {useState, useEffect, useCallback} from "preact/hooks";
import "./styles.scss";
import style from "./style.module.scss";
import {Container} from "./components/container";
import {loadTopics, saveTopics} from "./utils/topics";
import {Topic} from "./utils/topics";
import {Topics} from "./components/topics";
import {Topic as TopicComponent} from "./components/topic";
import {Route, routes, RouteSetter} from "./utils/route";
import {Settings} from "./components/settings";
import {Layout} from "./components/layout";
import {fetchSettings, resetSettings, saveSettings} from "./utils/settings";
import {generateTopic, generatePosts} from "./utils/oobabooga";
import {tokenizeTopic} from "./utils/model";

export function App(): JSX.Element {
    const [route, _setRoute] = useState<Route>(routes.home);
    const [page, setPage] = useState<number>(0);
    const [topicId, setTopicId] = useState<Topic["id"] | null>(null);

    // null when loading
    const [topics, setTopics] = useState<Topic[]>(loadTopics);
    const [latestGeneratedTopicId, setLatestGeneratedTopicId] = useState<string|null>(null);
    const [pendingGeneration, setPendingGeneration] = useState<boolean>(false);

    useEffect(() => {
        console.log("save !")
        saveTopics(topics);
    }, [topics]);

    const _generateTopic = async (postsCount: number) => {
        setPendingGeneration(true);
        const topic = await generateTopic(settings, postsCount);
        setLatestGeneratedTopicId(topic.id);
        setTopics(topics => [...topics, topic]);
        setPendingGeneration(false);
    }

    const addPosts = async (topicId: string, postsCount: number) => {
        setPendingGeneration(true);
        const posts = await generatePosts(settings, postsCount, topics.find(t => t.id === topicId));
        const newTopics = [...topics]; // Clone topics to avoid bugs
        const foundIndex = newTopics.findIndex(t => t.id === topicId);
        newTopics[foundIndex].posts = newTopics[foundIndex].posts.concat(posts);
        setTopics(newTopics)
        setPendingGeneration(false);
    }

    // useEffect(() => {
    //     setTopics(loadTopics());
    // }, []);

    const [settings, setSettings] = useState(fetchSettings)

    useEffect(() => {
        saveSettings(settings);
    }, [settings]);

    const resetApp = () => {
        resetSettings();
        setSettings(fetchSettings);
        setTopics([]);
    }

    const updateRoute = useCallback(() => {
        const url = new URL(window.location.href);
        const route = url.searchParams.get("route");
        if (route && route in routes) {
            _setRoute(route as keyof typeof routes);
        }
        const page = url.searchParams.get("page");
        if (page) {
            setPage(parseInt(page));
        }
        const id = url.searchParams.get("id");
        if (id) {
            setTopicId(id);
        }
    }, []);

    // Init page from url
    useEffect(() => {
        updateRoute()
    }, []);

    // Listen for URl change
    useEffect(() => {
        function listener() {
            updateRoute()
        }

        window.addEventListener('popstate', listener);

        return () => {
            window.removeEventListener('popstate', listener)
        }
    }, []);


    // Update URL params on route change
    const setRoute: RouteSetter = useCallback((route: Route, page?: number, id?: string) => {
        const url = new URL(window.location.href);
        url.searchParams.set("route", route);
        _setRoute(route);

        if (page !== undefined) {
            url.searchParams.set("page", String(page));
            setPage(page);
        }   else {
            url.searchParams.delete("page");
            setPage(0);
        }

        if (id !== undefined) {
            url.searchParams.set("id", id);
            setTopicId(id);
        } else {
            url.searchParams.delete("id");
            setTopicId(null);
        }

        const newUrl = url.toString();

        // Avoid to push the same URL mutiple time
        if (newUrl !== window.location.href) {
            window.history.pushState({}, "", newUrl);
        }
    }, []);

    let routeComponent: JSX.Element = undefined;
    let breadcrumbs: string = undefined;
    let title: string = undefined;

    switch (route) {
        case routes.home:
            routeComponent = <Topics
                topics={topics}
                setRoute={setRoute}
                settings={settings}
                setSettings={setSettings}
                generateTopic={_generateTopic}
                pendingGeneration={pendingGeneration}
                latestGeneratedTopicId={latestGeneratedTopicId}
            />
            breadcrumbs = "accueil"
            title = "Liste des sujets"
            break;
        case routes.topic:
            if (topicId === null) {
                routeComponent = <div>Impossible d'afficher le sujet</div>
                breadcrumbs = "accueil"
                title = "Sujet"
            } else {
                if (topics === null) {
                    routeComponent = <div>Chargement...</div>
                    breadcrumbs = `accueil / sujet`
                    title = `Chargement...`
                } else {
                    const topic = topics.find(t => t.id === topicId);
                    routeComponent = <TopicComponent
                        topic={topic}
                        settings={settings}
                        setSettings={setSettings}
                        addPosts={addPosts}
                        pendingGeneration={pendingGeneration}
                    />
                    breadcrumbs = `accueil / ${topic.title}`
                    title = `Sujet : ${topic.title}`
                }
            }

            break;
        case routes.settings:
            routeComponent = <Settings settings={settings} setSettings={setSettings} resetApp={resetApp}/>
            breadcrumbs = "accueil / paramètres"
            title = "Paramètres"
            break;
    }

    return (
        <>
            <header className={style.header}>
                <Container>
                    <h1 className={style.logo}>
                        <a href="#" onClick={e => {
                            e.preventDefault();
                            setRoute(routes.home);
                        }}>
                            JVCGPT
                        </a>
                    </h1>
                </Container>
            </header>
            <main>
                <Container>
                    <Layout
                        breadcrumbs={breadcrumbs}
                        title={title}
                        setRoute={setRoute}
                    >
                        {routeComponent}
                    </Layout>
                </Container>
            </main>
        </>
    );
}