import Structure from "../Structure";
import StructureFactory, {StructureImplConfig} from "../StructureFactory";
import {setElementVisibility} from "../../../Utility/ElementVisibility";

export default class Collapsible extends Structure{
    public startCollapsed: boolean = false;
    public header: string|null = null;
    public description: string|null = null;

    constructor(params: Partial<Collapsible> = {}) {
        super(params);
        Object.assign(this, params);
    }

    public placeHtml(container: HTMLElement): void {
        const structureDiv = document.createElement("div");
        this.addStandardContainerProperties(structureDiv);
        structureDiv.classList.add("pad-collapsible-group");

        const headerDiv = document.createElement("div");
        const headerArrow = document.createElement("span");
        headerArrow.classList.add("pad-expand-arrow");
        headerDiv.append(headerArrow);

        if (this.header) {
            const headerSpan = document.createElement("span");
            headerSpan.classList.add("pad-header");
            headerSpan.innerText = this.header;
            headerDiv.append(headerSpan);
        }

        if (this.description) {
            const descriptionParagraph = document.createElement("p");
            descriptionParagraph.classList.add("pad-description");
            descriptionParagraph.innerText = this.description;
            headerDiv.append(descriptionParagraph);
        }

        const contentDiv = document.createElement("div");
        let collapsed = this.startCollapsed;

        headerDiv.addEventListener("click", () => {
            collapsed = !collapsed;
            setElementVisibility(contentDiv, !collapsed);
            if (collapsed) headerDiv.classList.add("pad-collapsed");
            else headerDiv.classList.remove("pad-collapsed");
        })

        structureDiv.append(headerDiv);
        structureDiv.append(contentDiv);

        contentDiv.classList.add("pad-form-group");
        headerDiv.classList.add("pad-header-box");
        headerDiv.classList.toggle("pad-collapsed", collapsed);

        setElementVisibility(contentDiv, !collapsed);

        container.append(structureDiv);
        this.placedHtml.push(structureDiv);
        this.contents.forEach(c => c.placeHtml(contentDiv));
    }
}

export function addCollapsibleToFactory(factory: StructureFactory): void {
    factory.registerConstructor("collapsible", (config, params) => {
        const impl = config.impl;
        if (!isCollapsibleConfig(impl)) return null;

        const collapsibleParams: Partial<Collapsible> = params as Partial<Collapsible>;

        collapsibleParams.startCollapsed = impl.startCollapsed;
        collapsibleParams.header = impl.header;
        collapsibleParams.description = impl.description;

        return new Collapsible(collapsibleParams);
    });
}

function isCollapsibleConfig(config:StructureImplConfig): config is CollapsibleConfig{
    return config.type === "collapsible";
}

interface CollapsibleConfig extends StructureImplConfig{
    type: "collapsible";
    startCollapsed: boolean;
    header: string|null;
    description: string|null;
}