"use client"

import React, {
    useId,
    useRef,
    useState,
    forwardRef,
    useCallback,
    useImperativeHandle
} from 'react';
import {Ripple} from "./ripple";
import {Ripples} from "./ripple";
import {RippleAreaProps} from "./ripple.types";

const TIMEOUT : number = 550;
const rippleAreaContext = React.createContext(false);

const RippleArea = forwardRef(

    function RippleArea({central = false, callback, ...props} : RippleAreaProps, ref) {

        const [ripples, setRipples] = useState<Array<JSX.Element>>([]),
              rippleDomain = useRef<any>(null),
              clicked = useRef<boolean>(false),
              uniqueKey = useRef<number>(0),
              uniqueId = useId();

        let classes = props.className ?
                        `m3 m3-ripple-domain ${props.className}`.trimEnd() :
                        "m3 m3-ripple-domain";

        const start = useCallback((event : any, cb : (state : boolean) => void) : void => {

            clicked.current = true;
            cb(clicked.current);

            const rippleDomainChar = rippleDomain.current ? rippleDomain.current.getBoundingClientRect() : {
                width: 0,
                height: 0,
                left: 0,
                top: 0,
            }

            let rippleX : number = !central ? event.clientX - rippleDomainChar.left : rippleDomainChar.width / 2,
                rippleY : number = !central ? event.clientY - rippleDomainChar.top : rippleDomainChar.height / 2,
                rippleSizeX : number = Math.max(Math.abs(rippleDomainChar.width - rippleX), rippleX) * 2 + 2,
                rippleSizeY : number = Math.max(Math.abs(rippleDomainChar.height - rippleY), rippleY) * 2 + 2,
                rippleS : number = (rippleSizeX ** 2 + rippleSizeY ** 2) ** 0.5;

            setRipples((prevRipples : Array<JSX.Element>) => {
                    if(prevRipples.length === 0){
                        return [
                            <Ripple rippleX={rippleX}
                                    rippleY={rippleY}
                                    rippleS={rippleS}
                                    key={uniqueKey.current}
                                    lifetime={TIMEOUT}/>
                        ]
                    } else {
                        let old = [...prevRipples];
                        old.push(
                            <Ripple rippleX={rippleX}
                                    rippleY={rippleY}
                                    rippleS={rippleS}
                                    key={uniqueKey.current}
                                    lifetime={TIMEOUT}/>
                        )
                        return old;
                    }
                }
            )

            uniqueKey.current += 1;

        }, []);

        const stop = useCallback((_event : any, cb : (state : boolean) => void) => {

            clicked.current = false;
            cb(clicked.current);

            setRipples((prevRipples : Array<JSX.Element>) => {
                if(prevRipples.length > 0) {
                    let old = [...prevRipples];
                    old.shift();
                    return old;
                }
                return prevRipples
            });

        },[]);

        useImperativeHandle(ref, () => ({
            start,
            stop,
        }), [start, stop]);

        return (
            <span className={classes}
                  id={uniqueId}
                  ref={rippleDomain}>
                <rippleAreaContext.Provider value={clicked.current}>
                    <Ripples>
                        {ripples}
                    </Ripples>
                </rippleAreaContext.Provider>
            </span>
        );

    }

)

export {rippleAreaContext, RippleArea};