//@ts-ignore
import { __ } from '@wordpress/i18n';

import {
    CheckboxControl, PanelBody, TextControl, Tip,Button, DropdownMenu, Flex, FlexBlock, FlexItem,FormToggle, 
    __experimentalNumberControl as NumberControl, 
    __experimentalDivider as Divider,
    //@ts-ignore
} from '@wordpress/components';
import {
    more,
    check,
    pencil,
    trash,
    rotateLeft,
} from '@wordpress/icons';

import { useState, useEffect } from '@wordpress/element';
import { AttributesCanvas3d } from '../../../v2/blocks/canvas3d/types';
import C3dVariables from '../../../v2/guides';
import guidec3dvariables from '../../guides/guide-c3d-variables';
import getScrollsequenceFop from '../../../v2/getScrollsequenceFop'

/*

TODO: 
    - does not work really - once the attributes update, it does not update fully. i believe we need to have useeffect here.
    - when displayed too early (before spline loads) we get again => outdated values that are not correct (matched = false)
    - boolean does not update UI
    - when deleting we get a react error 


*/


export default function VariablesControl({
    attributes,
    setAttributes,
    elRef
}:{
    attributes: AttributesCanvas3d // TODO - improve types and assign default values   
    setAttributes: any
    elRef:any
}){
    const { variables } = attributes; 

    const data = getScrollsequenceFop(elRef.current)?.readBlock(elRef.current); // TODO: improve typing. It can be undefined I believe
    const variablesSpline = data?.variablesSpline || {};
    const variablesMatched = data?.variablesMatched || {};

    const variablesSafe = variables || {};
    console.log('variablesSafe:',variablesSafe) 
    const variablesUnmatched = Object.keys(variablesSafe).reduce((acc: any, key: string) => {
        if (data?.variablesMatched?.hasOwnProperty(key)) {
            acc[key] = variablesSafe[key];
        }
        return acc;
    }, {})
            

    // Make an array of objects, first variablesMatched, then variablesUnmatched
    const variablesMatchedArray = variablesMatched ? Object.keys(variablesMatched).map((keyName) => ({ matched:true, keyName, value: variablesMatched[keyName] })) : [];
    const variablesUnmatchedArray = variablesUnmatched ? Object.keys(variablesUnmatched).map((keyName) => ({ matched:false, keyName, value: variablesUnmatched[keyName] })) : [];
    const variablesAllArray = [
        ...variablesMatchedArray,
        ...variablesUnmatchedArray,
    ]


    console.log('1VariablesControl variables:',variables)
    console.log('2VariablesControl variablesSpline:',variablesSpline)
    console.log('3VariablesControl variablesMatched:',variablesMatched)
    console.log('4VariablesControl variablesUnmatched:',variablesUnmatched)
    console.log('5VariablesControl variablesAllArray:',variablesAllArray)
    
    return (
        <>
            <Tip>
                {__('Add variables in Spline Editor, save and then they appear here and can be edited.', 'scrollsequence')}
                <C3dVariables pages={guidec3dvariables}>
                    {({ isOpen, openGuide, closeGuide }) => (
                        <>
                            <Button onClick={openGuide} size="small" >Learn more.</Button>

                            {//isOpen && <p>Guide is open</p>
                            }
                        </>
                    )}
                </C3dVariables>  
            </Tip>          
            <Divider />
            {(variablesAllArray.length > 0) ? variablesAllArray.map((varx:any, index:number) => {
                if (typeof varx.value === "boolean") {
                    return <MyBooleanControl 
                        key={index}
                        keyName={varx.keyName}
                        value={Boolean(varx.value)}
                        matched={varx.matched}
                        attributes={attributes}
                        setAttributes={setAttributes}
                    />;
                } else if (typeof varx.value === "number") {
                    return <MyNumberControl 
                        key={index}
                        keyName={varx.keyName}
                        value={Number(varx.value)}
                        matched={varx.matched}
                        attributes={attributes}
                        setAttributes={setAttributes}
                    />;
                } else if (typeof varx.value === "string") {
                    return <MyStringControl 
                        key={index}
                        keyName={varx.keyName}
                        value={String(varx.value)}
                        matched={varx.matched}
                        attributes={attributes}
                        setAttributes={setAttributes}
                    />;
                } else {
                    return <p>error in type</p>;
                }
            })
            :
                <p>{__('No variables found', 'scrollsequence')}</p>
            }

          
        </>
    )
}

