import { logMonitor } from "./DevTools";
import { Children } from "react";
import {
	liftReducerWith as wrapReducerWithDevToolsProfiler,
	unliftStore as unwrapDevToolsStore,
	unliftState as unwrapDevToolsState,
} from "redux-devtools-instrument";
import { Reducer } from "@reduxjs/toolkit";
import { StoreEnhancer } from "@reduxjs/toolkit";

const monitorReducer = (state, action) => Children.only(logMonitor).type.update(logMonitor.props, state, action);

/**
 * For performance reasons, we want to dynamically bypass DevTools functionality when it's not in use.
 *
 * We know DevTools is in use based on Interop service's window visible or the `visibility` value in the service's config
 *
 * In order to bypass DevTools, we have to create our own store enhancer that will initialize DevTools and then
 * dynamically choose which reducer to dispatch actions to based on what state we're in.
 *
 */
export default (function (doCreateStore) {
	return (currentReducer, preloadedState) => {
		const wrappedReducer = wrapReducerWithDevToolsProfiler(
			currentReducer,
			preloadedState,
			monitorReducer,
			{}
		) as Reducer;

		let didInit = false;

		const reducer = (wrappedState, wrappedAction) => {
			if (!didInit) {
				didInit = true;
				return wrappedReducer(wrappedState, wrappedAction);
			}

			const unwrappedAction = wrappedAction.action;
			const unwrappedState = unwrapDevToolsState(wrappedState);
			const isWindowVisible = unwrappedState && unwrappedState.root.isVisible;
			const isDevToolsAction = wrappedAction.type !== "PERFORM_ACTION" || !unwrappedAction;
			const isBecomingVisible =
				unwrappedAction && unwrappedAction.type === "root/windowVisible" && unwrappedAction.payload === true;

			if (!isDevToolsAction && !isWindowVisible && !isBecomingVisible) {
				// bypass DevTools reducer if devtools window isn't visible
				wrappedState.computedStates[wrappedState.currentStateIndex].state = currentReducer(
					unwrappedState,
					unwrappedAction
				);

				return wrappedState;
			}

			return wrappedReducer(wrappedState, wrappedAction);
		};

		const wrappedStore = doCreateStore(reducer);

		return unwrapDevToolsStore(wrappedStore, reducer as any, {});
	};
} as StoreEnhancer);
