import * as React from 'react';
import { Text, View, Switch, ScrollView, Platform } from 'react-native';
import { ButtonV1 as Button, Separator, Pressable } from '@fluentui/react-native';
import { Callout } from '@fluentui-react-native/callout';
import { CALLOUT_TESTPAGE } from '@fluentui-react-native/e2e-testing';
import { E2ECalloutTest } from './CalloutE2ETest';
import { MenuPicker } from '../Common/MenuPicker';
import { fluentTesterStyles } from '../Common/styles';
import { Test } from '../Test';
const StandardCallout = () => {
    const [showStandardCallout, setShowStandardCallout] = React.useState(false);
    const [isStandardCalloutVisible, setIsStandardCalloutVisible] = React.useState(false);
    const [openCalloutOnHoverAnchor, setOpenCalloutOnHoverAnchor] = React.useState(true);
    const [calloutHovered, setCalloutHovered] = React.useState(false);
    const [shouldSetInitialFocus, setShouldSetInitialFocus] = React.useState(true);
    const onInitialFocusChange = React.useCallback((value) => setShouldSetInitialFocus(value), []);
    const [customRestoreFocus, setCustomRestoreFocus] = React.useState(false);
    const onRestoreFocusChange = React.useCallback((value) => setCustomRestoreFocus(value), []);
    const [isBeakVisible, setIsBeakVisible] = React.useState(false);
    const onIsBeakVisibleChange = React.useCallback((value) => setIsBeakVisible(value), []);
    const [preventDismissOnKeyDown, setPreventDismissOnKeyDown] = React.useState(false);
    const [preventDismissOnClickOutside, setPreventDismissOnClickOutside] = React.useState(false);
    const [calloutDismissBehaviors, setDismissBehaviors] = React.useState([]);
    const onPreventDismissOnKeyDownChange = React.useCallback((value) => {
        setPreventDismissOnKeyDown(value);
        if (value) {
            setDismissBehaviors(calloutDismissBehaviors.concat('preventDismissOnKeyDown'));
        }
        else {
            const newDismissBehaviors = calloutDismissBehaviors.filter((value) => {
                value != 'preventDismissOnKeyDown';
            });
            setDismissBehaviors(newDismissBehaviors);
        }
    }, [calloutDismissBehaviors]);
    const onPreventDismissOnClickOutsideChange = React.useCallback((value) => {
        setPreventDismissOnClickOutside(value);
        if (value) {
            setDismissBehaviors(calloutDismissBehaviors.concat('preventDismissOnClickOutside'));
        }
        else {
            const newDismissBehaviors = calloutDismissBehaviors.filter((value) => {
                value != 'preventDismissOnClickOutside';
            });
            setDismissBehaviors(newDismissBehaviors);
        }
    }, [calloutDismissBehaviors]);
    const calloutRef = React.useRef(null);
    const calloutButtonRef = React.useRef(null);
    const redTargetRef = React.useRef(null);
    const blueTargetRef = React.useRef(null);
    const greenTargetRef = React.useRef(null);
    const decoyBtn1Ref = React.useRef(null);
    const decoyBtn2Ref = React.useRef(null);
    const [anchorRef, setAnchorRef] = React.useState(redTargetRef);
    const [hoveredTargetsCount, setHoveredTargetsCount] = React.useState(0);
    const [displayCountHoveredTargets, setDisplayCountHoveredTargets] = React.useState(0);
    const anchorRefsInfo = React.useMemo(() => {
        return {
            hoverCount: displayCountHoveredTargets,
            isCurrentAnchor: [
                openCalloutOnHoverAnchor && isStandardCalloutVisible && anchorRef == redTargetRef,
                openCalloutOnHoverAnchor && isStandardCalloutVisible && anchorRef == greenTargetRef,
                openCalloutOnHoverAnchor && isStandardCalloutVisible && anchorRef == blueTargetRef,
            ],
        };
    }, [anchorRef, displayCountHoveredTargets, isStandardCalloutVisible, openCalloutOnHoverAnchor]);
    // Use a timer to update the targets count and avoid jittery updates of counts on-screen
    React.useLayoutEffect(() => {
        const timer = setTimeout(() => {
            setDisplayCountHoveredTargets(hoveredTargetsCount);
        }, 50);
        return () => clearTimeout(timer);
    }, [hoveredTargetsCount]);
    React.useLayoutEffect(() => {
        // The callout may be dismissed by multiple mechanisms, depending on its active invocation
        // mechanisms.  In each of those dismissal routes, we use this function to reset the callout's
        // state universally.
        if (!showStandardCallout) {
            setIsStandardCalloutVisible(false);
            setCalloutHovered(false);
        }
    }, [showStandardCallout]);
    const toggleShowStandardCallout = React.useCallback(() => {
        setShowStandardCallout(!showStandardCallout);
    }, [showStandardCallout]);
    // Set up a LayoutEffect for hover callout mechanics including:
    //   the toggle switch for hover callout behavior
    //   multiple hover targets (i.e. the callout and its anchor)
    //   a dismissal timer for closing the callout with no targets hovered
    React.useLayoutEffect(() => {
        if (!openCalloutOnHoverAnchor) {
            setShowStandardCallout(false);
        }
        else if (openCalloutOnHoverAnchor && hoveredTargetsCount > 0) {
            setShowStandardCallout(true);
        }
        else {
            const timer = setTimeout(() => {
                setShowStandardCallout(false);
            }, 2000);
            return () => clearTimeout(timer);
        }
        return undefined;
    }, [openCalloutOnHoverAnchor, hoveredTargetsCount]);
    const updateCalloutTargetsHoverState = React.useCallback((show, hoverAnchorRef) => {
        if (hoverAnchorRef !== undefined && hoverAnchorRef !== anchorRef) {
            return;
        }
        setHoveredTargetsCount(hoveredTargetsCount + (show ? 1 : -1));
    }, [anchorRef, hoveredTargetsCount, setHoveredTargetsCount]);
    const calloutHoveredCallback = React.useCallback((isHovered) => {
        updateCalloutTargetsHoverState(isHovered, undefined);
        setCalloutHovered(isHovered);
    }, [updateCalloutTargetsHoverState]);
    const toggleCalloutRef = React.useCallback(() => {
        // Cycle the target ref between the RGB target views
        setAnchorRef(anchorRef === redTargetRef ? greenTargetRef : anchorRef === greenTargetRef ? blueTargetRef : redTargetRef);
    }, [anchorRef]);
    const switchTargetRefOrRect = React.useCallback(() => {
        // Switch between RGB views or a fixed anchor
        setAnchorRef(anchorRef === redTargetRef || anchorRef === greenTargetRef || anchorRef == blueTargetRef ? undefined : redTargetRef);
    }, [anchorRef]);
    React.useEffect(() => {
        if (!showStandardCallout && anchorRef === undefined) {
            setAnchorRef(redTargetRef);
        }
    }, [anchorRef, setAnchorRef, showStandardCallout]);
    const onShowStandardCallout = React.useCallback(() => {
        setIsStandardCalloutVisible(true);
    }, []);
    const onDismissStandardCallout = React.useCallback(() => {
        // setting the internal state to false will instigate unmounting the
        // zombie Callout control.
        setShowStandardCallout(false);
    }, []);
    const onShiftFocusToCallout = React.useCallback(() => {
        calloutRef?.current.focusWindow();
    }, [calloutRef]);
    const onShiftFocusToCalloutButton = React.useCallback(() => {
        calloutButtonRef?.current?.focus?.();
    }, [calloutButtonRef]);
    const onShiftFocusToPage = React.useCallback(() => {
        calloutRef?.current.blurWindow();
    }, [calloutRef]);
    const onRestoreFocusStandardCallout = React.useCallback((restoreFocusEvent) => {
        if (restoreFocusEvent?.nativeEvent?.containsFocus) {
            decoyBtn1Ref?.current?.focus?.();
        }
        else {
            decoyBtn2Ref?.current?.focus?.();
        }
    }, [decoyBtn1Ref, decoyBtn2Ref]);
    const colorDefault = 'default';
    const colorSelections = [colorDefault, 'red', 'green', 'blue'];
    const menuPickerColorCollection = colorSelections.map((color) => {
        return {
            label: color,
            value: color,
        };
    });
    const [selectedBackgroundColor, setSelectedBackgroundColor] = React.useState(undefined);
    const [selectedBorderColor, setSelectedBorderColor] = React.useState(undefined);
    const borderWidthDefault = Platform.OS === 'macos' ? '0' : '1';
    const borderWidthSelections = ['0', '1', '2', '4', '10'];
    const menuPickerBorderWidthCollection = borderWidthSelections.map((width) => {
        return {
            label: width,
            value: width,
        };
    });
    const borderRadiusDefault = '5';
    const borderRadiusSelections = ['0', '5', '7', '15'];
    const menuPickerBorderRadiusCollection = borderRadiusSelections.map((width) => {
        return {
            label: width,
            value: width,
        };
    });
    const [selectedBorderWidth, setSelectedBorderWidth] = React.useState(undefined);
    const [selectedBorderRadius, setSelectedBorderRadius] = React.useState(undefined);
    const [showScrollViewCallout, setShowScrollViewCalout] = React.useState(false);
    const [scrollviewContents, setScrollviewContents] = React.useState([1, 2, 3]);
    const removeButton = React.useCallback(() => {
        const tempArray = scrollviewContents;
        tempArray.pop();
        setScrollviewContents([...tempArray]);
    }, [setScrollviewContents, scrollviewContents]);
    const addButton = React.useCallback(() => {
        setScrollviewContents((arr) => [...arr, 1]);
    }, [setScrollviewContents]);
    const calloutTargetOrAnchor = {};
    if (anchorRef) {
        calloutTargetOrAnchor.target = anchorRef;
    }
    else {
        calloutTargetOrAnchor.anchorRect = { screenX: 50, screenY: 50, width: 1, height: 1 };
    }
    return (React.createElement(View, null,
        React.createElement(View, { style: { flexDirection: 'row', paddingVertical: 5 } },
            React.createElement(View, { style: { flexDirection: 'column', paddingHorizontal: 5 } },
                React.createElement(View, { style: { flexDirection: 'row' } },
                    React.createElement(Switch, { value: openCalloutOnHoverAnchor, onValueChange: setOpenCalloutOnHoverAnchor }),
                    React.createElement(Text, null, "Show Callout On Hover Anchor")),
                React.createElement(View, { style: { flexDirection: 'row' } },
                    React.createElement(Switch, { value: shouldSetInitialFocus, onValueChange: onInitialFocusChange }),
                    React.createElement(Text, null, "Set Initial Focus")),
                React.createElement(View, { style: { flexDirection: 'row' } },
                    React.createElement(Switch, { value: customRestoreFocus, onValueChange: onRestoreFocusChange }),
                    React.createElement(Text, null, "Customize Restore Focus")),
                React.createElement(View, { style: { flexDirection: 'row' } },
                    React.createElement(Switch, { value: isBeakVisible, onValueChange: onIsBeakVisibleChange }),
                    React.createElement(Text, null, "Beak Visible")),
                React.createElement(View, { style: { flexDirection: 'row' } },
                    React.createElement(Switch, { value: preventDismissOnKeyDown, onValueChange: onPreventDismissOnKeyDownChange }),
                    React.createElement(Text, null, "Prevent Dismiss On Key Down")),
                React.createElement(View, { style: { flexDirection: 'row' } },
                    React.createElement(Switch, { value: preventDismissOnClickOutside, onValueChange: onPreventDismissOnClickOutsideChange }),
                    React.createElement(Text, null, "Prevent Dismiss On Click Outside")),
                React.createElement(View, { style: { flexDirection: 'row' } },
                    React.createElement(Switch, { value: showScrollViewCallout, onValueChange: setShowScrollViewCalout }),
                    React.createElement(Text, null, "Enable ScrollView Callout")),
                React.createElement(MenuPicker, { prompt: "Background Color", selected: selectedBackgroundColor || colorDefault, onChange: (color) => setSelectedBackgroundColor(color === colorDefault ? undefined : color), collection: menuPickerColorCollection }),
                React.createElement(MenuPicker, { prompt: "Border Color", selected: selectedBorderColor || colorDefault, onChange: (color) => setSelectedBorderColor(color === colorDefault ? undefined : color), collection: menuPickerColorCollection }),
                React.createElement(MenuPicker, { prompt: "Border Width", selected: selectedBorderWidth || borderWidthDefault, onChange: (color) => setSelectedBorderWidth(color === colorDefault ? undefined : color), collection: menuPickerBorderWidthCollection }),
                React.createElement(MenuPicker, { prompt: "Border Radius", selected: selectedBorderRadius || borderRadiusDefault, onChange: (radius) => setSelectedBorderRadius(radius === borderRadiusDefault ? undefined : radius), collection: menuPickerBorderRadiusCollection })),
            React.createElement(Separator, { vertical: true }),
            React.createElement(View, { style: { flexDirection: 'column', paddingHorizontal: 5 } },
                React.createElement(Button, { onClick: toggleShowStandardCallout, disabled: openCalloutOnHoverAnchor }, (openCalloutOnHoverAnchor ? 'Hover Color Anchor ' : 'Press Here ') + 'for Callout'),
                React.createElement(Text, null,
                    React.createElement(Text, null, "Visibility: "),
                    isStandardCalloutVisible ? React.createElement(Text, { style: { color: 'green' } }, "Visible") : React.createElement(Text, { style: { color: 'red' } }, "Not Visible"))),
            React.createElement(Separator, { vertical: true }),
            React.createElement(View, { style: { flexDirection: 'column', paddingHorizontal: 5 } },
                React.createElement(Pressable, { onHoverIn: () => updateCalloutTargetsHoverState(true, redTargetRef), onHoverOut: () => updateCalloutTargetsHoverState(false, redTargetRef) },
                    React.createElement(View, { ref: redTargetRef, style: { height: 40, width: 40, backgroundColor: 'red', padding: 5 } }, anchorRefsInfo.isCurrentAnchor[0] && React.createElement(Text, null, anchorRefsInfo.hoverCount))),
                React.createElement(Pressable, { onHoverIn: () => updateCalloutTargetsHoverState(true, greenTargetRef), onHoverOut: () => updateCalloutTargetsHoverState(false, greenTargetRef) },
                    React.createElement(View, { ref: greenTargetRef, style: { height: 40, width: 40, backgroundColor: 'green', padding: 5 } }, anchorRefsInfo.isCurrentAnchor[1] && React.createElement(Text, null, anchorRefsInfo.hoverCount))),
                React.createElement(Pressable, { onHoverIn: () => updateCalloutTargetsHoverState(true, blueTargetRef), onHoverOut: () => updateCalloutTargetsHoverState(false, blueTargetRef) },
                    React.createElement(View, { ref: blueTargetRef, style: { height: 40, width: 40, backgroundColor: 'blue', padding: 5 } }, anchorRefsInfo.isCurrentAnchor[2] && React.createElement(Text, { style: { color: 'white' } }, anchorRefsInfo.hoverCount))))),
        React.createElement(Separator, null),
        React.createElement(View, { style: { paddingVertical: 5 } },
            React.createElement(Button, { componentRef: decoyBtn1Ref, onClick: onShiftFocusToCallout }, 'Custom reFocus w/ focus in Callout'),
            React.createElement(Button, { componentRef: decoyBtn2Ref, onClick: onShiftFocusToCalloutButton }, 'Custom reFocus w/o focus in Callout')),
        showStandardCallout && (React.createElement(Callout, { componentRef: calloutRef, ...{
                doNotTakePointerCapture: openCalloutOnHoverAnchor ?? undefined,
                ...calloutTargetOrAnchor,
                onDismiss: onDismissStandardCallout,
                onShow: onShowStandardCallout,
                ...(customRestoreFocus && { onRestoreFocus: onRestoreFocusStandardCallout }),
                accessibilityLabel: 'Standard Callout',
                setInitialFocus: shouldSetInitialFocus,
                isBeakVisible: isBeakVisible,
                ...(selectedBorderColor && { borderColor: selectedBorderColor }),
                ...(selectedBackgroundColor && { backgroundColor: selectedBackgroundColor }),
                ...(selectedBorderWidth && { borderWidth: parseInt(selectedBorderWidth) }),
                ...(selectedBorderRadius && { borderRadius: parseInt(selectedBorderRadius) }),
                ...(calloutDismissBehaviors && { dismissBehaviors: calloutDismissBehaviors }),
            } },
            React.createElement(Pressable, { onHoverIn: () => calloutHoveredCallback(true), onHoverOut: () => calloutHoveredCallback(false) }, showScrollViewCallout ? (React.createElement(View, { style: fluentTesterStyles.scrollViewContainer },
                React.createElement(ScrollView, { contentContainerStyle: fluentTesterStyles.scrollViewStyle, showsVerticalScrollIndicator: true },
                    React.createElement(Button, { onClick: toggleCalloutRef }, 'click to change anchor'),
                    React.createElement(Button, { onClick: switchTargetRefOrRect }, 'click to switch between anchor and rect'),
                    React.createElement(Button, { style: fluentTesterStyles.testListItem, onClick: addButton }, 'Click to add a button'),
                    React.createElement(Button, { style: fluentTesterStyles.testListItem, onClick: removeButton }, 'Click to remove a button'),
                    scrollviewContents.map((value) => {
                        return (React.createElement(Button, { key: value, style: fluentTesterStyles.testListItem }, 'Button'));
                    })))) : (
            //else
            React.createElement(View, { style: { padding: 20, backgroundColor: calloutHovered ? 'lightgreen' : 'pink' } },
                React.createElement(Button, { onClick: toggleCalloutRef }, 'click to change anchor'),
                React.createElement(Button, { onClick: onShiftFocusToCalloutButton }, 'focus last button'),
                React.createElement(Button, { onClick: switchTargetRefOrRect }, 'click to switch between anchor and rect'),
                React.createElement(Button, { componentRef: calloutButtonRef, onClick: onShiftFocusToPage }, 'Click to invoke blur()'))))))));
};
const CustomCallout = () => {
    const [showCustomizedCallout, setShowCustomizedCallout] = React.useState(false);
    const [isCustomizedCalloutVisible, setIsCustomizedCalloutVisible] = React.useState(false);
    const toggleShowCustomizedCallout = React.useCallback(() => {
        setShowCustomizedCallout(!showCustomizedCallout);
        // Unmounting a callout does not invoke onDismiss; onDismiss is only invoked
        // for dismissals generated by the native app.  When toggling to 'show',
        // the isVisible state will be corrected to 'true' by the onShow callback.
        setIsCustomizedCalloutVisible(false);
    }, [showCustomizedCallout, setIsCustomizedCalloutVisible, setShowCustomizedCallout]);
    const onShowCustomizedCallout = React.useCallback(() => {
        setIsCustomizedCalloutVisible(true);
    }, [setIsCustomizedCalloutVisible]);
    const onDismissCustomizedCallout = React.useCallback(() => {
        setIsCustomizedCalloutVisible(false);
        // setting the internal state to false will instigate unmounting the
        // zombie Callout control.
        setShowCustomizedCallout(false);
    }, [setIsCustomizedCalloutVisible, setShowCustomizedCallout]);
    const myRect = { screenX: 10, screenY: 10, width: 100, height: 100 };
    return (React.createElement(View, null,
        React.createElement(View, { style: { flexDirection: 'column', paddingVertical: 5 } },
            React.createElement(Button, { onClick: toggleShowCustomizedCallout }, 'Press for Callout'),
            React.createElement(Text, { selectable: true },
                React.createElement(Text, null, "Visibility: "),
                isCustomizedCalloutVisible ? React.createElement(Text, { style: { color: 'green' } }, "Visible") : React.createElement(Text, { style: { color: 'red' } }, "Not Visible"))),
        showCustomizedCallout && (React.createElement(Callout, { anchorRect: myRect, onDismiss: onDismissCustomizedCallout, onShow: onShowCustomizedCallout, accessibilityLabel: "Customized Callout", accessibilityRole: "alert", accessibilityOnShowAnnouncement: "Be informed that a customized callout has been opened." },
            React.createElement(View, { style: { padding: 20, borderWidth: 2, borderColor: 'black' } },
                React.createElement(Text, null, "just some text so it does not take focus and is not empty."))))));
};
const calloutSections = [
    {
        name: 'Standard Usage',
        testID: CALLOUT_TESTPAGE,
        component: StandardCallout,
    },
    {
        name: 'Customized Usage',
        component: CustomCallout,
    },
];
const e2eSections = [
    {
        name: 'E2E Testing Callout',
        component: E2ECalloutTest,
    },
];
export const CalloutTest = () => {
    const status = {
        win32Status: 'Production',
        uwpStatus: 'Backlog',
        iosStatus: 'N/A',
        macosStatus: 'Production',
        androidStatus: 'N/A',
    };
    const description = 'A callout is an anchored tip that can be used to teach people or guide them through the app without blocking them.';
    return React.createElement(Test, { name: "Callout Test", description: description, sections: calloutSections, status: status, e2eSections: e2eSections });
};
//# sourceMappingURL=CalloutTest.js.map