//@ts-ignore: Cannot find module '@wordpress/i18n' or its corresponding type declarations
import { __ } from '@wordpress/i18n';
import { video, code } from '@wordpress/icons'; 
import {
	__experimentalBlockAlignmentMatrixControl as BlockAlignmentMatrixControl,
	//@ts-ignore
} from '@wordpress/block-editor';
import AnimationControlPanel from './AnimationControlPanel'
import PointerEventsSelect from '../../components/PointerEventsSelect';
import {animations, getAnimationObject} from './animations'
import ChatButton from '../../components/block-controls-canvasxd/ChatButton';
import getScrollsequenceFop from '../../getScrollsequenceFop'
import getElByClientId from '../../getElByClientId'
import { DHCA } from '../../../dbg'
// !!!!! PROBLEM: Gsap is only present in the PREMIUM version. This shoud happen in the "extend" folder.
import gsap from 'gsap' // !!!!! here i need to make sure the version matches EXACTLY the version in the plugin.
// !!!!! Also GSAP needs to be loaded "the wordpress way" using script and not via npm
// !!!! Also this needs to happen only on the premium side of things.

declare const wp: any;

const { createHigherOrderComponent } = wp.compose;
const { InspectorControls, useBlockProps, BlockControls } = wp.blockEditor;
const { PanelBody, SelectControl, TextControl, Modal, Button, Flex, FlexItem, Popover, ToolbarButton, DropdownMenu, ToolbarGroup,   } = wp.components;
const { useSelect } = wp.data // done this myself :-) so proud! <3 LOL
const { useState, useRef, useEffect } = wp.element // done this myself too :-) so proud! <3 LOL

type VpAlign =  undefined | 'top left' | 'top center' | 'top right' | 'center left' | 'center center' | 'center right' | 'bottom left' | 'bottom center' | 'bottom right'

function getClassNameFromVpAlign(vpAlign:VpAlign){
    if (!vpAlign) return 'ssq-hoc-scene-center-center';
    return `ssq-hoc-scene-${vpAlign.replace(" ", "-")}`;
}

// see: https://developer.wordpress.org/block-editor/reference-guides/filters/block-filters/#editor-blockedit

