import { newGuid } from "@insite/client-framework/Common/StringHelpers";
import { loadPage, UpdateFieldParameter } from "@insite/client-framework/Store/Data/Pages/PagesActionCreators";
import { getCurrentPage } from "@insite/client-framework/Store/Data/Pages/PageSelectors";
import { createContextualIds, prepareFields } from "@insite/client-framework/Store/Data/Pages/PrepareFields";
import { AllowedContexts } from "@insite/client-framework/Types/AllowedContexts";
import { ItemProps } from "@insite/client-framework/Types/PageProps";
import WidgetProps, { WidgetPropsWithChildren } from "@insite/client-framework/Types/WidgetProps";
import { ToastContextData } from "@insite/mobius/Toast/ToasterContext";
import { getWidgetDefinition } from "@insite/shell/DefinitionLoader";
import { isSharedContentOpened, updatePageOnSite } from "@insite/shell/Store/Data/Pages/PagesHelpers";
import ShellState from "@insite/shell/Store/ShellState";
import ShellThunkAction, { ShellDispatch } from "@insite/shell/Store/ShellThunkAction";
import { TS } from "@insite/shell/TS";
import { push } from "redux-first-history";

export * from "@insite/client-framework/Store/Data/Pages/PagesActionCreators";

export const updateField =
    (parameter: UpdateFieldParameter): ShellThunkAction =>
    (dispatch, getState) => {
        dispatch({
            type: "Data/Pages/UpdateField",
            ...parameter,
        });

        updatePageOnSite(getState());
    };

export const removeWidget =
    (id: string, pageId: string): ShellThunkAction =>
    (dispatch, getState) => {
        dispatch({
            type: "Data/Pages/RemoveWidget",
            id,
            pageId,
        });

        updatePageOnSite(getState());
    };

export const addWidget =
    (widget: WidgetProps, index: number, pageId: string): ShellThunkAction =>
    (dispatch, getState) => {
        dispatch({
            type: "Data/Pages/AddWidget",
            widget,
            index,
            pageId,
        });

        updatePageOnSite(getState());
    };

export const copyWidgetTo =
    (
        widgetWithChildren: WidgetPropsWithChildren,
        parentId: string,
        zone: string,
        pageId: string,
        pageType: string,
        toaster: ToastContextData,
    ): ShellThunkAction =>
    (dispatch, getState) => {
        const widgetToCopy = {
            ...widgetWithChildren,
            zone,
        };

        const allWidgetsAdded = addWidgetsWithChildren(dispatch, getState, [widgetToCopy], parentId, pageId, pageType);
        if (!allWidgetsAdded) {
            toaster.addToast({
                body: TS("Some widgets were not added because they are not allowed on this page."),
                messageType: "warning",
            });
        }

        updatePageOnSite(getState());
    };

const addWidgetsWithChildren = (
    dispatch: ShellDispatch,
    getState: () => ShellState,
    widgets: WidgetPropsWithChildren[],
    parentId: string,
    pageId: string,
    pageType: string,
) => {
    let allWidgetsAdded = true;
    for (let index = 0; index < widgets.length; index++) {
        const widgetWithChildren = widgets[index];
        const { children, ...widget } = widgetWithChildren;

        const { allowedContexts } = getWidgetDefinition(widget.type);
        if (allowedContexts?.length && allowedContexts.indexOf(pageType as AllowedContexts) === -1) {
            allWidgetsAdded = false;
            continue;
        }

        const widgetCopy = {
            ...widget,
            fields: {},
            id: newGuid(),
            parentId,
            isLayout: pageType === "Layout",
        };

        const state = getState();
        const languageId = state.shellContext.languagesById[state.shellContext.currentLanguageId]!.id;
        const defaultLanguageId = state.shellContext.defaultLanguageId;
        const contextualIds = createContextualIds(
            languageId,
            defaultLanguageId,
            state.shellContext.currentDeviceType,
            [state.shellContext.currentPersonaId],
            state.shellContext.defaultPersonaId,
        );

        prepareFields(widgetCopy, languageId, defaultLanguageId, contextualIds);

        dispatch({
            type: "Data/Pages/AddWidget",
            widget: widgetCopy,
            pageId,
        });

        const allChildrenWidgetsAdded = addWidgetsWithChildren(
            dispatch,
            getState,
            children,
            widgetCopy.id,
            pageId,
            pageType,
        );
        if (!allChildrenWidgetsAdded) {
            allWidgetsAdded = false;
        }
    }

    return allWidgetsAdded;
};

export const moveWidgetTo =
    (id: string, parentId: string, zoneName: string, index: number, pageId: string): ShellThunkAction =>
    (dispatch, getState) => {
        dispatch({
            type: "Data/Pages/MoveWidgetTo",
            id,
            parentId,
            zoneName,
            index,
            pageId,
        });

        updatePageOnSite(getState());
    };

export const replaceItem =
    (item: ItemProps): ShellThunkAction =>
    (dispatch, getState) => {
        dispatch({
            type: "Data/Pages/ReplaceItem",
            item,
        });

        updatePageOnSite(getState());
    };

export const loadPageIfNeeded =
    (pageId: string, finished: () => void): ShellThunkAction =>
    (dispatch, getState) => {
        if (getCurrentPage(getState()).id !== pageId) {
            dispatch(
                loadPage(
                    {
                        pathname: `/Content/Page/${pageId}`,
                        search: "",
                    },
                    undefined,
                    () => {
                        const url = isSharedContentOpened()
                            ? `/ContentAdmin/SharedContent/${pageId}`
                            : `/ContentAdmin/Page/${pageId}`;
                        dispatch(push(url));
                        finished();
                    },
                ),
            );
        } else {
            finished();
        }
    };
