<script>
    import { createEventDispatcher, onMount } from "svelte";
    import { scale } from "svelte/transition";
    import { SchemaField } from "pocketbase";
    import CommonHelper from "@/utils/CommonHelper";
    import tooltip from "@/actions/tooltip";
    import { errors } from "@/stores/errors";
    import Accordion from "@/components/base/Accordion.svelte";
    import Field from "@/components/base/Field.svelte";
    import FieldTypeSelect from "@/components/collections/schema/FieldTypeSelect.svelte";
    import TextOptions from "@/components/collections/schema/TextOptions.svelte";
    import NumberOptions from "@/components/collections/schema/NumberOptions.svelte";
    import BoolOptions from "@/components/collections/schema/BoolOptions.svelte";
    import EmailOptions from "@/components/collections/schema/EmailOptions.svelte";
    import UrlOptions from "@/components/collections/schema/UrlOptions.svelte";
    import DateOptions from "@/components/collections/schema/DateOptions.svelte";
    import SelectOptions from "@/components/collections/schema/SelectOptions.svelte";
    import JsonOptions from "@/components/collections/schema/JsonOptions.svelte";
    import FileOptions from "@/components/collections/schema/FileOptions.svelte";
    import RelationOptions from "@/components/collections/schema/RelationOptions.svelte";
    import UserOptions from "@/components/collections/schema/UserOptions.svelte";

    const dispatch = createEventDispatcher();

    export let key = "0";
    export let field = new SchemaField();
    export let disabled = false;
    export let excludeNames = [];

    let accordion;
    let initialType = field.type;

    $: if (initialType != field.type) {
        initialType = field.type;
        // reset common options
        field.options = {};
        field.unique = false;
    }

    $: if (excludeNames.length) {
        const normalizedName = normalizeFieldName(field.name);
        if (field.name !== normalizedName) {
            field.name = normalizedName;
        }
    }

    $: canBeStored = !CommonHelper.isEmpty(field.name) && field.type;

    $: if (!canBeStored) {
        accordion && expand();
    }

    $: if (field.toDelete) {
        accordion && collapse();

        // reset the name if it was previously deleted
        if (!field.name && field.originalName) {
            field.name = field.originalName;
        }
    }

    $: if (!field.originalName && field.name) {
        field.originalName = field.name;
    }

    $: if (typeof field.toDelete === "undefined") {
        field.toDelete = false; // normalize
    }

    $: if (field.required) {
        field.nullable = false;
    }

    $: interactive = !disabled && !field.system && !field.toDelete && canBeStored;

    $: hasErrors = !CommonHelper.isEmpty(CommonHelper.getNestedVal($errors, `schema.${key}`));

    export function expand() {
        accordion?.expand();
    }

    export function collapse() {
        accordion?.collapse();
    }

    function handleDelete() {
        if (!field.id) {
            collapse();
            dispatch("remove");
        } else {
            field.toDelete = true;
        }
    }

    function normalizeFieldName(name) {
        name = CommonHelper.slugify(name);

        let counter = "";
        while (excludeNames.includes(name + counter)) {
            ++counter;
        }

        return name + counter;
    }

    onMount(() => {
        // auto expand new fields
        if (!field.id) {
            expand();
        }
    });
</script>

<Accordion
    bind:this={accordion}
    on:expand
    on:collapse
    on:toggle
    single
    {interactive}
    class={disabled || field.toDelete || field.system ? "field-accordion disabled" : "field-accordion"}
