<script lang="ts">

    import EditLayerState from "./EditLayerState";
    import type { ConfigMeta } from "./configMeta";
    import { UIEventSource } from "../../Logic/UIEventSource";
    import type {
        QuestionableTagRenderingConfigJson
    } from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson";
    import TagRenderingEditable from "../Popup/TagRendering/TagRenderingEditable.svelte";
    import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig";
    import { onDestroy } from "svelte";
    import SchemaBasedInput from "./SchemaBasedInput.svelte";
    import type { JsonSchemaType } from "./jsonSchema";
    // @ts-ignore
    import nmd from "nano-markdown";

    /**
     * If 'types' is defined: allow the user to pick one of the types to input.
     */

    export let state: EditLayerState
    export let path: (string | number)[] = []
    export let schema: ConfigMeta
    const defaultOption = schema.hints.typesdefault ? Number(schema.hints.typesdefault) : undefined

    const hasBooleanOption = (<JsonSchemaType[]>schema.type)?.findIndex(t => t["type"] === "boolean")
    const types = schema.hints.types.split(";")
    if (hasBooleanOption >= 0) {
        console.log(path.join("."), ": types are", types, ", boolean index is", hasBooleanOption)
        types.splice(hasBooleanOption)
    }

    const configJson: QuestionableTagRenderingConfigJson = {
        id: "TYPE_OF:" + path.join("_"),
        question: "Which subcategory is needed?",
        questionHint: nmd(schema.description),
        mappings: types.map(opt => opt.trim()).filter(opt => opt.length > 0).map((opt, i) => ({
            if: "value=" + i,
            addExtraTags: ["direct="],
            then: opt + (i === defaultOption ? " (Default)" : "")
        }))
    }
    let tags = new UIEventSource<Record<string, string>>({})

    if (hasBooleanOption >= 0) {
        configJson.mappings.unshift(
          {
              if: "direct=true",
              then: "Yes " + (schema.hints.iftrue ?? ""),
              addExtraTags: ["value="]
          },
          {
              if: "direct=false",
              then: "No " + (schema.hints.iffalse ?? ""),
              addExtraTags: ["value="]
          }
        )
    }
    const config = new TagRenderingConfig(configJson, "config based on " + schema.path.join("."))


    const existingValue = state.getCurrentValueFor(path)
    console.log("Setting direct: ", hasBooleanOption, path.join("."), existingValue)
    if (hasBooleanOption >= 0 && (existingValue === true || existingValue === false)) {
        tags.setData({direct: "" + existingValue})
    } else if (existingValue) {
        // We found an existing value. Let's figure out what type it matches and select that one
        // We run over all possibilities and check what is required
        const possibleTypes = []
        outer: for (let i = 0; i < (<[]>schema.type).length; i++) {
            const type = schema.type[i];
            if (type.required) {
                for (const requiredAttribute of type.required) {
                    if (existingValue[requiredAttribute] === undefined) {
                        console.log(path.join("."), " does not have required field", requiredAttribute, " so it cannot be type ", type)
                        // The 'existingValue' does _not_ have this required attribute, so it cannot be of this type
                        continue outer
                    }
                }
                possibleTypes.push(i)
            } else {
                possibleTypes.push(i)
            }
        }

        if (possibleTypes.length > 0) {
            tags.setData({value: "" + possibleTypes[0]})
        }
    } else if (defaultOption !== undefined) {
        tags.setData({value: "" + defaultOption})
    }

    if (hasBooleanOption >= 0) {

        const directValue = tags.mapD(tags => {
            if(tags["value"]){
                return undefined
            }
            return tags["direct"] === "true";
        })
        onDestroy(state.register(path, directValue, true))
    }
    
    let chosenOption: number = defaultOption
    let subSchemas: ConfigMeta[] = []
    onDestroy(tags.addCallbackAndRun(tags => {
        const oldOption = chosenOption
        chosenOption = tags["value"] ? Number(tags["value"]) : defaultOption
        if(chosenOption !== oldOption){
            // Reset the values beneath
            subSchemas = []
            state.setValueAt(path, undefined)
        }
        const type = schema.type[chosenOption]
        if (!type) {
            return
        }
        if (!type.properties) {
            return
        }
        const cleanPath = <string[]>path.filter(p => typeof p === "string")
        for (const crumble of Object.keys(type.properties)) {
            subSchemas.push(...(state.getSchema([...cleanPath, crumble])))
        }
    }))

    

</script>

<div class="p-2 border-2 border-dashed border-gray-300 flex flex-col gap-y-2">
    <div>
        <TagRenderingEditable selectedElement={undefined} {config} showQuestionIfUnknown={true} {state} {tags}/>
    </div>

    {#if chosenOption !== undefined}
        {#each subSchemas as subschema}
            <SchemaBasedInput {state} schema={subschema}
                              path={[...path, (subschema?.path?.at(-1) ?? "???")]}></SchemaBasedInput>
        {/each}
    {/if}
</div>