import React, { useCallback, useEffect, useRef, useState } from "react";
import { View, StyleSheet } from "react-native";
import { NotificationView as NotificationViewNative } from "./NotificationView/NotificationView";
import { NotificationView as NotificationViewSamsung } from "./NotificationView/NotificationView.samsung";
import { NotificationView as NotificationViewLG } from "./NotificationView/NotificationView.lg";

import { useConnectionInfo } from "@applicaster/zapp-react-native-utils/reactHooks/connection";
import { usePrevious } from "@applicaster/zapp-react-native-utils/reactHooks/utils";
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";

import { componentsLogger } from "../../Helpers/logger";
import { parseConnectionInfo } from "./utils";

const logger = componentsLogger.addSubsystem("OfflineHandler");

type Props = {
  children?: React.ReactElement<any>;
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    position: "relative",
  },
});

const timers = {
  goingOffline: 5000,
  goingOnline: 2000,
};

export const NotificationView = platformSelect({
  samsung_tv: NotificationViewSamsung,
  lg_tv: NotificationViewLG,
  default: NotificationViewNative,
});

export const OfflineHandler = ({ children }: Props) => {
  const connectionInfo = useConnectionInfo(false);
  const { online, deviceOnline } = parseConnectionInfo(connectionInfo);

  const [hidden, setHidden] = useState<boolean>(true);
  const previousOnline: boolean = usePrevious(online);
  const timer = useRef<NodeJS.Timeout | null>(null);
  const initialRender = useRef(false);

  const dismiss = useCallback(() => {
    setHidden(true);

    if (timer.current) {
      clearTimeout(timer.current);
      timer.current = null;
    }
  }, []);

  const setTimer = useCallback((cb, duration) => {
    if (timer.current) {
      clearTimeout(timer.current);
    }

    timer.current = setTimeout(cb, duration);
  }, []);

  useEffect(() => {
    if (initialRender.current) {
      const wentOffline = previousOnline && online === false;
      const wentOnline = !previousOnline && online;
      const renderedOffline = !online && previousOnline === null;

      if (!deviceOnline || wentOffline || renderedOffline) {
        logger.log("Device went offline");
        setTimer(() => setHidden(true), timers.goingOffline);
        setHidden(false);
      }

      if (wentOnline) {
        logger.log("Device is back online");
        setHidden(false);
        setTimer(() => setHidden(true), timers.goingOnline);
      }
    } else {
      initialRender.current = true;
    }

    return () => {
      if (timer.current) {
        clearTimeout(timer.current);
        timer.current = null;
      }
    };
  }, [connectionInfo]);

  return (
    <View style={styles.container}>
      <NotificationView
        hidden={hidden}
        online={online}
        previousOnline={previousOnline}
        dismiss={dismiss}
      >
        {children}
      </NotificationView>
    </View>
  );
};