>
    <svelte:fragment slot="header" let:active={expanded}>
        <div class="inline-flex">
            <span class="icon field-type">
                <i class={CommonHelper.getFieldTypeIcon(field.type)} />
            </span>
            <strong class="title field-name" class:txt-strikethrough={field.toDelete} title={field.name}>
                {field.name || "-"}
            </strong>
        </div>

        {#if !field.toDelete}
            <div class="inline-flex">
                {#if field.system}
                    <span class="label label-danger">System</span>
                {/if}
                {#if !field.id}
                    <span class="label" class:label-warning={interactive && !field.toDelete}>New</span>
                {/if}
                {#if field.required}
                    <span class="label label-success">Required</span>
                {/if}
                {#if field.unique}
                    <span class="label label-success">Unique</span>
                {/if}
            </div>
        {/if}

        <div class="flex-fill" />

        {#if hasErrors}
            <i
                class="ri-error-warning-fill txt-danger"
                transition:scale={{ duration: 150, start: 0.7 }}
                use:tooltip={{ text: "Has errors", position: "left" }}
            />
        {/if}

        {#if field.toDelete}
            <button
                type="button"
                class="btn btn-sm btn-danger btn-secondary"
                on:click|stopPropagation={() => {
                    field.toDelete = false;
                }}
            >
                <span class="txt">Restore</span>
            </button>
        {/if}
    </svelte:fragment>

    <form
        class="field-form"
        on:submit|preventDefault={() => {
            canBeStored && collapse();
        }}
    >
        <div class="grid">
            <div class="col-sm-6">
                <Field
                    class="form-field required {field.id ? 'disabled' : ''}"
                    name="schema.{key}.type"
                    let:uniqueId
                >
                    <label for={uniqueId}>Type</label>
                    <FieldTypeSelect id={uniqueId} disabled={field.id} bind:value={field.type} />
                </Field>
            </div>
            <div class="col-sm-6">
                <Field
                    class="form-field required {field.id && field.system ? 'disabled' : ''}"
                    name="schema.{key}.name"
                    let:uniqueId
                >
                    <label for={uniqueId}>Name</label>
                    <!-- svelte-ignore a11y-autofocus -->
                    <input
                        type="text"
                        id={uniqueId}
                        required
                        disabled={field.id && field.system}
                        spellcheck="false"
                        autofocus={!field.id}
                        value={field.name}
                        on:input={(e) => {
                            field.name = normalizeFieldName(e.target.value);
                            e.target.value = field.name;
                        }}
                    />
                </Field>
            </div>

            <div class="col-sm-12 hidden-empty">
                {#if field.type === "text"}
                    <TextOptions {key} bind:options={field.options} />
                {:else if field.type === "number"}
                    <NumberOptions {key} bind:options={field.options} />
                {:else if field.type === "bool"}
                    <BoolOptions {key} bind:options={field.options} />
                {:else if field.type === "email"}
                    <EmailOptions {key} bind:options={field.options} />
                {:else if field.type === "url"}
                    <UrlOptions {key} bind:options={field.options} />
                {:else if field.type === "date"}
                    <DateOptions {key} bind:options={field.options} />
                {:else if field.type === "select"}
                    <SelectOptions {key} bind:options={field.options} />
                {:else if field.type === "json"}
                    <JsonOptions {key} bind:options={field.options} />
                {:else if field.type === "file"}
                    <FileOptions {key} bind:options={field.options} />
                {:else if field.type === "relation"}
                    <RelationOptions {key} bind:options={field.options} />
                {:else if field.type === "user"}
                    <UserOptions {key} bind:options={field.options} />
                {/if}
            </div>

            <div class="col-sm-4 flex">
                <Field class="form-field form-field-toggle m-0" name="requried" let:uniqueId>
                    <input type="checkbox" id={uniqueId} bind:checked={field.required} />
                    <label for={uniqueId}>Required</label>
                </Field>
            </div>

            <div class="col-sm-4 flex">
                {#if field.type !== "file"}
                    <Field class="form-field form-field-toggle m-0" name="unique" let:uniqueId>
                        <input type="checkbox" id={uniqueId} bind:checked={field.unique} />
                        <label for={uniqueId}>Unique</label>
                    </Field>
                {/if}
            </div>

            {#if !field.toDelete}
                <div class="col-sm-4">
                    <div class="flex-fill" />
                    <div class="inline-flex flex-gap-base flex-nowrap">
                        <button
                            type="button"
                            class="btn btn-sm btn-secondary fade"
                            on:click|stopPropagation={handleDelete}
                        >
                            <span class="txt">Remove</span>
                        </button>

                        {#if interactive}
                            <button
                                type="button"
                                class="btn btn-sm btn-outline btn-expanded-sm"
                                on:click|stopPropagation={collapse}
                            >
                                <span class="txt">Done</span>
                            </button>
                        {/if}
                    </div>
                </div>
            {/if}
        </div>

        <input type="submit" class="hidden" tabindex="-1" />
    </form>
</Accordion>

<style>
    .title.field-name {
        max-width: 130px;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
    }
</style>
