import React, { useEffect, useLayoutEffect, useState, useRef, } from "react";
import { useDebounce } from "react-use";
import { forEachObjIndexed } from "ramda";
import { useDispatch, useSelector } from "../../../store/redux-separate-context";
import { isPrintMode } from "../../dashboard/utils/parse-url";
import { selectDestroyOnHide, selectIsAsyncOnScroll, selectAlarm } from "../../global/selectors";
import { getPortalNodeStyles } from "../utils/get-portal-node-styles";
import { chartLibrariesSettings } from "../utils/chartLibrariesSettings";
import { useCommonIntersection } from "../../../hooks/use-common-intersection";
import { clearChartStateAction } from "../actions";
import { InvisibleSearchableText } from "./invisible-searchable-text";
const SCROLL_DEBOUNCE_ASYNC = 750;
const SCROLL_DEBOUNCE_SYNC = 100;
const cloneWithCanvas = (element) => {
    const cloned = element.cloneNode(true);
    const clonedCanvases = cloned.querySelectorAll("canvas");
    element.querySelectorAll("canvas")
        .forEach((oldCanvas, index) => {
        const newCanvas = clonedCanvases[index];
        const context = newCanvas.getContext("2d");
        newCanvas.width = oldCanvas.width;
        newCanvas.height = oldCanvas.height;
        if (context) {
            context.drawImage(oldCanvas, 0, 0);
        }
    });
    return cloned;
};
const shouldCleanChartStateAlways = localStorage.getItem("wipe-chart-state");
export const DisableOutOfView = ({ attributes, chartUuid, children, portalNode, }) => {
    var _a;
    /* when unmounting, clear redux state for this chart */
    const dispatch = useDispatch();
    useEffect(() => {
        return () => {
            dispatch(clearChartStateAction({ id: chartUuid }));
        };
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);
    /* separate functionality - adding custom styles to portalNode */
    const chartSettings = chartLibrariesSettings[attributes.chartLibrary];
    const [hasPortalNodeBeenStyled, setHasPortalNodeBeenStyled] = useState(false);
    const isShowingAlarmOnChart = ((_a = useSelector(selectAlarm)) === null || _a === void 0 ? void 0 : _a.chartId) === attributes.id;
    useLayoutEffect(() => {
        if (hasPortalNodeBeenStyled) {
            return;
        }
        const shouldAddSpecialHeight = isShowingAlarmOnChart
            && attributes.chartLibrary === "dygraph"
            && chartSettings.hasLegend(attributes);
        const styles = getPortalNodeStyles(attributes, chartSettings, shouldAddSpecialHeight);
        forEachObjIndexed((value, styleName) => {
            if (value) {
                portalNode.style.setProperty(styleName, value);
            }
        }, styles);
        // eslint-disable-next-line no-param-reassign
        portalNode.className = chartSettings.containerClass(attributes);
        setHasPortalNodeBeenStyled(true);
    }, [attributes, chartSettings, hasPortalNodeBeenStyled, isShowingAlarmOnChart, portalNode,
        setHasPortalNodeBeenStyled]);
    /* end of "adding custom styles to portalNode" */
    const destroyOnHide = useSelector(selectDestroyOnHide);
    const clonedChildrenRef = useRef();
    const isVisibleIntersection = useCommonIntersection(portalNode, clonedChildrenRef);
    // todo hook to scroll (observe on visible items) instead of changes in intersectionRatio
    // because intersectinnRatio maxes out on 1.0 when element is fully visible
    const isAsyncOnScroll = useSelector(selectIsAsyncOnScroll);
    const debounceTime = isAsyncOnScroll ? SCROLL_DEBOUNCE_ASYNC : SCROLL_DEBOUNCE_SYNC;
    // "should hide because of debounced scroll handler"
    const [shouldHideDebounced, setShouldHideDebounced] = useState(!isVisibleIntersection);
    useDebounce(() => {
        // start rendering, when intersectionRatio is not 0 and it hasn't changed for 1500 ms
        setShouldHideDebounced(!isVisibleIntersection);
    }, debounceTime, [isVisibleIntersection]);
    const shouldHide = isVisibleIntersection ? shouldHideDebounced : true;
    const previousIsVisibleIntersection = useRef(isVisibleIntersection);
    if (clonedChildrenRef.current
        && previousIsVisibleIntersection.current !== isVisibleIntersection) {
        previousIsVisibleIntersection.current = isVisibleIntersection;
    }
    useEffect(() => {
        if (!isPrintMode && shouldHide && shouldCleanChartStateAlways) {
            dispatch(clearChartStateAction({ id: chartUuid }));
        }
    }, [chartUuid, dispatch, shouldHide]);
    if (isPrintMode) {
        // we should show everything in this case
        return children;
    }
    if (shouldHide) {
        // todo perhaps loader should be added here to both scenarios
        if (destroyOnHide) {
            return (React.createElement(InvisibleSearchableText, { attributes: attributes }));
        }
        if (!clonedChildrenRef.current) {
            const newClonedChildren = Array.from(portalNode.children)
                .map((child) => cloneWithCanvas(child));
            const clonedChildrenContainer = document.createElement("div");
            clonedChildrenContainer.style.visibility = "hidden";
            newClonedChildren.forEach((child) => {
                clonedChildrenContainer.appendChild(child);
            });
            clonedChildrenRef.current = clonedChildrenContainer;
        }
        return (React.createElement(React.Fragment, null,
            React.createElement(InvisibleSearchableText, { attributes: attributes }),
            React.createElement("div", { ref: (nodeElement) => {
                    if (nodeElement && clonedChildrenRef.current) {
                        nodeElement.appendChild(clonedChildrenRef.current);
                    }
                } })));
    }
    if (!destroyOnHide && clonedChildrenRef.current) {
        clonedChildrenRef.current = undefined;
    }
    return children;
};
//# sourceMappingURL=disable-out-of-view.js.map