import React from 'react';

import {DEFAULT_NAMESPACE} from '@gravity-ui/dashkit/helpers';
import {useDispatch, useSelector} from 'react-redux';
import type {WidgetType} from 'shared';
import {DashTabItemType, EntryScope, Feature} from 'shared';
import {useEffectOnce} from 'ui';
import {DialogEditItem, isDialogEditItemType} from 'ui/components/DialogEditItem/DialogEditItem';
import type {DatalensGlobalState} from 'ui/index';
import {registry} from 'ui/registry';
import {isEnabledFeature} from 'ui/utils/isEnabledFeature';
import type {ValuesType} from 'utility-types';

import {DIALOG_TYPE} from '../../../../constants/dialogs';
import {selectControlDialogTheme} from '../../../../store/selectors/controlDialog';
import {changeNavigationPath, setItemData} from '../../store/actions/dashTyped';
import type {SetItemDataPayload} from '../../store/actions/dashTyped';
import {closeDialog} from '../../store/actions/dialogs/actions';
import {
    selectCurrentTabId,
    selectDashWorkbookId,
    selectEntryId,
    selectNavigationPath,
    selectOpenedItem,
    selectOpenedItemData,
    selectVisualSettings,
    selectWidgetsCurrentTab,
} from '../../store/selectors/dashTypedSelectors';

import Settings from './Settings/Settings';
import type {SettingsDrawerFormApiRef} from './Settings/SettingsDrawer';
import {SettingsDrawer} from './Settings/SettingsDrawer';
import Tabs from './Tabs/Tabs';

const DASHBOARD_FEATURES = {
    [DashTabItemType.GroupControl]: {
        enableGlobalSelectors: true,
    },
    [DashTabItemType.Control]: {
        enableGlobalSelectors: true,
    },
    [DashTabItemType.Widget]: {
        enableBackgroundColor: isEnabledFeature(Feature.EnableDashColorPickersByTheme),
    },
} as const;

// TODO: to see if dialogs with complex content will slow down due to the fact that mount/unmount is happening
// TODO: if there are noticeable lags, it will be possible to render the contents of the dialogs as available
// TODO: however, this content is not really needed by those who are not going to edit the dashboard
export function Dialogs({
    settingsDrawerApiRef,
}: {
    settingsDrawerApiRef?: React.RefObject<SettingsDrawerFormApiRef>;
} = {}) {
    const dispatch = useDispatch();

    const entryId = useSelector(selectEntryId);
    const openedDialog = useSelector<DatalensGlobalState, ValuesType<typeof DIALOG_TYPE> | null>(
        (state) => state.dash.openedDialog,
    );
    const widgetType = useSelector<DatalensGlobalState, WidgetType | undefined>(
        (state) => state.dash.openedItemWidgetType,
    );
    const openedItemId = useSelector<DatalensGlobalState, string | null>(
        (state) => state.dash.openedItemId,
    );
    const openedItemData = useSelector(selectOpenedItemData);
    const openedItem = useSelector(selectOpenedItem);
    const currentTabId = useSelector(selectCurrentTabId);
    const workbookId = useSelector(selectDashWorkbookId);
    const widgetsCurrentTab = useSelector(selectWidgetsCurrentTab);
    const navigationPath = useSelector(selectNavigationPath);
    const theme = useSelector(selectControlDialogTheme);
    const visualSettings = useSelector(selectVisualSettings);

    useEffectOnce(() => {
        return () => {
            dispatch(closeDialog());
        };
    });

    const setItemDataHandle = React.useCallback(
        (newItemData: SetItemDataPayload) => {
            dispatch(setItemData(newItemData));
        },
        [dispatch],
    );

    const closeDialogHandle = React.useCallback(() => {
        dispatch(closeDialog());
    }, [dispatch]);

    const changeNavigationPathHandle = React.useCallback(
        (newNavigationPath: string) => {
            dispatch(changeNavigationPath(newNavigationPath));
        },
        [dispatch],
    );

    if (openedDialog && isDialogEditItemType(openedDialog)) {
        const openedItemDefaults =
            openedItem && 'defaults' in openedItem ? openedItem.defaults : null;
        return (
            <DialogEditItem
                scope={EntryScope.Dash}
                entryId={entryId}
                type={openedDialog as any}
                openedItemId={openedItemId}
                openedItemNamespace={openedItem?.namespace ?? DEFAULT_NAMESPACE}
                openedItemDefaults={openedItemDefaults}
                openedItemData={openedItemData as any}
                widgetType={widgetType}
                currentTabId={currentTabId}
                workbookId={workbookId}
                widgetsCurrentTab={widgetsCurrentTab}
                closeDialog={closeDialogHandle}
                setItemData={setItemDataHandle}
                navigationPath={navigationPath}
                changeNavigationPath={changeNavigationPathHandle}
                theme={theme}
                features={DASHBOARD_FEATURES}
                commonVisualSettings={visualSettings}
            />
        );
    }

    switch (openedDialog) {
        case DIALOG_TYPE.TABS:
            return <Tabs />;
        case DIALOG_TYPE.SETTINGS:
            if (isEnabledFeature(Feature.EnableCommonChartDashSettings)) {
                return <SettingsDrawer onClose={closeDialogHandle} apiRef={settingsDrawerApiRef} />;
            }
            return <Settings />;
        case DIALOG_TYPE.SELECT_STATE: {
            const DashSelectStateDialog = registry.dash.components.get('DashSelectStateDialog');
            return <DashSelectStateDialog />;
        }
    }
    return null;
}

export default Dialogs;
