import React, { useRef, useState, useEffect } from "react";
import * as R from "ramda";
import {
  View,
  Text,
  Animated,
  StyleSheet,
  TouchableWithoutFeedback,
} from "react-native";

import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
import { textTransform } from "@applicaster/zapp-react-native-utils/cellUtils";
import { useNotificationHeight } from "../utils";

export const onlinePhrase = "You are back online";

export const offlinePhrase = "No internet connection";

const styles = StyleSheet.create({
  notificationView: {
    flex: 1,
    position: "absolute",
    alignItems: "center",
    justifyContent: "center",
    top: 0,
    left: 0,
    right: 0,
  },
});

type Props = {
  children?: React.ReactNode;
  hidden?: boolean;
  online?: boolean;
  dismiss: () => void;
};

type NumberBoolean = 0 | 1;

const OFFLINE_EXPERIENCE = "offline-experience";

export const NotificationView = ({
  children,
  hidden = true,
  online = true,
  dismiss,
}: Props) => {
  const { plugins } = usePickFromState(["plugins"]);
  const { statusHeight, notificationHeight } = useNotificationHeight();

  const offlinePlugin = R.find(
    R.propEq("identifier", OFFLINE_EXPERIENCE),
    plugins
  );

  const { useOfflineExperienceConfiguration } = offlinePlugin.module;

  const {
    configurationFields,
    localizations,
  }: {
    configurationFields: OfflineExperiencePluginConfiguration;
    localizations: OfflineExperienceLocalizations;
  } = useOfflineExperienceConfiguration?.();

  const [notificationOpacity, setNotificationOpacity] =
    useState<NumberBoolean>(0);

  const yPosition = useRef(new Animated.Value(0)).current;

  const showNotification = () => {
    setNotificationOpacity(1);

    Animated.timing(yPosition, {
      toValue: 1,
      useNativeDriver: true,
      duration: 300,
    }).start();
  };

  const hideNotification = () => {
    Animated.timing(yPosition, {
      toValue: 0,
      useNativeDriver: true,
      duration: 300,
    }).start(() => {
      setNotificationOpacity(0);
    });
  };

  useEffect(() => {
    hidden ? hideNotification() : showNotification();
  }, [hidden]);

  const backgroundColor = online
    ? configurationFields.offline_toast_online_background_color
    : configurationFields.offline_toast_offline_background_color;

  const animatedViewStyles = {
    ...styles.notificationView,
    transform: [
      {
        translateY: yPosition.interpolate({
          inputRange: [0, 1],
          outputRange: [-notificationHeight, 0],
        }),
      },
    ],
    opacity: notificationOpacity,
    height: notificationHeight,
    width: "100%",
    backgroundColor,
  };

  const textStyles = {
    color: online
      ? configurationFields.offline_toast_message_online_font_color
      : configurationFields.offline_toast_message_font_color,
    fontFamily: platformSelect({
      ios: configurationFields.offline_toast_message_ios_font_family,
      android: configurationFields.offline_toast_message_android_font_family,
    }),
    fontSize: configurationFields.offline_toast_message_font_size,
    lineHeight: configurationFields.offline_toast_message_line_height,
    letterSpacing: platformSelect({
      ios: configurationFields.offline_toast_message_letter_spacing_ios,
      android: configurationFields.offline_toast_message_letter_spacing_android,
    }),
  };

  const message = textTransform(
    configurationFields.offline_toast_message_text_transform,
    online
      ? localizations.online_toast_message
      : localizations.offline_toast_message
  );

  return (
    <View style={StyleSheet.absoluteFill}>
      {children}
      <TouchableWithoutFeedback
        style={styles.notificationView}
        onPress={dismiss}
      >
        <Animated.View style={animatedViewStyles}>
          <View style={{ height: statusHeight, backgroundColor }} />
          <Text style={textStyles}>{message}</Text>
        </Animated.View>
      </TouchableWithoutFeedback>
    </View>
  );
};
