import React, { useEffect, useRef, useState } from 'react';
import { nanoid } from 'nanoid';
import { LayoutAnimation, Platform, UIManager } from 'react-native';
import { toasterSubject$ } from '../services/toaster-service';
import { fp as _ } from '../../../utils/fp';
import { SBox } from '../../../s-components/layout/s-box';
import { SBoxAnimated } from '../../../s-components/layout/s-box-animated';
import { Toast } from './toast';
import { useAutoUnsub } from '../../../hooks/use-auto-unsub';
import { StreamFactory } from '../../../utils/stream-factory';
import { ReduxState } from '../../../utils/redux';
import { makeRoutingCurrentSelector } from '../../../selectors';
import { isLastRouteInCamel } from '../../../transducers';
import { TToast } from '../types';

/*
 * https://github.com/oblador/react-native-animatable
 * */

type TProps = {
  hasSafeArea?: boolean;
  page: string;
};

type TStateToast = {
  id: string;
  toast: TToast;
};

// https://reactnative.dev/docs/layoutanimation
if (Platform.OS === 'android') {
  if (UIManager.setLayoutAnimationEnabledExperimental) {
    UIManager.setLayoutAnimationEnabledExperimental(true);
  }
}

export const ToastAnimationCooldown = new StreamFactory({ withState: true });

export const Toaster: React.FC<TProps> = props => {
  const timers = useRef<Record<string, any>>({});
  const [toasts, setToasts] = useState<TStateToast[]>([]);
  const autoUnsub = useAutoUnsub();
  const { page } = props;

  const checkIfBlurred = () => {
    const state = ReduxState.getState();
    const route = makeRoutingCurrentSelector()(state);
    return !isLastRouteInCamel(_.capitalizeSafe(page), route!);
  };

  useEffect(() => {
    autoUnsub(
      toasterSubject$.subscribe(toast => {
        // TODO: I'll comment it for now as it causes AG-7796
        // TODO: However it will cause duplicated messages in toasts during fast navigation
        if (checkIfBlurred()) {
          return;
        }

        if (Platform.OS === 'ios') {
          LayoutAnimation.easeInEaseOut();
        }

        setToasts(toasts => {
          const id = nanoid();
          timers.current[id] = setTimeout(() => {
            timers.current[id] = undefined;

            if (!checkIfBlurred()) {
              LayoutAnimation.easeInEaseOut();
            }

            setToasts(toastsToRemove => {
              return _.reject({ id }, toastsToRemove);
            });
          }, (toast as TToast).time || 5000);

          if (toasts.length > 3) {
            timers.current[id] = undefined;
          }

          return [
            ...(toasts.length > 3 ? toasts.slice(1) : toasts),
            {
              id,
              toast: toast as TToast,
            },
          ];
        });
      })
    );

    return () => {
      _.mapValues(timerId => clearTimeout(timerId), timers.current);
      setToasts([]);
    };
  }, []);

  const { hasSafeArea } = props;
  const marginBottom = hasSafeArea ? 50 : 16;

  if (!toasts.length) {
    return null;
  }

  return (
    <SBox position="absolute" zIndex={11} bottom={marginBottom} width={1}>
      {toasts.map(({ id, toast }) => {
        return (
          <SBoxAnimated key={id} marginTop={16}>
            <Toast {...toast! as any} />
          </SBoxAnimated>
        );
      })}
    </SBox>
  );
};

Toaster.defaultProps = {
  hasSafeArea: false,
};
