import React, { memo, useCallback } from 'react';
// import Constants from 'expo-constants';
import { Dimensions, Platform, Pressable } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
// import { NavigationScreenProp } from 'react-navigation';
import { RefreshableView } from '../../common/components/refreshable-view';
// import { type NavigationScreenProp } from 'react-navigation';
import { BackButton } from '../../common/components/back-button';
import { SBoxAnimated } from '../../common/s-components/layout/s-box-animated';
import { theme } from '../../app/theme';
import { EStarSourcePages } from '../../common/constants';
import { SBox } from '../../common/s-components/layout/s-box';
import { Arc } from '../../common/components/arc';
import { SwipeableList } from '../../common/components/swipeable-list';
// import { ViewNoStarred } from '../../common/components/view-no-starred';
import { ViewLoadFailed } from '../../common/components/view-load-failed';
import { ViewNetworkFailed } from '../../common/components/view-network-failed';
import { ViewNoChartTracks } from './view-no-chart-tracks';
import {
  getStatusBarHeight,
  addSafeArea,
  isBrokenIsrc,
  setAndroidFigureOffset,
  getAnimations,
} from '../../common/transducers';
import { Router } from '../../common/utils/navigation-service';
import WithMarketIndicator from '../../common/containers/with-market-indicator';
import { updatePageMeta, PAGES } from '../../analytics';
import { fp as _ } from '../../common/utils/fp';
import { openPopupByVariant } from '../../common/utils/keyboard-service';
import {
  TRefreshableRenderer,
  TTracksSimpleExtended,
} from '../../common/types';
import { TRefresh, TGoToHomeListTrack, TVisibility } from '../types';
import { ROUTE_PARAMS, ROUTES } from '../../app/constants';
import { getHomeListPageVariant } from '../transducers';
import { TToggleStarred } from '../../common/submodules/starring-tracks/types';
import { SH3 } from '../../common/s-components/typography/s-h3';
import { Flag } from '../../common/components/flag';
import { SRow } from '../../common/s-components/layout/s-row';
import { SListTitle } from '../s-components/s-list-title';

// const maxHeight = 149;
// const minHeight = 120;
const maxHeight = addSafeArea(84);
const minHeight = addSafeArea(60);
const safeArea = getStatusBarHeight();
const heightDiff = maxHeight - minHeight;
const maxSafeHeight = addSafeArea(229);
const { height: DEVICE_HEIGHT, width: DEVICE_WIDTH } = Dimensions.get('window');
const headerAdditionalValue = 20;

export type TProps = {
  route: { name: string; params: any };
  additions: TTracksSimpleExtended[];
  removals: TTracksSimpleExtended[];
  toggleStarred: TToggleStarred;
  refreshing: boolean;
  refresh: TRefresh;
  visibility: TVisibility;
  marketName: string;
};

const Animation = getAnimations({
  headerBg: {
    opacity: {
      inputRange: [0, heightDiff],
      outputRange: [0, 1],
    },
    translateY: {
      inputRange: [0, heightDiff],
      outputRange: [0, -heightDiff],
    },
  },

  title: {
    opacity: {
      inputRange: [0, heightDiff / 3, heightDiff / 2, heightDiff],
      outputRange: [1, 1, 0, 0],
    },
    translateY: {
      inputRange: [0, heightDiff / 1.5, heightDiff],
      outputRange: [safeArea + 21, safeArea + 12, 0],
    },
  },

  titleSmall: {
    opacity: {
      inputRange: [0, heightDiff / 2, heightDiff / 1.5, heightDiff],
      outputRange: [0, 0, 1, 1],
    },
    translateY: {
      inputRange: [0, heightDiff / 3, heightDiff / 2, heightDiff],
      outputRange: [safeArea + 45, safeArea + 45, safeArea + 18, safeArea + 12],
    },
    scaleY: {
      inputRange: [0, heightDiff / 3, heightDiff / 2],
      outputRange: [0, 1, 1],
    },
  },

  arrow: {
    translateY: {
      inputRange: [0, heightDiff],
      outputRange: [safeArea + 12, safeArea],
    },
    translateX: 16,
  },
});

