import {
    useImperativeHandle,
    useLayoutEffect,
    forwardRef,
    useEffect,
    useState,
    Fragment,
    useRef
} from "react";
import {
    ScrollView,
    Platform,
    Animated,
    Easing,
    View
} from "react-native";
import {
    type MenuButton as MenuButtonType
} from "./components/menuButton/type";
import {
    type IMenuRef
} from "./type";
import type IMenuProps from "./type";
import stylesheet, {
    useStyles
} from "./stylesheet";
import MenuButton from "./components/menuButton";
import {
    NCoreUIKitTheme,
    NCoreUIKitMenu
} from "../../core/hooks";
import type {
    RefForwardingComponent
} from "../../types";
import {
    SafeAreaView
} from "react-native-safe-area-context";
import {
    Portal
} from "../../helpers/portalize";
import Seperator from "../seperator";
import SiteLogo from "../siteLogo";
import Modal from "../modal";

const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
    isWorkWithSafeAreaView = true,
    isWorkWithAnimation = true,
    portalName = "menu-system",
    renderFooter: RenderFooter,
    renderHeader: RenderHeader,
    customBackgroundColorKey,
    isWorkWithPortal = true,
    isWorkWithModal = true,
    customBackgroundColor,
    renderHeaderSeperator,
    close: closeAction,
    glassEffect = 0,
    customLocalize,
    renderSiteLogo,
    seperatorProps,
    siteLogoProps,
    customTheme,
    isCollapse,
    modalProps,
    navigation,
    onClosed,
    onOpened,
    buttons,
    onClose,
    onOpen,
    style,
    id,
    ...props
}, ref) => {
    const {
        colors,
        spaces
    } = NCoreUIKitTheme.useContext(customTheme);

    const {
        headerContainer: headerContainerDynamicStyle,
        seperator: seperatorDynamicStyle,
        container: containerDynamicStyle
    } = useStyles({
        customBackgroundColorKey,
        customBackgroundColor,
        glassEffect,
        colors,
        spaces
    });

    const [
        isOpacityVisible,
        setIsOpacityVisible
    ] = useState(false);

    const [
        measures,
        setMeasures
    ] = useState<null | number>(null);

    const [
        isActive,
        setIsActive
    ] = useState(false);

    const animatedX = useRef(new Animated.Value(0)).current;

    useImperativeHandle(
        ref,
        () => ({
            close,
            open
        }),
        []
    );

    useEffect(() => {
        if(measures !== null) {
            animatedX.setValue(measures * -1);

            if(!isOpacityVisible) setIsOpacityVisible(true);

            if(isActive) setIsActive(false);
        }
    }, [
        measures
    ]);

    useEffect(() => {
        if(isCollapse !== undefined) {
            if(isCollapse) {
                setIsActive(isCollapse);
            } else {
                if(onClose) onClose({
                    id
                });

                if(isWorkWithAnimation) {
                    closeAnimation(() => setIsActive(isCollapse));
                } else {
                    animatedX.setValue(measures! * -1);

                    setIsActive(isCollapse);

                    if(onClosed) onClosed({
                        id
                    });
                }
            }
        }
    }, [
        isCollapse
    ]);

    useLayoutEffect(() => {
        if(isActive && isOpacityVisible) {
            if(onOpen) onOpen({
                id
            });

            if(isWorkWithAnimation) {
                openAnimation();
            } else {
                animatedX.setValue(0);

                if(onOpened) onOpened({
                    id
                });
            }
        }
    }, [
        isOpacityVisible,
        isActive
    ]);

    const open = () => {
        setIsActive(true);
    };

    const close = () => {
        if(onClose) onClose({
            id
        });

        if(isWorkWithAnimation) {
            closeAnimation(() => setIsActive(false));
        } else {
            animatedX.setValue(measures! * -1);

            setIsActive(false);

            if(onClosed) onClosed({
                id
            });
        }
    };

    const openAnimation = () => {
        Animated.timing(animatedX, {
            useNativeDriver: Platform.OS !== "web",
            easing: Easing.linear,
            duration: 300,
            toValue: 0
        }).start(({
            finished
        }) => {
            if(finished) {
                if(onOpened) onOpened({
                    id
                });
            }
        });
    };

    const closeAnimation = (callback?: () => void) => {
        Animated.timing(animatedX, {
            useNativeDriver: Platform.OS !== "web",
            toValue: measures! * -1,
            easing: Easing.linear,
            duration: 300
        }).start(({
            finished
        }) => {
            if(finished) {
                if(callback) callback();

                if(onClosed) onClosed({
                    id
                });
            }
        });
    };

    const updateMenuButtonCollabs = ({
        depthMap,
        status
    }: {
        depthMap: Array<number>;
        status: boolean;
    }) => {
        const state = NCoreUIKitMenu.get({
            id
        });

        if(!state) {
            return;
        }

        const recursivelyCatch = (item: Array<MenuButtonType>, index = 0): Array<MenuButtonType> => {
            const tIndex = depthMap[index];

            return item.map((c_item, c_index) => {
                if(c_index !== tIndex) {
                    return c_item;
                }

                if(index === depthMap.length - 1) {
                    return {
                        ...c_item,
                        isCollapse: status
                    };
                }

                return {
                    ...c_item,
                    subButtons: recursivelyCatch(c_item.subButtons as Array<MenuButtonType>, index + 1)
                };
            });
        };

        const newButtons = recursivelyCatch(state.buttons);

        state.buttons = newButtons;

        NCoreUIKitMenu.update({
            menuData: state,
            id: id
        });
    };

    const renderHeader = () => {
        if(RenderHeader) {
            return <RenderHeader/>;
        }

        return <View
            style={[
                stylesheet.headerContainer,
                headerContainerDynamicStyle
            ]}
        >
            {
                renderSiteLogo ?
                    renderSiteLogo()
                :
                    <SiteLogo
                        customLocalize={customLocalize}
                        customTheme={customTheme}
                        {...siteLogoProps}
                    />
            }
            {
                renderHeaderSeperator ?
                    renderHeaderSeperator()
                :
                    <Seperator
                        {...seperatorProps}
                        style={[
                            seperatorProps?.style,
                            stylesheet.seperator,
                            seperatorDynamicStyle
                        ]}
                        length="100%"
                    />
            }
        </View>;
    };

    const renderButtons = () => {
        if(!buttons || !buttons.length) {
            return null;
        }

        return buttons.map((buttonItem, buttonIndex) => {
            return <MenuButton
                updateMenuButtonCollabs={updateMenuButtonCollabs}
                key={`menu-button-${id}-${buttonIndex}`}
                closeAction={closeAction}
                buttonIndex={buttonIndex}
                buttonItem={buttonItem}
                navigation={navigation}
                depthMap={[
                    buttonIndex
                ]}
                id={id}
            />;
        });
    };

    const renderFooter = () => {
        if(!RenderFooter) {
            return null;
        }

        return <RenderFooter/>;
    };

    const renderSafeAreaContext = () => {
        if(!isWorkWithSafeAreaView) {
            return <Fragment>
                {renderHeader()}
            </Fragment>;
        }

        return <SafeAreaView
            style={[
                stylesheet.safeAreaView
            ]}
        >
            {renderHeader()}
            <ScrollView
                showsHorizontalScrollIndicator={false}
                showsVerticalScrollIndicator={false}
                contentContainerStyle={[
                    stylesheet.contentContainer
                ]}
                style={[
                    stylesheet.content
                ]}
            >
                {renderButtons()}
            </ScrollView>
            {renderFooter()}
        </SafeAreaView>;
    };

    const renderContent = () => {
        return <Animated.View
            {...props}
            onLayout={(event) => {
                const width = event.nativeEvent.layout.width;

                setMeasures(width);
            }}
            style={[
                style,
                stylesheet.container,
                containerDynamicStyle,
                {
                    opacity: isOpacityVisible ? 1 : 0,
                    transform: [
                        {
                            translateX: animatedX
                        }
                    ]
                }
            ]}
        >
            {renderSafeAreaContext()}
        </Animated.View>;
    };

    if(isWorkWithModal && measures !== null) {
        return <Modal
            {...modalProps}
            isWorkWithPortal={isWorkWithPortal}
            isOverlayVisible={isOpacityVisible}
            onOverlayPress={() => {
                close();
            }}
            portalName={portalName}
            isActive={isActive}
            id="menu-modal"
        >
            {renderContent()}
        </Modal>;
    }

    if(isWorkWithPortal && measures !== null) {
        return <Portal
            name={portalName}
        >
            {renderContent()}
        </Portal>;
    }

    return renderContent();
};
export default forwardRef(Menu);