function MyBooleanControl({
    keyName,
    value,
    matched,
    attributes,
    setAttributes,
}:{
    keyName: string,
    value?: boolean
    matched: boolean
    attributes: AttributesCanvas3d,
    setAttributes: any
}){
    const { variables } = attributes;
    function handleDelete(){
        console.log('delete booean keyname:',keyName,)
        setAttributes({ variables: { ...variables, [keyName]: undefined } });
    }
    return (
        <>
            <Flex>
                <FlexBlock>
                    {keyName}
                </FlexBlock>        
                {!matched && (
                    <FlexItem>
                        <Button
                            icon={trash}
                            label="Delete"
                            size="small"
                            isDestructive
                            onClick={() => {
                                if (window.confirm("Are you sure you want to delete the value?")) {
                                    handleDelete();
                                }
                            }}
                        />      
                    </FlexItem>              
                )}                
                <FlexItem>
                    <FormToggle
                        checked={value}
                        onChange={() => setAttributes({ variables: { ...variables, [keyName]: !value } })}
                    />
                </FlexItem>
                <FlexItem>
                    {JSON.stringify(value)}
                </FlexItem>
            </Flex>
            <Divider />
        </>
    )
}

// Very similar to number control below, i wonder if we can merge them.
function MyStringControl({
    keyName,
    value,
    matched,
    attributes,
    setAttributes,
}:{
    keyName: string,
    value?: string
    matched: boolean
    attributes: AttributesCanvas3d,
    setAttributes: any
}){
    const { variables } = attributes;
    const [ localValue, setLocalValue ] = useState(value)
    function handleConfirm(){
        console.log('confirm  keyName',keyName,'localValue:', localValue)
        setAttributes({ variables: { ...variables, [keyName]: localValue } });
    }
    function handleReset(){
        console.log('reset keyName',keyName,'localValue', localValue)
        console.log('NOT IMPLEMENTED YET')
        //setAttributes({ variables: { ...variables, [keyName]: value } });
    }
    function handleDelete(){
        console.log('delete keyName',keyName,'localValue', localValue)
        setAttributes({ variables: { ...variables, [keyName]: undefined } });
    }

    return (
        <>
            <Flex style={{ marginBottom: '10px' }}>
                <FlexBlock>
                    {keyName}
                </FlexBlock>
                <FlexItem>
                    <>
                        {matched ? (
                            <Button
                                icon={rotateLeft}
                                label="Reset"
                                size="small"
                                isDestructive
                                onClick={() => {
                                    if (window.confirm("Are you sure you want to reset the value?")) {
                                        handleReset();
                                    }
                                }}
                            />
                        ) : (
                            <Button
                                icon={trash}
                                label="Delete"
                                size="small"
                                isDestructive
                                onClick={() => {
                                    if (window.confirm("Are you sure you want to delete the value?")) {
                                        handleDelete();
                                    }
                                }}
                            />
                        )}
                        <Button icon={ check } label="Confirm" onClick={() => handleConfirm()} />
                    </>
                </FlexItem>
            </Flex>

            <TextControl
                __nextHasNoMarginBottom
                label={keyName}
                hideLabelFromVision
                value={localValue}
                onChange={(newValue: string) => {
                    setLocalValue(newValue)
                }}
                //help={'string help matched'}
            />
            <Divider />
        </>
    )
}



// Same as string, except a few differences, can be merged after some testing - we need to pass the type explicitly to the comp.

function MyNumberControl({
    keyName,
    value,
    matched,
    attributes,
    setAttributes,
}:{
    keyName: string,
    value?: number
    matched: boolean
    attributes: AttributesCanvas3d,
    setAttributes: any
}){
    const { variables } = attributes;
    const [ localValue, setLocalValue ] = useState(value)
    function handleConfirm(){
        console.log('confirm  keyName',keyName,'localValue:', localValue)
        setAttributes({ variables: { ...variables, [keyName]: localValue } });
    }
    function handleReset(){
        console.log('reset keyName',keyName,'localValue', localValue)
        console.log('NOT IMPLEMENTED YET')
        //setAttributes({ variables: { ...variables, [keyName]: value } });
    }
    function handleDelete(){
        console.log('delete keyName',keyName,'localValue', localValue)
        setAttributes({ variables: { ...variables, [keyName]: undefined } });
    }

    return (
        <>
            <Flex style={{ marginBottom: '10px' }}>
                <FlexBlock>
                    {keyName}
                </FlexBlock>
                <FlexItem>
                    <>
                        {matched ? (
                            <Button
                                icon={rotateLeft}
                                label="Reset"
                                size="small"
                                isDestructive
                                onClick={() => {
                                    if (window.confirm("Are you sure you want to reset the value?")) {
                                        handleReset();
                                    }
                                }}
                            />
                        ) : (
                            <Button
                                icon={trash}
                                label="Delete"
                                size="small"
                                isDestructive
                                onClick={() => {
                                    if (window.confirm("Are you sure you want to delete the value?")) {
                                        handleDelete();
                                    }
                                }}
                            />
                        )}
                        <Button icon={ check } label="Confirm" onClick={() => handleConfirm()} />
                    </>
                </FlexItem>
            </Flex>

            <NumberControl
                __next40pxDefaultSize
                label={keyName}
                hideLabelFromVision
                onChange={(newValue: any) => {
                    console.log('newValue:', newValue, 'Number:',Number(newValue), )
                        setLocalValue(Number(newValue))
                }}
                value={localValue}
            />

            <Divider />
        </>
    )
}


















