import React, { memo, useCallback } from 'react';
import { Dimensions, Platform } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import { RefreshableView } from '../../common/components/refreshable-view';
import { theme } from '../../app/theme';
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 { addSafeArea } from '../../common/transducers';
import { RefillingIndicator } from '../../common/components/refilling-indicator';
import { SEARCH_FILTERING_POPUP_ID, SEARCH_VARIANT } from '../constants';
import { TActiveVisibilityConfig, TGetAnyData, TState } from '../types';
import { TRefreshableRenderer } from '../../common/types';
import { ROUTES } from '../../app/constants';
import { RecentTracks } from './tab-tracks/recent-tracks';
import { SKeyboardAvoidingView } from '../../common/s-components/s-keyboard-avoiding-view';
import { Header } from './header';
import { Tracks } from './tab-tracks/tracks';
import { ViewEmptyRecentSearch } from './shared/view-empty-recent-search';
import { ViewEmptySearch } from './shared/view-empty-search';
import { RecentPlaylists } from './tab-playlists/recent-playlists';
import { Playlists } from './tab-playlists/playlists';
import { LoadingOverlay } from '../../common/components/loading-overlay';
import { SwipeablePopup } from '../../common/components/bottom-sheet/swipeable-popup';
import { useNanoId } from '../../common/hooks/use-nano';
import { PopupFilter } from './popup-filter';
import { Portal } from '../../common/utils/portal/portal';
import { fp as _ } from '../../common/utils/fp';

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

type TProps = {
  refresh: () => void;
  activeVisibility: TActiveVisibilityConfig;
  getData: () => void;
  getAnyData: TGetAnyData;
  config: TState['tracks']['config'];
};

export const Search: React.FC<TProps> = memo(props => {
  const { refresh, activeVisibility, getData } = props;

  const id = useNanoId();

  const renderHeader: TRefreshableRenderer = ({
    animationY,
    scrollToTop,
    isScrolled,
  }) => {
    return (
      <Header
        animationY={animationY}
        scrollToTop={scrollToTop}
        isScrolled={isScrolled}
      />
    );
  };

  const renderBody: TRefreshableRenderer = useCallback(() => {
    const { variant, visibility } = activeVisibility;
    const isIos = Platform.OS === 'ios';

    return (
      <>
        <SBoxAnimated flex={1} pt={maxHeight} pb={32}>
          {visibility.offline ? (
            <ViewNetworkFailed
              verticalOffset={-18}
              variant="network-failed-white"
              withAnimation
            />
          ) : null}

          {visibility.error ? (
            <ViewLoadFailed variant="search" verticalOffset={12} />
          ) : null}

          {(variant === SEARCH_VARIANT.recentPlaylists ||
            variant === SEARCH_VARIANT.recentTracks) &&
          visibility.empty ? (
            <ViewEmptyRecentSearch
              keyboardHiddenMargin={8}
              keyboardDisplayedMargin={isIos ? -44 : 0}
            />
          ) : null}

          {(variant === SEARCH_VARIANT.tracks ||
            variant === SEARCH_VARIANT.playlists) &&
          visibility.empty ? (
            <ViewEmptySearch
              keyboardHiddenMargin={8}
              keyboardDisplayedMargin={isIos ? -44 : 0}
            />
          ) : null}

          {visibility.extra.search &&
          visibility.extra.loading &&
          !visibility.refresh ? (
            <LoadingOverlay variant="transparent" />
          ) : null}

          {variant === SEARCH_VARIANT.recentTracks &&
          (visibility.data || visibility.skeleton) ? (
            <RecentTracks />
          ) : null}
          {variant === SEARCH_VARIANT.tracks && visibility.data ? (
            <Tracks />
          ) : null}

          {variant === SEARCH_VARIANT.recentPlaylists &&
          (visibility.data || visibility.skeleton) ? (
            <RecentPlaylists />
          ) : null}

          {variant === SEARCH_VARIANT.playlists && visibility.data ? (
            <Playlists />
          ) : null}

          {visibility.extra.refill ? <RefillingIndicator /> : null}
        </SBoxAnimated>
      </>
    );
  }, [activeVisibility]);

  const renderBgLayer = () => {
    const { variant, visibility } = activeVisibility;
    const fastGradient = !(
      [SEARCH_VARIANT.tracks, SEARCH_VARIANT.playlists].includes(
        variant as SEARCH_VARIANT
      ) ||
      visibility.empty ||
      visibility.error ||
      visibility.offline
    );
    // to avoid the keyboard background we need to increase the height of the gradient
    const fastGradientHeight = DEVICE_HEIGHT * 0.6;
    const layerHeight = fastGradient ? fastGradientHeight : DEVICE_HEIGHT;

    return (
      <SBox height={layerHeight}>
        <LinearGradient
          colors={theme.gradients.search}
          locations={[0, fastGradient ? 273 / fastGradientHeight : 1]}
          style={{ flex: 1 }}
        />
      </SBox>
    );
  };

  const renderFgLayer = () => {
    const { config, getAnyData } = props;

    const params = {
      vendor: _.path('vendor', config),
    };

    return (
      <Portal id={`POPUP_SEARCH:${id}`} updateIfAnyChanged={params}>
        <SwipeablePopup
          variant={SEARCH_FILTERING_POPUP_ID}
          content={
            <PopupFilter
              id={SEARCH_FILTERING_POPUP_ID}
              title="Playlists"
              value={params.vendor as string[]}
              getAnyData={getAnyData}
            />
          }
        />
      </Portal>
    );
  };

  const { visibility } = activeVisibility;
  const isIos = Platform.OS === 'ios';
  const behavior =
    isIos ||
    (!isIos &&
      (visibility.empty || visibility.extra.search || visibility.offline))
      ? 'padding'
      : undefined;

  return (
    <SKeyboardAvoidingView behavior={behavior} enabled>
      <RefreshableView
        testID="search-refreshable-view"
        enableScroll={visibility.data}
        indicatorLight
        indicatorOffsetTop={maxHeight - 15}
        loading={activeVisibility.visibility.refresh}
        // inifite pagination - get next page when we don't have payload
        onScrollReachBottom={() => getData()}
        onPullDown={() => !activeVisibility.visibility.skeleton && refresh()}
        renderHeader={renderHeader}
        renderBody={renderBody}
        renderBgLayer={renderBgLayer}
        renderFgLayer={renderFgLayer}
        name={ROUTES.search}
        withNativeDriver
      />
    </SKeyboardAvoidingView>
  );
});

// static navigationOptions = () => ({
//   title: 'Search',
//   header: null,
// });
