import React, { memo, useCallback } from 'react';
import { Dimensions, StyleSheet } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import { RefreshableView } from '../../common/components/refreshable-view';
import { SBoxAnimated } from '../../common/s-components/layout/s-box-animated';
import { ViewLoadFailed } from '../../common/components/view-load-failed';
import { ViewNetworkFailed } from '../../common/components/view-network-failed';
import { SBox } from '../../common/s-components/layout/s-box';
import { TState } from '../types';
import {
  NEntityInfinite,
  TEntityVisibility,
  TRefreshableRenderer,
} from '../../common/types';
import { Header } from './header';
import { theme } from '../../app/theme';
import { fp as _ } from '../../common/utils/fp';
import { SHeaderGradient } from '../../track/s-components/s-header-gradient';
import { List } from './list';
import { Regions } from './regions';
import { Metrics } from './metrics';
import { SImage } from '../../common/s-components/s-image';
import { TData } from '../../track/types';
import { SortPopup } from './list/sort-popup';
import { Portal } from '../../common/utils/portal/portal';
import { SwipeablePopup } from '../../common/components/bottom-sheet/swipeable-popup';
import { InfoNmfPopup } from './info-nmf-popup';
import { INFO_POPUP_HH, INFO_POPUP_NMF } from '../constants';
import { ROUTES } from '../../app/constants';
import { addSafeArea } from '../../common/transducers/transducers.device-dimension';

const { height: DEVICE_HEIGHT } = Dimensions.get('window');
const maxHeight = addSafeArea(100);

type TProps = {
  // navigation: TNavigation;
  refreshing: boolean;
  refresh: () => void;
  visibilityData: TEntityVisibility;
  visibilitySettings: TEntityVisibility;
  getData: NEntityInfinite.TEntityInfiniteGet;
  // getSettings: () => void;
  setConfig: (config: TState['config']) => void;
  config: TState['config'];
  trackData: TData | {};
  marketsData: TState['marketsData'];
  latestDate: TState['latestDate'];
  visibilityMarketsData: TEntityVisibility;
  pageVariant: string;
};

export const Nmf: React.FC<TProps> = memo(props => {
  const {
    pageVariant,
    visibilityData,
    visibilitySettings,
    visibilityMarketsData,
    config,
    getData,
    setConfig,
    marketsData,
    latestDate,
    trackData,
    refreshing,
    refresh,
  } = props;

  const renderOffline = () => {
    return (
      <SBoxAnimated position="relative" flex={1} pt={29}>
        <ViewNetworkFailed verticalOffset={35} />
      </SBoxAnimated>
    );
  };

  const renderFailedToLoad = useCallback(() => {
    const isNmf = pageVariant === 'nmf';
    const variant = isNmf ? 'nmf' : 'hh';
    return <ViewLoadFailed variant={variant} verticalOffset={0} />;
  }, [pageVariant]);

  const renderHeader: TRefreshableRenderer = useCallback(
    ({ animationY, scrollToTop, isScrolled }) => {
      const isNmf = pageVariant === 'nmf';
      return (
        <Header
          animationY={animationY}
          scrollToTop={scrollToTop}
          isScrolled={isScrolled}
          isNmf={isNmf}
        />
      );
    },
    [pageVariant]
  );

  const renderBody: TRefreshableRenderer = useCallback(() => {
    const anyOffline =
      visibilitySettings.offline ||
      visibilityMarketsData.offline ||
      visibilityData.offline;

    if (anyOffline) {
      return renderOffline();
    }

    if (visibilitySettings.error) {
      return renderFailedToLoad();
    }

    return (
      <SBox position="relative" flex={1} pt={maxHeight} pb={32}>
        <LinearGradient
          colors={theme.gradients.nmfList}
          locations={[0, 0.2, 0.3, 1]}
          style={[StyleSheet.absoluteFill, { height: 460, top: 100 }]}
        />
        <Metrics />
        <SBox position="relative">
          <Regions />
          <List />
        </SBox>
      </SBox>
    );
  }, [visibilityData, visibilitySettings, visibilityMarketsData]);

  const renderBgLayer: TRefreshableRenderer = useCallback(() => {
    const anyError =
      visibilitySettings.error ||
      visibilitySettings.offline ||
      visibilityMarketsData.offline ||
      visibilityData.offline;

    if (anyError) return false;

    const imageUrl = _.path('image_url', trackData);
    const gradientHeight = DEVICE_HEIGHT * 0.7;
    const imageHeight = 375;

    return (
      <SBox height={gradientHeight}>
        {imageUrl ? (
          <SBox height={imageHeight} width={1} position="absolute">
            <SImage
              height={imageHeight}
              width={1}
              resizeMode="cover"
              source={{
                uri: imageUrl,
              }}
            />
          </SBox>
        ) : null}

        <SHeaderGradient
          height={300}
          top={200}
          colors={theme.gradients.playlistsImageCover}
          locations={[0, 0.24, 1]}
        />

        <SHeaderGradient
          height={375}
          top={0}
          colors={theme.gradients.nmfAvatar}
          location={[0, 0.26, 0.67, 1]}
        />
      </SBox>
    );
  }, [visibilityData, trackData, visibilitySettings, visibilityMarketsData]);

  const renderFgLayer = useCallback(() => {
    const isNmf = pageVariant === 'nmf';
    const params = {
      orderBy: _.path('order_by', config),
      marketsData: _.path('data', marketsData),
      isNmf,
      latestDate,
    };

    const popupVariant = isNmf ? INFO_POPUP_NMF : INFO_POPUP_HH;

    return (
      <Portal id={popupVariant} updateIfAnyChanged={params}>
        <SortPopup
          config={config}
          getData={getData}
          setConfig={setConfig}
          isNmf={isNmf}
        />
        <SwipeablePopup
          variant={popupVariant}
          content={
            <InfoNmfPopup
              isNmf={isNmf}
              data={marketsData}
              latestDate={latestDate}
            />
          }
        />
      </Portal>
    );
  }, [config, getData, setConfig, marketsData, pageVariant, latestDate]);

  return (
    <RefreshableView
      testID="nmf-refreshable-view"
      loading={refreshing}
      indicatorLight
      indicatorOffsetTop={120}
      onPullDown={() => {
        if (visibilitySettings.skeleton || visibilityMarketsData.skeleton) {
          return;
        }
        refresh();
      }}
      renderHeader={renderHeader}
      renderBody={renderBody}
      renderBgLayer={renderBgLayer}
      renderFgLayer={renderFgLayer}
      name={ROUTES.nmf}
      withNativeDriver
    />
  );
});
