<script lang="ts">

    import utils from "../../common/utils";
    import {DisplayMode} from "../../common/DisplayMode";
    import CheckBox from "../../checkbox";
    import type {OnChangeHandler} from "../../common/OnChangeHandler";

    export let disabled: boolean = false;
    export let readonly: boolean = false;
    export let style: string = "";
    export let value: string | number;
    export let bitBase: boolean = false;
    export let options: Array<any>;
    export let keyField: string = "code";
    export let textField: string = "text";
    export let delimiter: string = ';';
    export let displayMode: DisplayMode = DisplayMode.Edit;
    export let item$style: string = '';
    export let disabledOptions: Array<string> = [];
    export let hideOptions: Array<string> = [];
    export let variant: '' | 'plain' | 'outlined' | 'filled' = '';
    export let compact: boolean = false;
    export let onchange: OnChangeHandler<string | number> = null as unknown as OnChangeHandler<string | number>;
    export let onfocus: (() => void) | null = null;
    export let onblur: (() => void) | null = null;

    export const setFocus = () => {
        const firstCheckbox = groupContainer?.querySelector('input[type="checkbox"]:not(:disabled)') as HTMLInputElement;
        if (firstCheckbox) {
            firstCheckbox.focus();
        }
    }

    let textValue: string;
    let selectedList: Array<any> = [];
    let oldValue = value;
    let isUserChange: boolean = false;
    let hasFocus: boolean = false;
    let groupContainer: HTMLDivElement;

    const generateText = (list: Array<string>) => {
        if (list.length > 0) {
            let arr = [];
            for (let item of options) {
                if (list.indexOf(item[keyField]) > -1) {
                    arr.push(item[textField]);
                }
            }
            textValue = arr.length == 0 ? '' : arr.join(delimiter);
        } else {
            textValue = '';
        }
    }



    const handleCheckboxChange = (key: string) => async (checked: boolean) => {
        isUserChange = true;
        if (checked) {
            selectedList.push(key);
        } else {
            let idx = selectedList.findIndex(el => el == key);
            if (idx > -1) {
                selectedList.splice(idx, 1);
            }
        }
        selectedList = [...selectedList]; // 触发reactive更新
        if (bitBase) {
            let v = 0;
            for (let i=0; i<options.length; i++) {
                if (selectedList.indexOf(options[i][keyField]) > -1) {
                    v += (1 << i);
                }
            }
            value = v;
        } else {
            value = selectedList.length==0 ?  '' : selectedList.join(delimiter)
        }
    }

    const generateSelectedListViaBits = (v: number): void => {
        value = Math.round(v??0);
        let s = [];
        let idx=0;
        while (v > 0) {
            if ((v % 2) == 1) {
                s.push(options[idx][keyField]);
            }
            idx++;
            v = v >> 1;
        }
        selectedList = s;
    }

    const generateSelectedListViaString = (v: string): void => {
        value = v;
        selectedList = (value == null || value.toString().trim() == '') ? [] : value.split(delimiter);
    }

    $: bitBase ? generateSelectedListViaBits(utils.getNumberValue(value)??0) : generateSelectedListViaString(utils.getStringValue(value)??'');
    $: generateText(selectedList);

    // 处理onchange事件
    $: if (oldValue != value) {
        if (isUserChange) {
            onchange?.(value);
            isUserChange = false;
        }
        oldValue = value;
    }

    // 处理focus/blur事件
    const handleFocus = () => {
        if (!hasFocus) {
            hasFocus = true;
            onfocus?.();
        }
    }

    const handleBlur = () => {
        if (hasFocus) {
            hasFocus = false;
            onblur?.();
        }
    }

    const handleContainerClick = (e: MouseEvent) => {
        if (!disabled && !readonly && e.target === groupContainer) {
            handleFocus();
            setFocus();
        }
    }

    const handleContainerBlur = (e: FocusEvent) => {
        // 检查焦点是否移到了组件外部
        setTimeout(() => {
            const activeElement = document.activeElement;
            if (!groupContainer?.contains(activeElement)) {
                handleBlur();
            }
        }, 0);
    }


</script>
{#if displayMode === DisplayMode.View}
    <div class="uniface-display-field">
        <span>{textValue}</span>
    </div>
{:else}
    <div bind:this={groupContainer} class="uniface-group-box {variant}" {style} class:compact class:disabled on:click={handleContainerClick} on:focusout={handleContainerBlur}>
        {#each options as op}
            {#if (hideOptions??[]).indexOf(op[keyField]) === -1}
                <CheckBox {compact} {readonly} disabled={disabled || disabledOptions.indexOf(op[keyField]) > -1}
                      label={op[textField]} style={item$style} value={selectedList.indexOf(op[keyField]) > -1}
                      onchange={handleCheckboxChange(op[keyField])}
                      onclick={handleFocus}
                      onfocus={handleFocus}
                      onblur={handleContainerBlur}/>
            {/if}
        {/each}
    </div>
{/if}

