import styled from '@emotion/styled';
import {
    Icon,
    TextareaControl,
    PanelRow,
    __experimentalToolsPanel as ToolsPanel,
    __experimentalToolsPanelItem as ToolsPanelItem,
    __experimentalConfirmDialog as ConfirmDialog,
    Button, 
    Popover,
    DropdownMenu,
    Panel, 
    PanelBody
    //@ts-ignore: Cannot find module '@wordpress/components' or its corresponding type declarations.
} from '@wordpress/components';
//@ts-ignore: Cannot find module '@wordpress/i18n' or its corresponding type declarations.
import { __ } from '@wordpress/i18n';
//@ts-ignore: Cannot find module '@wordpress/data' or its corresponding type declarations.
import { useSelect } from '@wordpress/data';
import { plus, video, edit, update, trash, check } from '@wordpress/icons'; 
import { useState, useEffect, useRef } from '@wordpress/element';

import { IconGenerateWithAI } from '../../../icons'
import { ScrollTriggerAnimations} from './animations'
import getScrollsequenceFop from '../../getScrollsequenceFop'
import getElByClientId from '../../getElByClientId'
import { DHCA } from '../../../dbg'


import { experimental_useObject as useObject } from '@ai-sdk/react';
import { z } from "zod";


import Stack from '@mui/material/Stack';
import PinControlHocs from '../../components/PinControlHocs';
import ScrollTriggerControlHocs from '../../components/ScrollTriggerControlHocs';

declare const scroll_sequence_editor_data :any

const PanelDescription = styled.div`
    grid-column: span 2;
`;

const SingleColumnItem = styled( ToolsPanelItem )`
    grid-column: span 1;
`;