export const withScrollsequenceAnimationControls = createHigherOrderComponent( ( BlockEdit:any ) => {
    return ( props:any ) => {
        const { clientId, attributes, setAttributes } = props;
        const { 
            ssqAnimateOnLoad, ssqAnimateOnClick, ssqAnimateOnHover,ssqAnimateOnScroll,
            ssqPointerEvents, 
            ssqSceneBegin, ssqSceneEnd, ssqSceneAlign, 
        } = attributes;

        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 hasContainerAncestor =  parentClientNames.includes('scroll-sequence/v2-container');
        const hasSceneAncestor =  parentClientNames.includes('scroll-sequence/v2-scene');
        const hasContainerOrSceneAncestor = hasContainerAncestor || hasSceneAncestor;
        const hasSceneDirectParent = (parentClientNames[parentClientNames.length-1] === 'scroll-sequence/v2-scene') ? true : false;
        const isSceneBlock = props.name === 'scroll-sequence/v2-scene'

        const isCanvas1DBlock = props.name === 'scroll-sequence/v2-canvas1d';
        const isCanvas2DBlock = props.name === 'scroll-sequence/v2-canvas2d';
        const isCanvas3DBlock = props.name === 'scroll-sequence/v2-canvas3d';

        const isGroupBlock = props.name === 'core/group';

        const isCanvasBlock = isCanvas1DBlock || isCanvas2DBlock || isCanvas3DBlock;

        // hasInnerBlocks
        const hasInnerBlocks = useSelect((select: any) => {
            const { getBlock } = select('core/block-editor');
            const block = getBlock(clientId);
            return block.innerBlocks && block.innerBlocks.length > 0;
        }, [clientId]);
        
        //console.log('block name: ', props.name, 'hasInnerBlocks:', hasInnerBlocks, );

        // based on threes show* we decide what to render.
        const showKeyframes =       hasContainerOrSceneAncestor && !isSceneBlock;   // keyframe animation is only available in container blocks children and NOT on scene  itself
        const showCustomTriggers =  hasContainerOrSceneAncestor && !isSceneBlock && !hasSceneAncestor; // custom scroll trigger is only available in container blocks children and NOT on scene block itself or children
        const showAlign = hasSceneDirectParent;   // alignment controls are only available on direct children of scene block

        // modal 
        const [ isModalOpen, setModalOpen ] = useState( false ); // < false | 'onLoad' | 'onClick' | 'onHover' | 'onScroll'>
        const closeModal = () => setModalOpen( false );
        const openModal = (tab: any) => setModalOpen( tab );



        // use effect
        useEffect(() => {
            const element = getElByClientId( clientId ); // OLD : const element = elRef.current?.children[0];
            element && getScrollsequenceFop(element)?.createBlock(element);

            return () => {
                const element = getElByClientId( clientId ); // OLD : const element = elRef.current?.children[0];
                element && getScrollsequenceFop(element)?.destroyBlock(element);
            };
        }, [
            ssqAnimateOnLoad, ssqAnimateOnClick, ssqAnimateOnHover, ssqAnimateOnScroll,
            ssqPointerEvents,
            ssqSceneBegin, ssqSceneEnd, ssqSceneAlign, 
        ]);  
        
        // console.log(
        //     'name: ', props.name, 
        //     { 
        //         parentClientNames, 
        //         hasContainerAncestor, 
        //         hasSceneAncestor, 
        //         hasSceneDirectParent, 
        //         isSceneBlock, 
        //         isCanvasBlock,
        //         showKeyframes, 
        //         showCustomTriggers, 
        //         showAlign 
        //     }
        // );    

        if ( !showKeyframes && !showCustomTriggers && !showAlign  ) { // Bail if nothing is added
            return (
                <BlockEdit {...props} />
            )
        }

        return(
            <>
                { props.isSelected && isGroupBlock && (
                    <BlockControls>
                        <ChatButton clientId={clientId} />
                    </BlockControls>
                )}


                { props.isSelected && showAlign && (
                    <BlockControls group="block">
                        <BlockAlignmentMatrixControl
                            label={ __( 'Change content position', 'scrollsequence' ) }
                            value={ ssqSceneAlign }
                            onChange={ ( nextPosition:any ) =>
                                setAttributes( {
                                    ssqSceneAlign: nextPosition,
                                } )
                            }
                            //isDisabled={ ! hasInnerBlocks }
                        />
                    </BlockControls>    
                )}

                { 
                /*
                    If we have showAlign true, we need to wrap the BlockEdit in an extra div to be able to position it correctly.
                    If we dont have showAlign, we can just render the BlockEdit directly.
                */
                showAlign ? (
                    <div
                        className={`ssq-absolute ssq-inset ssq-flex ssq-pointer-events-none ${ ssqPointerEvents === 'none' ? 'ssq-pointer-events-child-none' :  'ssq-pointer-events-child-auto' } ${getClassNameFromVpAlign(ssqSceneAlign)}`}
                        style={{marginBlockStart: '0px', marginBlockEnd: '0px', }}
                        data-ssq-scene-begin={ssqSceneBegin ? JSON.stringify(ssqSceneBegin) : 0} // !!! this is scene specific, why to have this always here? 
                        data-ssq-scene-end={ssqSceneEnd ? JSON.stringify(ssqSceneEnd) : 1} // !!! this is scene specific, why to have this always here?                     
                    >
                        <BlockEdit 
                            // key="edit" // not sure what is this? 
                            { ...props }  
                        />                        
                    </div>
                ) : (
                    <BlockEdit 
                        // key="edit" // not sure what is this? 
                        { ...props }  
                    />
                )}

                { props.isSelected && (
                    <>
                        <InspectorControls group="advanced">
                            <PointerEventsSelect attributes={attributes} setAttributes={setAttributes} />
                        </InspectorControls>
                        <InspectorControls>
                            

                            { !isCanvasBlock && ( // It throws a bunch of errors if i try to animate canvas, turning off for now
                                <AnimationControlPanel 
                                    clientId={clientId}
                                    attributes={attributes} 
                                    setAttributes={setAttributes} 
                                    setModalOpen={setModalOpen} 
                                    closeModal={closeModal} 
                                    openModal={openModal} 
                                />
                            )}

                            
                        </InspectorControls>
                    </>
                )}

                { props.isSelected && isModalOpen && (
                    <Modal title={`Choose ${isModalOpen} animation`} onRequestClose={ closeModal } isFullScreen>
                        <div
                            style={{
                                display: 'grid',
                                gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))',
                                gap: '16px',
                            }}
                        >
                            {animations.map((animation) => (
                                <AnimationItem
                                    key={animation.id}
                                    title={animation.title}
                                    id={animation.id}
                                    description={animation.description}
                                    data={animation.data}
                                    setAttributes={setAttributes}
                                    isModalOpen={isModalOpen}
                                    setModalOpen={setModalOpen}
                                    
                                />
                            ))}
                        </div>
                    </Modal>
                ) }                   

            </>
        )

    };
}, 'withScrollsequenceAnimationControls' );        




