import { Text, TouchableOpacity, View } from "react-native";
import Card, { MyNotifyCard } from "../../Components/Card";
import {
  AppContext,
  AppSelectedUserDevice,
  AppStyles,
  Constants,
  GetDevice,
  VibrateShort,
} from "../../utils";
import { useCallback, useContext, useState } from "react";
import MyDropdown from "../../Components/Dropdown";
import MyIcon from "../../Components/Icon";
import { useTranslation } from "react-i18next";
import MyResult from "../../Components/Result";
import { MyTextButton } from "../../Components/Button";
import { useFocusEffect } from "@react-navigation/native";
import { Divider } from "../../Components/Divider";
import { MyColorSwatch } from "../../Components/ColorPicker";
import { MyDotsModal } from "../../Components/Modal";
import DraggableFlatList, {
  ScaleDecorator,
} from "react-native-draggable-flatlist";

export default function SceneView({ navigation }) {
  const appContext = useContext(AppContext);
  const { t } = useTranslation();

  const [device, setDevice] = useState();

  const getSelectedDeviceSceneName = () => {
    let scene;

    if (device.selectedScene !== "") {
      scene = appContext.deviceScenes.find(
        (s) => s.sceneId === device.selectedScene
      );
    }

    return scene === undefined
      ? t("screens.device.scenes.dropdownSceneSelection.noSceneSelected")
      : scene.name;
  };

  useFocusEffect(
    useCallback(() => {
      setDevice(GetDevice(appContext.devices));

      if (device !== undefined) {
        navigation.setOptions({
          headerRight: () =>
            device.selectedScene !== "" ? (
              <MyDotsModal
                modalData={[
                  {
                    icon: "pencil",
                    label: t(
                      "screens.device.scenes.modalDotsScene.changeSceneName"
                    ),
                    onPress: () =>
                      navigation.navigate("modalUpdateSceneName", {
                        deviceSelectedScene: device.selectedScene,
                        sceneName: getSelectedDeviceSceneName(),
                      }),
                  },
                  {
                    icon: "trash-can",
                    label: t(
                      "screens.device.scenes.modalDotsScene.deleteScene"
                    ),
                    onPress: () => {
                      appContext.setDeviceScenes((scenes) =>
                        scenes.filter(
                          (scene) =>
                            scene.sceneId !==
                            GetDevice(appContext.devices).selectedScene
                        )
                      );

                      appContext.setDevices((arr) => {
                        const newArr = [...arr];

                        const foundDeviceIndex = arr.findIndex(
                          (d) => d.id === AppSelectedUserDevice.current.id
                        );

                        if (foundDeviceIndex !== -1) {
                          newArr[foundDeviceIndex].selectedScene = "";

                          appContext.setDeviceSceneActions((actions) =>
                            actions.filter(
                              (action) =>
                                action.sceneId !==
                                newArr[foundDeviceIndex].selectedScene
                            )
                          );
                        }

                        return newArr;
                      });
                    },
                  },
                ]}
              />
            ) : null,
        });
      }
    }, [device])
  );

  if (device === undefined) return <></>;

  const deviceSceneActions = appContext.deviceSceneActions.filter(
    (a) => a.sceneId === device.selectedScene
  );

  const DropdownCard = () => {
    return (
      <Card>
        <MyDropdown
          label={t("screens.device.scenes.dropdownSceneSelection.label")}
          onPress={() =>
            navigation.navigate("modalChooseScene", {
              device: { selectedScene: device.selectedScene },
            })
          }
          selectedItemLabel={getSelectedDeviceSceneName()}
        />
      </Card>
    );
  };

  const lastSceneAction = deviceSceneActions[deviceSceneActions.length - 1];

  const NotifyCard = () => {
    // TODO: API show notify card if there are some problems with the esp
    return (
      <MyNotifyCard
        iconName="connection"
        notifyTitle={"Netzteil überprüfen"}
        notifyDescription={
          "Bitte überprüfen Sie, ob das korrekte Netzteil verwendet wurde."
        }
        onClose={() => console.log("closed notify")}
      />
    );
  };

  return (
    <>
      {device.selectedScene === "" ? (
        <>
          <NotifyCard />
          <DropdownCard />

          <MyResult
            text={t("screens.device.scenes.infoNoSceneSelected")}
            iconName={"selection-search"}
          />
        </>
      ) : (
        <DraggableFlatList
          data={deviceSceneActions}
          onDragEnd={({ data }) =>
            // TODO: api: save sorting new order
            appContext.setDeviceSceneActions((arr) => {
              let newArr = [...arr];

              newArr = arr.filter(
                (a) => a.sceneId !== deviceSceneActions[0].sceneId
              );

              data.forEach((item) => newArr.push(item));

              return newArr;
            })
          }
          keyExtractor={(item) => item.actionId}
          ListHeaderComponent={
            <View style={{ marginBottom: 10 }}>
              <NotifyCard />

              <DropdownCard />
            </View>
          }
          ListEmptyComponent={
            <MyResult
              text={t("screens.device.scenes.infoNoActionsAvailableInScene")}
              iconName={"selection-search"}
            />
          }
          ListFooterComponent={
            <>
              {lastSceneAction?.type === Constants.actionType.stop && (
                <ActionListItem
                  drag={false}
                  navigation={navigation}
                  device={device}
                  item={lastSceneAction}
                />
              )}

              <MyTextButton
                title={t("screens.device.scenes.buttonAddAction")}
                styleContainer={[
                  {
                    alignItems: "center",
                    marginTop: 10,
                  },
                  AppStyles.appBottom,
                ]}
                style={{ padding: 8 }}
                actionColor={
                  deviceSceneActions === undefined ||
                  deviceSceneActions.length === 0
                }
                onPress={() =>
                  navigation.navigate("modalAddSceneAction", {
                    deviceFirmwareVersion: device.firmware.version,
                  })
                }
                iconName="plus-circle-outline"
                disabled={lastSceneAction?.type === Constants.actionType.stop}
              />
            </>
          }
          renderItem={({ item, drag }) => {
            // the item for stop will be rendered on the footer of the FlatList to prevent dragging other actions below the stop
            if (item.type === Constants.actionType.stop) {
              return null;
            }

            return (
              <ScaleDecorator>
                <ActionListItem
                  drag={drag}
                  navigation={navigation}
                  device={device}
                  item={item}
                />
              </ScaleDecorator>
            );
          }}
          onRelease={VibrateShort}
        />
      )}
    </>
  );
}

