import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
import {
  Animated,
  Easing,
  LayoutAnimation,
  Platform,
  StyleSheet,
  UIManager,
  View,
} from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import { SkeletonTypes } from './types';
import { Colors, Styles } from '../Consts';
import styles from './styles';
import { ScreenContext, SkeletonContext } from '../Context';

const Skeleton: React.FC<SkeletonTypes> = ({ style }) => {
  const screen = useContext<any>(ScreenContext);
  const [width, setWidth] = useState(0);
  const PRIMARY_COLOR = Colors.black_05;
  const HIGHLIGHT_COLOR1 = Colors.black_05;
  const HIGHLIGHT_COLOR2 = Colors.black_03;
  const beginShimmerPosition = useRef(new Animated.Value(0)).current;

  const shimmerColors = [HIGHLIGHT_COLOR1, HIGHLIGHT_COLOR2, HIGHLIGHT_COLOR1];
  const linearTranslate = beginShimmerPosition.interpolate({
    inputRange: [0, 1],
    outputRange: [-width, width],
  });
  const animatedValue = useMemo(() => {
    return Animated.loop(
      Animated.timing(beginShimmerPosition, {
        toValue: 1,
        duration: 1000,
        easing: Easing.linear,
        useNativeDriver: Platform.OS !== 'web',
      }),
    );
  }, [beginShimmerPosition]);

  useEffect(() => {
    animatedValue.start();
    screen?.onLoading?.(true);
    return () => {
      animatedValue.stop();
      screen?.onLoading?.(false);
    };
  }, [animatedValue, screen]);

  const onLayout = (newWidth: number) => {
    if (newWidth !== width) {
      setWidth(newWidth);
    }
  };

  return (
    <View style={[styles.container, style]}>
      <View
        onLayout={e => onLayout(e.nativeEvent.layout.width)}
        style={[Styles.flex, { backgroundColor: PRIMARY_COLOR }]}
      >
        <Animated.View
          style={{
            transform: [{ translateX: linearTranslate }],
            width: '60%',
            height: '100%',
          }}
        >
          <LinearGradient
            style={[StyleSheet.absoluteFill]}
            colors={shimmerColors}
            start={{
              x: 0,
              y: 0,
            }}
            end={{
              x: 1,
              y: 0,
            }}
          />
        </Animated.View>
      </View>
    </View>
  );
};

const SkeletonProvider: React.FC<{ loading: boolean; children: any }> = ({
  loading = true,
  children,
}) => {
  const [previous, setPrevious] = useState(loading);

  useEffect(() => {
    if (previous !== loading) {
      if (Platform.OS === 'android') {
        if (UIManager.setLayoutAnimationEnabledExperimental) {
          UIManager.setLayoutAnimationEnabledExperimental(true);
        }
      }
      LayoutAnimation.configureNext({
        duration: 500,
        create: {
          type: LayoutAnimation.Types.easeInEaseOut,
          property: LayoutAnimation.Properties.opacity,
        },
      });
      setPrevious(loading);
    }
  }, [loading, previous]);

  return (
    <SkeletonContext.Provider value={{ loading: previous }}>
      {children}
    </SkeletonContext.Provider>
  );
};

export { Skeleton, SkeletonProvider };