function doAnim(animObject:any, target:any) {
    gsap.to(target, { ...animObject, onComplete: () => {
        DHCA&&console.log('Animation completed');
    } });
}

const AnimationItem = ({ title, id, description, data, setAttributes,isModalOpen, setModalOpen }:any) => {
    //DHCA&&console.log('isModalOpen',isModalOpen)
    const animRef = useRef(null);

    const [ isPopover, setIsPopover ] = useState( false );
    const togglePopover = () => {
        setIsPopover( ( state:any ) => ! state );
    };

    return (
        <Flex
            className="pattern-item"
            direction="column"
            style={{
                border: '1px solid #e2e2e2',
                borderRadius: '4px',
                padding: '10px',
                marginBottom: '10px',
                
            }}
        >
            <FlexItem>
                <div >
                    {isPopover 
                    ?
                        <pre style={{overflow:"auto", height:"250px", marginBottom: '10px',}}>{JSON.stringify(getAnimationObject(id),null,2)}</pre>
                    :
                        <div
                            onMouseOver={() => { doAnim(getAnimationObject(id), animRef.current) }}
                            onClick={()=>{ 
                                //alert('are you sure?') 
                                DHCA&&console.log('xxxxxxxxx isModalOpen',isModalOpen);
                                (isModalOpen === 'onLoad') && setAttributes({ ssqAnimateOnLoad: {to: getAnimationObject(id )} }) ;
                                (isModalOpen === 'onClick') && setAttributes({ ssqAnimateOnClick: {to: getAnimationObject(id )} }) ;
                                (isModalOpen === 'onHover') && setAttributes({ ssqAnimateOnHover: {to: getAnimationObject(id )} }) ;
                                (isModalOpen === 'onScroll') && setAttributes({ ssqAnimateOnScroll: {to: getAnimationObject(id )} }) ;
                                setModalOpen(false);
                            }}
                            style={{
                                minHeight: '250px',
                                backgroundColor: '#f2f2f2',
                                marginBottom: '10px',
                                overflow: 'hidden',
                                display: 'flex',
                                alignItems: 'center',
                                justifyContent: 'center',
                                cursor: 'pointer',
                            }}
                        >
                            <p ref={animRef} >Hello World</p>
                        </div>                   
                    }
 
                </div>
            </FlexItem>
            <FlexItem>
                <Flex>
                    <h4>{title}</h4>
                    <span>
                        <Button 
                            icon={video} // Add the play icon here
                            label="Play Animation"
                            onClick={() => { setIsPopover(false); doAnim(getAnimationObject(id), animRef.current)}}
                        />
                        <Button 
                            icon={code} // Add the play icon here
                            isPressed={isPopover}
                            label="View Code"
                            onClick={ togglePopover }
                        />
                    </span>
                </Flex>
                {/* <p>{description}</p> */}
            </FlexItem>
        </Flex>
    );
};