function ActionListItem({ drag, navigation, device, item }) {
  const appContext = useContext(AppContext);
  const { t } = useTranslation();

  let navigateTo;
  let navigateToOptions = {
    deviceFirmwareVersion: device.firmware.version,
    action: item,
  };
  let itemModeList = [];
  let adjustments = [];

  const ListItem = ({ text, children }) => {
    return (
      <View style={{ flexDirection: "row", alignItems: "center" }}>
        <Text style={{ color: appContext.appTheme.textSecondary }}>{text}</Text>
        {children}
      </View>
    );
  };

  const getAnimationText = (animationInOrOutList, itemId, itemAdjustment) => {
    const usedAnimation = animationInOrOutList.find((lA) => lA.id === itemId);

    return `${usedAnimation.name[appContext.appLanguage]} (${
      itemAdjustment[usedAnimation.adjustment.variableName]
    }${usedAnimation.adjustment.unitOfMeasurement[appContext.appLanguage]})`;
  };

  const ListItemTitle = () => {
    let title = "???";

    if (item.type === Constants.actionType.wait) {
      title = t("screens.device.scenes.modalAddSceneAction.actions.wait");
    } else if (item.type === Constants.actionType.stop) {
      title = t("screens.device.scenes.modalAddSceneAction.actions.stop");
    } else if (item.modeId !== "") {
      title = itemModeList.find((m) => m.id === item.modeId).name[
        appContext.appLanguage
      ];
    }

    return (
      <Text
        style={{
          color: appContext.appTheme.colors.primary,
        }}
      >
        {title}
      </Text>
    );
  };

  switch (item.type) {
    case Constants.actionType.layers:
      navigateTo = "modalLightsEditAction";
      navigateToOptions.actionType = Constants.actionType.layers;
      itemModeList = appContext.deviceFirmwareModes.lightModes;

      if (item.modeAdjustments.layers !== undefined) {
        const layerGrammarForm =
          item.modeAdjustments.layers.length > 1
            ? t(
                "screens.device.scenes.sceneActionsListItems.layers.layer_grammar_form.multipleLayers"
              )
            : t(
                "screens.device.scenes.sceneActionsListItems.layers.layer_grammar_form.oneLayer"
              );
        const affectedLayers = item.modeAdjustments.layers.join(", ");

        const lightMode = appContext.deviceFirmwareModes.lightModes.find(
          (lM) => lM.id === item.modeId
        );

        adjustments.push(
          <ListItem
            text={
              lightMode && (
                <>
                  {lightMode.defaults.length === 0
                    ? `${t(
                        "screens.device.scenes.sceneActionsListItems.layers.applyToLayers",
                        {
                          LAYER_GRAMMAR_FORM: layerGrammarForm,
                          AFFECTED_LAYERS: affectedLayers,
                        }
                      )} `
                    : `${t(
                        "screens.device.scenes.sceneActionsListItems.layers.setLayersTo",
                        {
                          LAYER_GRAMMAR_FORM: layerGrammarForm,
                          AFFECTED_LAYERS: affectedLayers,
                        }
                      )} ${
                        item.modeAdjustments.colors.length === 0 ? "???" : ""
                      }`}
                </>
              )
            }
            children={
              item.modeAdjustments.colors !== undefined && (
                <>
                  {item.modeAdjustments.colors.map((color, index) => (
                    <MyColorSwatch
                      key={index}
                      backgroundColor={color}
                      size={16}
                      style={{ marginRight: -2 }}
                    />
                  ))}
                </>
              )
            }
          />
        );
      }
      break;
    case Constants.actionType.ambilight:
      navigateTo = "modalLightsEditAction";
      navigateToOptions.actionType = Constants.actionType.ambilight;
      itemModeList = appContext.deviceFirmwareModes.lightModes;

      adjustments.push(
        <ListItem
          text={
            <>{t("screens.device.scenes.sceneActionsListItems.ambilight")} </>
          }
          children={
            item.modeAdjustments.colors !== undefined && (
              <>
                {item.modeAdjustments.colors.map((color, index) => (
                  <MyColorSwatch
                    key={index}
                    backgroundColor={color}
                    size={16}
                    style={{ marginRight: -2 }}
                  />
                ))}
              </>
            )
          }
        />
      );
      break;
    case Constants.actionType.motor:
      navigateTo = "modalMotorEditAction";
      itemModeList = appContext.deviceFirmwareModes.motorModes;
      break;
    case Constants.actionType.wait:
      navigateTo = "modalWaitEditAction";

      let msg = "";

      const hours = item.modeAdjustments.hours;
      const minutes = item.modeAdjustments.minutes;
      const seconds = item.modeAdjustments.seconds;

      const hoursText =
        hours === 1
          ? t(
              "screens.device.scenes.editActions.modalWaitEditAction.hours.singular"
            )
          : t(
              "screens.device.scenes.editActions.modalWaitEditAction.hours.plural"
            );

      const minutesText =
        minutes === 1
          ? t(
              "screens.device.scenes.editActions.modalWaitEditAction.minutes.singular"
            )
          : t(
              "screens.device.scenes.editActions.modalWaitEditAction.minutes.plural"
            );

      const secondsText =
        seconds === 1
          ? t(
              "screens.device.scenes.editActions.modalWaitEditAction.seconds.singular"
            )
          : t(
              "screens.device.scenes.editActions.modalWaitEditAction.seconds.plural"
            );

      const wordAndForBetterSceneActionListAdjustmentReadingText = t(
        "screens.device.scenes.editActions.modalWaitEditAction.wordAndForBetterSceneActionListAdjustmentReading"
      );

      if (hours > 0) {
        msg += `${hours} ${hoursText}`;
      }

      if (minutes > 0) {
        if (msg.length > 0) {
          msg += ", ";
        }

        if (hours > 0 && seconds === 0) {
          msg += ` ${wordAndForBetterSceneActionListAdjustmentReadingText} `;
        }

        msg += `${minutes} ${minutesText}`;
      }

      if (seconds > 0) {
        if (msg.length > 0) {
          msg += ` ${wordAndForBetterSceneActionListAdjustmentReadingText} `;
        }

        msg += `${seconds} ${secondsText}`;
      }

      if (msg.length === 0) {
        msg = `0 ${secondsText}`;
      }

      adjustments.push(<ListItem text={<Text>{msg}</Text>} />);
      break;
    case Constants.actionType.stop:
      navigateTo = "modalStopEditAction";
      break;
    default:
      console.log("item type not defined" + item.type);
      return;
  }

  if (
    item.animationInId !== Constants.defaultAnimationId ||
    item.animationOutId !== Constants.defaultAnimationId
  ) {
    let inAndOutAnimation = [];

    if (item.animationInId !== Constants.defaultAnimationId) {
      inAndOutAnimation.push(
        getAnimationText(
          appContext.deviceFirmwareModes.lightAnimationsIn,
          item.animationInId,
          item.animationInAdjustment
        )
      );
    }

    if (item.animationOutId !== Constants.defaultAnimationId) {
      inAndOutAnimation.push(
        getAnimationText(
          appContext.deviceFirmwareModes.lightAnimationsOut,
          item.animationOutId,
          item.animationOutAdjustment
        )
      );
    }

    adjustments.push(
      <View style={{ flexDirection: "row", alignItems: "center", gap: 6 }}>
        <MyIcon name="transition" size={16} />
        <Text style={{ color: appContext.appTheme.textSecondary }}>
          {inAndOutAnimation.join(", ")}
        </Text>
      </View>
    );
  }

  const renderAdjustments = () => {
    if (item.modeId === "" && item.type !== Constants.actionType.wait) {
      return null;
    }

    return (
      <>
        {adjustments.map((adjustment, index) => (
          <View key={index} style={{ flexDirection: "row" }}>
            {adjustment}
          </View>
        ))}
      </>
    );
  };

  return (
    <View style={{ marginLeft: 15, marginRight: 15 }}>
      <TouchableOpacity
        onPress={() => navigation.navigate(navigateTo, navigateToOptions)}
      >
        <View
          style={{
            flexDirection: "row",
            justifyContent: "space-between",
            alignItems: "center",
          }}
        >
          <View
            style={{
              flexDirection: "row",
              alignItems: "center",
            }}
          >
            <MyIcon name={ActionTypeIconName(item.type)} size={24} />

            <View style={{ flexDirection: "row" }}>
              <View style={{ marginLeft: 12 }}>
                <ListItemTitle />

                {renderAdjustments()}
              </View>
            </View>
          </View>

          <TouchableOpacity
            disabled={drag === false}
            onLongPress={() => {
              // darg will be null if stop is rendered on the footer of the FlatList
              if (!drag) return;

              drag();
              VibrateShort();
            }}
            style={{ padding: 4 }}
          >
            <MyIcon name="menu" size={20} disabled={drag === false} />
          </TouchableOpacity>
        </View>

        <Divider />
      </TouchableOpacity>
    </View>
  );
}

export function ActionTypeIconName(actionType) {
  let iconName = "";

  switch (actionType) {
    case Constants.actionType.layers:
      iconName = "lightbulb-on-outline";
      break;
    case Constants.actionType.ambilight:
      iconName = "television-ambient-light";
      break;
    case Constants.actionType.motor:
      iconName = "axis-z-rotate-counterclockwise";
      break;
    case Constants.actionType.wait:
      iconName = "timer-sand";
      break;
    case Constants.actionType.waitUntilTimeX:
      iconName = "clock-time-eight-outline";
      break;
    case Constants.actionType.stop:
      iconName = "pause-octagon-outline";
      break;
    case Constants.actionType.timeControl:
      iconName = "timer-cog";
      break;
    case Constants.actionType.waitForConfirmationWithKey:
      iconName = "gesture-tap-button";
      break;
    case Constants.actionType.jumpToScene:
      iconName = "debug-step-over";
      break;
    default:
      iconName = "help";
      break;
  }

  return iconName;
}
