import {onReady} from "./main.ts";
import {TesoftBlogArticle} from "../components/blog-article.ts";
import {TesoftBlogArticleList} from "../components/blog-article-list.ts";

class Parameters {
    readonly id: number | null;
    readonly page: number | null;
    readonly tags: string[];

    constructor(id: number | null, page: number | null, tags: string[]) {
        this.id = id;
        this.page = page;
        this.tags = tags;
    }

    constructUrl(): URL {
        const url = new URL(window.location.origin + window.location.pathname);

        if (this.id !== null) {
            url.searchParams.set("id", this.id.toString());
        }
        if (this.page !== null) {
            url.searchParams.set("page", this.page.toString());
        }
        if (this.tags.length > 0) {
            url.searchParams.set("tags", this.tags.join(","));
        }

        return url;
    }

    static parse(searchParams: URLSearchParams): Parameters {
        let id: number | null = null;
        if (searchParams.has("id")) {
            id = parseInt(searchParams.get("id")!);
        }

        let page: number | null = null;
        if (searchParams.has("page")) {
            page = parseInt(searchParams.get("page")!);
        }

        let tags: string[] = [];
        const tagsStr = searchParams.get("tags");
        if (tagsStr) {
            tags = tagsStr.split(",");
        }

        return new Parameters(id, page, tags);
    }
}

class BlogSite {
    private readonly blogArticle: TesoftBlogArticle;
    private readonly blogArticleList: TesoftBlogArticleList;
    private parameters: Parameters;

    constructor(blogArticle: TesoftBlogArticle, blogArticleList: TesoftBlogArticleList, parameters: Parameters) {
        this.blogArticle = blogArticle;
        this.blogArticleList = blogArticleList;
        this.parameters = parameters;
    }

    async load() {
        if (this.parameters.id === null) {
            this.blogArticleList.addEventListener("update-parameters", (e) => {
                const {page, tags} = (e as CustomEvent).detail;
                e.stopPropagation();

                window.history.pushState(
                    null,
                    "",
                    new Parameters(
                        null,
                        page ?? this.parameters.page,
                        tags ?? this.parameters.tags,
                    ).constructUrl(),
                );
                this.reload();
            });

            await this.blogArticleList.load(this.parameters.page ?? 1, this.parameters.tags);
            this.blogArticleList.classList.remove("hidden");
        } else {
            await this.blogArticle.load(this.parameters.id, (tag) => {
                return new Parameters(
                    null,
                    null,
                    Array.from(new Set(this.parameters.tags).add(tag)),
                ).constructUrl().toString();
            });
            this.blogArticle.classList.remove("hidden");
        }
    }

    async reload() {
        this.parameters = Parameters.parse(new URLSearchParams(window.location.search));

        await this.blogArticleList.reload(this.parameters.page ?? 1, this.parameters.tags);
    }
}

onReady(async () => {
    const parameters = Parameters.parse(new URLSearchParams(window.location.search));

    const blogSite = new BlogSite(
        document.querySelector<TesoftBlogArticle>("tesoft-blog-article")!,
        document.querySelector<TesoftBlogArticleList>("tesoft-blog-article-list")!,
        parameters,
    );

    if (parameters.id === null) {
        window.addEventListener("popstate", async () => {
            await blogSite.reload();
        });
    }

    await blogSite.load();
});
