import * as R from "ramda";
import {
  populateConfigurationValues,
  remapUpdatedKeys,
} from "../configurationUtils";
import { useCurrentScreenData, useTargetScreenData } from "./screen";
import {
  useLayoutConfiguration,
  usePluginConfiguration,
} from "./usePluginConfiguration";
import React from "react";

type UseConfigurationParams = {
  entry?: ZappEntry;
  component?: ZappUIComponent;
  pluginIdentifier?: string;
  pluginManifest: Manifest;
  skipDefaults: boolean;
};

const getPluginTypeFromManifest = ({
  screen,
  type,
}: Manifest): PluginType | "screen" => (screen ? "screen" : type);

const discardUndefined = (leftProp, rightProp) =>
  rightProp === null ||
  typeof rightProp === "undefined" ||
  Number.isNaN(rightProp)
    ? leftProp
    : rightProp;

export const useConfiguration = ({
  entry,
  component,
  pluginIdentifier,
  pluginManifest,
  skipDefaults,
}: UseConfigurationParams): Record<string, any> => {
  const pluginId = pluginIdentifier ?? pluginManifest.identifier;
  const pluginType = getPluginTypeFromManifest(pluginManifest);
  const targetScreenData = useTargetScreenData(entry);
  const currentScreenData = useCurrentScreenData();
  const screenData = targetScreenData || currentScreenData;

  if (!pluginId) {
    throw new Error("no plugin id");
  }

  const layoutConfiguration = useLayoutConfiguration(
    screenData,
    pluginManifest,
    {
      skipDefaults,
    }
  );

  const { styles, general, localizations, rules } = React.useMemo(() => {
    if (R.equals("screen", pluginType)) {
      const styles = layoutConfiguration.styles;
      const general = layoutConfiguration.general;
      const localizations = layoutConfiguration.localizations;
      const rules = layoutConfiguration.rules;

      return { styles, general, localizations, rules };
    } else {
      if (component) {
        const remappedStylesConfiguration = remapUpdatedKeys(
          pluginManifest,
          component
        );

        R.forEachObjIndexed((value, key) => {
          const configKey = remappedStylesConfiguration[key];

          if (configKey) {
            remappedStylesConfiguration[value] = configKey;
          }
        }, pluginManifest?.styles?.updated_keys);

        const componentRules = component?.rules;
        const localizations = component?.localizations;

        const styles = populateConfigurationValues(
          pluginManifest?.styles?.fields,
          remappedStylesConfiguration.styles,
          skipDefaults
        );

        const rules = pluginManifest?.rules?.fields
          ? populateConfigurationValues(
              pluginManifest?.rules?.fields,
              componentRules,
              skipDefaults
            )
          : null;

        return { styles, general: null, localizations, rules };
      }
    }

    return { styles: null, general: null, localizations: null, rules: null };
  }, [
    pluginType,
    component,
    layoutConfiguration,
    skipDefaults,
    pluginManifest,
  ]);

  const { configurationFields, localizations: localizationsFields } =
    usePluginConfiguration(pluginId, pluginManifest);

  const pluginConfiguration = React.useMemo(
    () => R.mergeRight(configurationFields, localizationsFields, rules),
    [configurationFields, localizationsFields]
  );

  const screenConfiguration = React.useMemo(
    () => R.mergeAll([styles, general, localizations, rules]),
    [styles, general, localizations, rules]
  );

  return React.useMemo(
    () =>
      R.mergeDeepWith(
        discardUndefined,
        pluginConfiguration,
        screenConfiguration
      ),
    [pluginConfiguration, screenConfiguration]
  );
};