/*
 * Custom loader
 * http://qaru.site/questions/456933/how-to-customize-lookfeel-of-react-native-listviews-refreshcontrol
 * https://medium.com/@lennyboyatzis/custom-pull-to-refresh-animations-in-react-native-1efac58609d3
 * */
export const List: React.FC<TProps> = memo(props => {
  const {
    refreshing,
    refresh,
    route,
    visibility,
    additions,
    removals,
    toggleStarred,
    marketName,
  } = props;
  /*
   * https://reactnavigation.org/docs/en/header-buttons.html
   * To share public props and methods with navigationOptions e.g. redux actions or props
   * */
  // But it seems like we can use connected redux components inside navigationOptions?
  // componentDidMount() {
  // this.props.navigation.setParams({ increaseCount: this._increaseCount });
  // navigation.getParam('increaseCount')s
  // }

  const goToHomeListTrack: TGoToHomeListTrack = params => {
    if (_.isEmpty(params.trackId) || isBrokenIsrc(params.isrc)) {
      Router.goTo(ROUTES.emptytrack);
    } else {
      Router.goTo(ROUTES.track, params);

      updatePageMeta({
        page: PAGES.Track.page,
        source: _.pathEq(['type'], 'entries', route.params)
          ? 'Homeentries'
          : 'Homeexits',
        track_id: params.trackId,
        track_name: params.name,
        track_artist: params.artist,
        is_starred: params.starred,
        isrc: params.isrc,
        distributor: params.distributor,
      });
    }
  };

  const getTitle = () => {
    const params = _.path('params', route);
    const isAdditions = _.pathEq(['type'], 'entries', params);
    const isSpotify = _.pathEq(['homeVendor'], 'spotify', params);
    const direction = isAdditions ? 'Entries' : 'Exits';
    const vendor = isSpotify ? 'Spotify' : 'Apple Music';

    return `${vendor} ${direction}`;
  };

  const renderBgLayer = useCallback(() => {
    const params = _.path('params', route);
    const isSpotify = _.pathEq(['homeVendor'], 'spotify', params);
    const gradient = isSpotify
      ? theme.gradients.listHeaderTrackSpotify
      : theme.gradients.listHeaderTrackApple;

    if (visibility.errorOffline) return false;

    return (
      <SBox flex={1} pb={DEVICE_HEIGHT / 2}>
        <LinearGradient
          colors={gradient}
          style={{ flex: 1, width: DEVICE_WIDTH }}
          locations={[0, 0.4, 1]}
        />
      </SBox>
    );
  }, [route, visibility]);

  const renderErrors = useCallback(() => {
    const params = _.path('params', route);
    const isAdditions = _.pathEq(['type'], 'entries', params);
    const isAnyErrorView = isAdditions
      ? visibility.errorEntries
      : visibility.errorRemovals;

    return isAnyErrorView ? (
      <SBox mt={maxHeight * 2}>
        {isAnyErrorView ? <ViewLoadFailed /> : null}
      </SBox>
    ) : null;
  }, [visibility, route]);

  const renderHeader: TRefreshableRenderer = useCallback(
    ({ animationY, scrollToTop, isScrolled }) => {
      const marketVariant = 'market-list';
      const marketCode = _.path(['params', ROUTE_PARAMS.homeMarket], route);
      const onPress = () => {
        if (isScrolled) {
          scrollToTop();
        } else {
          openPopupByVariant(marketVariant);
        }
      };

      return (
        <>
          {!visibility.errorOffline ? (
            <>
              <SBoxAnimated
                style={Animation.headerBg(animationY)}
                height={maxHeight}
                bg={theme.colors.vulcan}
                position="absolute"
                width={1}
              />

              <SBoxAnimated
                style={Animation.title(animationY)}
                position="absolute"
                alignItems="center"
                width={1}
              >
                <Pressable onPress={onPress} testID="market-tappable-title">
                  {({ pressed }) => (
                    <WithMarketIndicator
                      variant="market-list"
                      marketCode={marketCode}
                      id="homelist"
                      notClickable
                      pressed={pressed}
                    >
                      <SListTitle>{getTitle()}</SListTitle>
                    </WithMarketIndicator>
                  )}
                </Pressable>
              </SBoxAnimated>

              <SBoxAnimated
                style={Animation.titleSmall(animationY)}
                position="absolute"
                alignItems="center"
                width={1}
              >
                <Pressable onPress={onPress}>
                  {({ pressed }) => (
                    <SRow alignItems="center" opacity={pressed ? 0.7 : 1}>
                      <Flag
                        market={marketCode}
                        width={16}
                        height={16}
                        marginTop={0}
                        variant="light"
                      />
                      <SH3 ml={8}>{getTitle()}</SH3>
                    </SRow>
                  )}
                </Pressable>
              </SBoxAnimated>
            </>
          ) : null}
          <SBoxAnimated
            style={[Animation.arrow(animationY)]}
            position="absolute"
          >
            <BackButton
              testID="nmf-back-button"
              onPress={() => Router.goBack()}
              fixed
            />
          </SBoxAnimated>
        </>
      );
    },
    [route, visibility]
  );

  const renderBody = useCallback(() => {
    const params = _.path('params', route);
    const isAdditions = _.pathEq(['type'], 'entries', params);
    const isRemovals = _.pathEq(['type'], 'exits', params);
    const noBlueDot = isAdditions || isRemovals;
    const isListVisible =
      (isAdditions ? visibility.entries : visibility.removals) ||
      visibility.entriesRemovals;
    const noChartsTracks =
      !visibility.errorOffline && !_.length(isAdditions ? additions : removals);
    const androidFigureOffset = setAndroidFigureOffset(
      maxSafeHeight,
      minHeight,
      headerAdditionalValue
    );
    const isIos = Platform.OS === 'ios';
    const offlineTopOffset = isIos ? 6 : -50;
    const homeListVariant = getHomeListPageVariant(isAdditions, !noBlueDot);

    return (
      <SBox flex={1} position="relative" pt={maxHeight} pb={32}>
        <SBox
          position="absolute"
          top={173}
          bottom={0}
          width={1}
          bg="ebonyClay"
        />
        <SBox position="absolute" top={143}>
          <Arc fill="ebonyClay" />
        </SBox>
        {visibility.errorOffline ? (
          <SBox flex={1}>
            <ViewNetworkFailed verticalOffset={offlineTopOffset} />
          </SBox>
        ) : null}
        {noChartsTracks ? (
          <ViewNoChartTracks
            market={marketName}
            vendor={_.path('homeVendor', params)}
            androidFigureOffset={androidFigureOffset}
            variant={isAdditions ? 'entries' : 'exits'}
            verticalOffset={-39}
            placeholderHeight={230}
          />
        ) : null}
        <SBox mt={-12}>
          {renderErrors()}
          {isListVisible ? (
            <SwipeableList
              testID="home-list-swipeable-list"
              cards={isAdditions ? additions : removals}
              onPress={goToHomeListTrack}
              onPressRight={toggleStarred}
              pageVariant={homeListVariant}
              starSource={
                isAdditions
                  ? EStarSourcePages.Homeentries
                  : EStarSourcePages.Homeexits
              }
            />
          ) : null}
        </SBox>
      </SBox>
    );
  }, [additions, removals, route, toggleStarred, visibility, marketName]);

  return (
    <RefreshableView
      testID="home-list-refreshable-view"
      indicatorLight
      loading={refreshing}
      onPullDown={() => {
        // refresh(isAdditions ? 'entries' : 'removals');
        refresh();
      }}
      indicatorOffsetTop={maxHeight}
      renderHeader={renderHeader}
      renderBody={renderBody}
      renderBgLayer={renderBgLayer}
      withoutBottomTabNavigator
      name={ROUTES.homelist}
      withNativeDriver
    />
  );
});