export default function AnimationControlPanel({clientId, attributes, setAttributes, setModalOpen, closeModal, openModal}:any) {
    const { ssqAnimateOnLoad, ssqAnimateOnClick, ssqAnimateOnHover,ssqAnimateOnScroll } = attributes;
    //DHCA&&console.log('AnimationControlPanel() attributes:',attributes)

    const [ localOnLoadValue, setLocalOnLoadValue ] = useState(ssqAnimateOnLoad?.to && JSON.stringify(ssqAnimateOnLoad.to,null,2));
    const [ localOnClickValue, setLocalOnClickValue ] = useState(ssqAnimateOnClick?.to && JSON.stringify(ssqAnimateOnClick.to,null,2));
    const [ localOnHoverValue, setLocalOnHoverValue ] = useState(ssqAnimateOnHover?.to && JSON.stringify(ssqAnimateOnHover.to,null,2));
    const [ localOnScrollValue, setLocalOnScrollValue ] = useState(ssqAnimateOnScroll?.to && JSON.stringify(ssqAnimateOnScroll.to,null,2));
    const [ localOnScrollTriggerValue, setLocalOnScrollTriggerValue ] = useState(ssqAnimateOnScroll?.st && JSON.stringify(ssqAnimateOnScroll.st,null,2));

    const resetAll = () => {
        setAttributes({ ssqAnimateOnLoad: undefined })
        setAttributes({ ssqAnimateOnClick: undefined })
        setAttributes({ ssqAnimateOnHover: undefined })
        setAttributes({ ssqAnimateOnScroll: undefined })
    };

    useEffect(() => {
        // update local values when attributes change
        setLocalOnLoadValue(ssqAnimateOnLoad?.to && JSON.stringify(ssqAnimateOnLoad.to,null,2));
        setLocalOnClickValue(ssqAnimateOnClick?.to && JSON.stringify(ssqAnimateOnClick.to,null,2));
        setLocalOnHoverValue(ssqAnimateOnHover?.to && JSON.stringify(ssqAnimateOnHover.to,null,2));
        setLocalOnScrollValue(ssqAnimateOnScroll?.to && JSON.stringify(ssqAnimateOnScroll.to,null,2));
        setLocalOnScrollTriggerValue(ssqAnimateOnScroll?.st && JSON.stringify(ssqAnimateOnScroll.st,null,2));
    }, [ssqAnimateOnLoad, ssqAnimateOnClick, ssqAnimateOnHover, ssqAnimateOnScroll]);

    // START - duplicate logic from withScrollsequenceAnimationControls to detect ancestors => we could just pass this prop instead ?
    const parentClientNames = useSelect((select: any) => {
        const parentClientIds = select('core/block-editor').getBlockParents(clientId);
        return parentClientIds.map((id: string) => {
            const { name } = select('core/block-editor').getBlock(id) || {};
            return name;
        });
    }, [clientId]);
    const hasSceneAncestor =  parentClientNames.includes('scroll-sequence/v2-scene'); 
    // END - duplicate logic from withScrollsequenceAnimationControls to detect ancestors => we could just pass this prop instead ?


    return (
        <>
        <ToolsPanel label={ __( 'Animation Settings', 'scrollsequence' ) } resetAll={ resetAll }>
            <PanelDescription>
                { __( 'Select dimensions or spacing related settings from the menu for additional controls.', 'scrollsequence' ) }
            </PanelDescription>
            {/* 
            
                ██       ██████   █████  ██████      
                ██      ██    ██ ██   ██ ██   ██     
                ██      ██    ██ ███████ ██   ██     
                ██      ██    ██ ██   ██ ██   ██     
                ███████  ██████  ██   ██ ██████      
                                
            */}            
            <ToolsPanelItem
                hasValue={ () => !! ssqAnimateOnLoad }
                label={ __( 'On Load', 'scrollsequence' ) }
                onDeselect={ () => setAttributes({ ssqAnimateOnLoad: undefined }) }
            >
                {ssqAnimateOnLoad 
                ?
                    <TextFieldWithButtons
                        label={__( 'Animate on Load (.to)', 'scrollsequence' ) }
                        value={localOnLoadValue}
                        onChangeValue={(value:string) => {setLocalOnLoadValue(value)}}
                        onClickPlay={ ()=> {
                            getScrollsequenceFop(getElByClientId( clientId )!)?.createBlock(getElByClientId( clientId )!)
                        }}
                        onClickDisable={ ()=> {
                            getScrollsequenceFop(getElByClientId( clientId )!)?.destroyBlock(getElByClientId( clientId )!)
                        }}
                        onClickSelect={ ()=> openModal('onLoad') }
                        onClickRemove={ ()=> { 
                            // restore to the original state => kill the timeline and set to null
                            let timeline = getScrollsequenceFop(getElByClientId( clientId )!)?.readBlock(getElByClientId( clientId )!)?.animContent.onLoad.timeline;
                            timeline?.revert()
                            timeline?.kill();
                            timeline = null;
                            // remove attributes
                            setAttributes({ ssqAnimateOnLoad: undefined }) } 
                        }
                        onClickSave={ ()=> {
                            setAttributes({ ssqAnimateOnLoad: {to: JSON.parse(localOnLoadValue)} })
                        }}
                    />
                :
                    <Button variant="secondary" icon={plus}  onClick={ ()=> openModal('onLoad') }>
                        Add Load Animation
                    </Button>                               
                }
            </ToolsPanelItem>        
            {/* 
            
            ██████  ██      ██  ██████ ██   ██ 
            ██      ██      ██ ██      ██  ██  
            ██      ██      ██ ██      █████   
            ██      ██      ██ ██      ██  ██  
            ██████  ███████ ██  ██████ ██   ██ 
                                   
                                
            */}                           
            <ToolsPanelItem
                hasValue={ () => !! ssqAnimateOnClick }
                label={ __( 'On Click', 'scrollsequence' ) }
                onDeselect={ () => setAttributes({ ssqAnimateOnClick: undefined }) }
            >
                {ssqAnimateOnClick 
                ?
                    <TextFieldWithButtons
                        label={__( 'Animate on Click (.to)', 'scrollsequence' ) }
                        value={localOnClickValue}
                        onChangeValue={(value:string) => {setLocalOnClickValue(value)}}
                        onClickPlay={ ()=> {
                            getScrollsequenceFop(getElByClientId( clientId )!)?.readBlock(getElByClientId( clientId )!)?.animContent.onClick.timeline.play(0)
                        }}
                        onClickDisable={ ()=> {
                            getScrollsequenceFop(getElByClientId( clientId )!)?.destroyBlock(getElByClientId( clientId )!)
                        }}
                        onClickSelect={ ()=> openModal('onClick') }
                        onClickRemove={ ()=> { 
                            // restore to the original state => kill the timeline and set to null
                            let timeline = getScrollsequenceFop(getElByClientId( clientId )!)?.readBlock(getElByClientId( clientId )!)?.animContent.onClick.timeline;
                            timeline?.revert()
                            timeline?.kill();
                            timeline = null;
                            // remove attributes
                            setAttributes({ ssqAnimateOnClick: undefined }) } 
                        }
                        onClickSave={ ()=> {
                            setAttributes({ ssqAnimateOnClick: {to: JSON.parse(localOnClickValue)} })
                        }}
                    />                    
                :
                    <Button variant="secondary" icon={plus}  onClick={ ()=> openModal('onClick') }>
                        Add Click Animation
                    </Button>                               
                }           
            </ToolsPanelItem>   
            {/* 
            
            ██   ██  ██████  ██    ██ ███████ ██████  
            ██   ██ ██    ██ ██    ██ ██      ██   ██ 
            ███████ ██    ██ ██    ██ █████   ██████  
            ██   ██ ██    ██  ██  ██  ██      ██   ██ 
            ██   ██  ██████    ████   ███████ ██   ██ 
                                          
                                   
                                
            */}  
            <ToolsPanelItem
                hasValue={ () => !! ssqAnimateOnHover }
                label={ __( 'On Hover', 'scrollsequence' ) }
                onDeselect={ () => setAttributes({ ssqAnimateOnHover: undefined }) }
            >
                {ssqAnimateOnHover 
                ?
                    <TextFieldWithButtons
                        label={__( 'Animate on Hover (.to)', 'scrollsequence' ) }
                        value={localOnHoverValue}
                        onChangeValue={(value:string) => {setLocalOnHoverValue(value)}}
                        onClickPlay={ ()=> {
                            getScrollsequenceFop(getElByClientId( clientId )!)?.readBlock(getElByClientId( clientId )!)?.animContent.onHover.timeline.play(0)
                        }}
                        onClickDisable={ ()=> {
                            getScrollsequenceFop(getElByClientId( clientId )!)?.destroyBlock(getElByClientId( clientId )!)
                        }}
                        onClickSelect={ ()=> openModal('onHover') }
                        onClickRemove={ ()=> { 
                            // restore to the original state => kill the timeline and set to null
                            let timeline = getScrollsequenceFop(getElByClientId( clientId )!)?.readBlock(getElByClientId( clientId )!)?.animContent.onHover.timeline;
                            timeline?.revert()
                            timeline?.kill();
                            timeline = null;
                            // remove attributes
                            setAttributes({ ssqAnimateOnHover: undefined }) } 
                        }
                        onClickSave={ ()=> {
                            setAttributes({ ssqAnimateOnHover: {to: JSON.parse(localOnHoverValue)} })
                        }}
                    />                    
                :
                    <Button variant="secondary" icon={plus}  onClick={ ()=> openModal('onHover') }>
                        Add Hover Animation
                    </Button>                               
                }            
            </ToolsPanelItem>        
            {/* 
            
            ███████  ██████ ██████   ██████  ██      ██      
            ██      ██      ██   ██ ██    ██ ██      ██      
            ███████ ██      ██████  ██    ██ ██      ██      
                 ██ ██      ██   ██ ██    ██ ██      ██      
            ███████  ██████ ██   ██  ██████  ███████ ███████ 
                                   
                                
            */}               
            <ToolsPanelItem
                hasValue={ () => !! ssqAnimateOnScroll }
                label={ __( 'On Scroll', 'scrollsequence' ) }
                onDeselect={ () => setAttributes({ ssqAnimateOnScroll: undefined }) }
            >
                {ssqAnimateOnScroll 
                ?
                    <>

                        <TextFieldWithButtons
                            label={__( 'Animate on Scroll (.to)', 'scrollsequence' ) }
                            value={localOnScrollValue}
                            onChangeValue={(value:string) => {setLocalOnScrollValue(value)}}
                            onClickPlay={ ()=> {
                                getScrollsequenceFop(getElByClientId( clientId )!)?.readBlock(getElByClientId( clientId )!)?.animContent.onScroll.timeline.play(0)
                            }}
                            onClickDisable={ ()=> {
                                getScrollsequenceFop(getElByClientId( clientId )!)?.destroyBlock(getElByClientId( clientId )!)
                            }}
                            onClickSelect={ ()=> openModal('onScroll') }
                            onClickRemove={ ()=> { 
                                // restore to the original state => kill the timeline and set to null
                                let timeline = getScrollsequenceFop(getElByClientId( clientId )!)?.readBlock(getElByClientId( clientId )!)?.animContent.onScroll.timeline;
                                timeline?.revert()
                                timeline?.kill();
                                timeline = null;
                                // remove attributes
                                setAttributes({ ssqAnimateOnScroll: undefined }) } 
                            }
                            onClickSave={ ()=> {
                                setAttributes({ ssqAnimateOnScroll: {to: JSON.parse(localOnScrollValue)} })
                            }}
                        />

                        { !hasSceneAncestor &&  // trigger and pins are only relevant when inside container, but NOT inside scene
                            <>
                                {/* <p>TODO:</p>
                                <p>1. Animation control (OK)</p>
                                <p>2. ScrollTrigger control (default|custom(s))</p>
                                <p>3. Pin Cotrol (default: off, trigger on + modify)</p>
                                Dneska: */}
                                <ScrollTriggerControlHocs
                                    attributes={attributes}
                                    setAttributes={setAttributes}
                                />

                                <PinControlHocs
                                    attributes={attributes}
                                    setAttributes={setAttributes}
                                />


                            </>
                        }
                    </>
                :
                    <Button variant="secondary" icon={plus}  onClick={ ()=> openModal('onScroll') }>
                        Add Scroll Animation
                    </Button>                               
                }   
            </ToolsPanelItem>                                        
        </ToolsPanel>

        <Panel>
            <PanelBody title={__("Debug ", "scrollsequence")} initialOpen={false}>
                <p>Attributes:</p>
                <pre>{JSON.stringify(attributes, null, 2)}</pre>
            </PanelBody>
        </Panel>  

        </>
    )
}


function TextFieldWithButtons({ 
    label,
    value,
    onChangeValue,

    onClickPlay, // play animation
    onClickDisable, // disable animation in editor (temporarily)
    onClickSelect, // select animation (opens modal)
    
    onClickRemove, // remove animation
    onClickSave, // save animation
}:{
    label:string,
    value:string,
    onChangeValue:(value:string)=>void,

    onClickPlay:()=>void,
    onClickDisable:()=>void,
    onClickSelect:()=>void,

    onClickRemove:()=>void,
    onClickSave:()=>void,
    
}){
    
    const [isValidJSON, setIsValidJSON] = useState(true);
    useEffect(() => {
        try {
            JSON.parse(value);
            setIsValidJSON(true);
        } catch (e) {
            setIsValidJSON(false);
        }
    }, [value]);

    const [ isComfirmDialogOpen, setIsConfirmDialogOpen ] = useState( false );
    const handleConfirm = () => {
        //console.debug( 'Confirmed!' );
        onClickRemove();
        setIsConfirmDialogOpen( false );
    };

    const handleCancel = () => {
        //console.debug( 'Cancelled!' );
        setIsConfirmDialogOpen( false );
    };

    // Popover for animation
    const [ popoverAnchor, setPopoverAnchor ] = useState();
    const [ isPopoverOpen, setIsPopoverOpen ] = useState( false );  
    const [ prompt, setPrompt ] = useState( '' );

    // This needs to be the same as the schema in the backend
    const schemaAnimation = z.object({
        animation: z.object({
            category: z
                .string()
                .describe(
                    "Category of the animation. Allowed categories: Simple, Advanced, Loop, Yoyo, Other."
                ),
            keyframes: z.string().describe("CSS keyframes for the animation."),
        }),
    });

    const { submit, isLoading, object } = useObject({
      api: `${scroll_sequence_editor_data.scrollSequenceApiUrl}/v2/generate/content/animation`,
      headers: {
        'Authorization': `${scroll_sequence_editor_data.fs_auth_hash}`,
      },
      schema: schemaAnimation,
      onFinish({ object }) {
        console.log('onFinish object:', object);
        // if (object != null) {
        //   setAnimation(object.animation);
        //   setInput("");
        //   inputRef.current?.focus();
        // }
      },
      onError: (e:any) => {
        alert("Error connecting to the API, please try again later!");
        console.error('e:',e)
        //toast.error("Error connecting to the API, please try again later!");
      },
    });   

    
    function genexxx() {
        const submitData = {
            prompt: prompt, 
            existing: JSON.parse(value)
        }
        console.log('submitData:', submitData);

        submit(submitData); 
    }


    return (
        <TextareaControl
            __nextHasNoMarginBottom
            ref={ setPopoverAnchor }
            label={label}
            help={ 
                <>
                    <div style={{color: isValidJSON ? undefined : 'red', textAlign:'right'}}>
                        {isValidJSON ? 'Valid JSON' : 'Invalid JSON'}
                    </div>
                    <div style={{display:'flex', justifyContent:'space-between'}}>
                        <div style={{display:'flex', gap:'5px'}}>
                            <Button 
                                icon={video}  
                                label={__("Play Animation", "scrollsequence")}
                                size="small"
                                onClick={ onClickPlay}
                            />
                            <Button 
                                label={__("Disable Animation in the Editor", "scrollsequence")}
                                size="small"
                                onClick={ onClickDisable } 
                                icon={<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M4.67 10.664s-2.09 1.11-2.917 1.582l.494.87 1.608-.914.002.002c.343.502.86 1.17 1.563 1.84.348.33.742.663 1.185.976L5.57 16.744l.858.515 1.02-1.701a9.1 9.1 0 0 0 4.051 1.18V19h1v-2.263a9.1 9.1 0 0 0 4.05-1.18l1.021 1.7.858-.514-1.034-1.723c.442-.313.837-.646 1.184-.977.703-.669 1.22-1.337 1.563-1.839l.002-.003 1.61.914.493-.87c-1.75-.994-2.918-1.58-2.918-1.58l-.003.005a8.29 8.29 0 0 1-.422.689 10.097 10.097 0 0 1-1.36 1.598c-1.218 1.16-3.042 2.293-5.544 2.293-2.503 0-4.327-1.132-5.546-2.293a10.099 10.099 0 0 1-1.359-1.599 8.267 8.267 0 0 1-.422-.689l-.003-.005Z"></path></svg>}/>
                            <Button icon={update}  label={__("Select Animation", "scrollsequence")} size="small" onClick={ onClickSelect }/>
                        </div>
                        <Button
                            icon={<IconGenerateWithAI width={16} height={16} />}
                            label={__("Generate with AI", "scrollsequence")} 
                            size="small" 
                            onClick={ ()=> 
                                setIsPopoverOpen((state) => !state)
                            }
                        />

                        {isPopoverOpen && 
                            <Popover anchor={ popoverAnchor } placement="left" flip={false} offset={30}>
                                <div style={{padding: '10px'}}>
                                    <TextareaControl
                                    __nextHasNoMarginBottom
                                        label="Prompt"
                                        help="Enter a prompt for the AI to generate animation code."
                                        value={ prompt }
                                        onChange={ ( value:any ) => setPrompt( value ) }
                                        style={{minWidth: '300px', }}
                                        
                                    />
                                    <pre>{JSON.stringify(object, null, 2)}</pre>
                                    {object && (<>Please copy and paste the JSON above to the right to try the animation</>)}
                                    <Stack direction={"row"} sx={{margin: 1}}>
                                        {/* <Button onClick={()=>setPrompt("")}> Undo </Button>     */}
                                        <Button onClick={()=>genexxx()} disabled={isLoading} variant="secondary" > Generate </Button>
                                    </Stack>
                                </div>
                            </Popover>
                        }




                        <div style={{display:'flex', gap:'5px'}}>
                            <Button 
                                icon={trash} 
                                label={__("Remove Animation", "scrollsequence")} 
                                size="small" 
                                onClick={ ()=> setIsConfirmDialogOpen( true ) } 
                                isDestructive
                            /> 
                            <Button 
                                icon={check} 
                                label={__("Save Animation", "scrollsequence")} 
                                size="small" 
                                onClick={ onClickSave } 
                                disabled={!isValidJSON}
                                style={{color: isValidJSON ? 'green' : undefined}}
                            />
                        </div>
                        {/* <TimelinePopoverButton />  // TRY THIS AS DROPDOWN MENU!!!! */}
                    </div> 
                    <ConfirmDialog
                        isOpen={ isComfirmDialogOpen }
                        onConfirm={ handleConfirm }
                        onCancel={ handleCancel }
                    >
                        <h2>
                            Trash animation? 
                        </h2>
                        This action cannot be undone!
                    </ConfirmDialog>

                </>
            }
            rows={10}
            value={ value }
            onChange={ onChangeValue }
        />      
    )
}


// function SingleAnimation({type}:{type:'onLoad'|'onClick'|'onHover'|'onScroll'}){
//     const [ isTimelinePopoverVisible, setIsTimelinePopoverVisible ] = useState( false );
//     const toggleVisible = () => {
//         setIsTimelinePopoverVisible( ( state ) => ! state );
//     };

//     return(
//         <Button icon={edit}  label="Edit Animation" onClick={ toggleVisible }>
//             <TimelinePopover isTimelinePopoverVisible={ isTimelinePopoverVisible} />
//         </Button>
//     )    
// }



























