import React, { useContext } from 'react'
import { View } from 'react-native'

import { ReactNavigationProps } from '../Navigation'
import { CommonScreenContainer } from '../components/CommonScreenContainer'
import { FilterText } from '../components/Filter'
import { HeaderNav } from '../components/HeaderNav'
import {
  sortByChangePercentage,
  sortByName,
  sortByReleaseDate,
  sortByStreams,
  TrackListItem,
} from '../components/TrackList'
import { DateListItem } from '../components/listitems/DateListItem'
import { Item, StreamsListItem } from '../components/listitems/StreamsListItem'
import { ScreenNames } from '../constants/ScreenNames'
import { ArtistContext } from '../contexts/ArtistContext'
import {
  EventType,
  sendAnalyticsEvent,
  useAnalytics,
} from '../hooks/useAnalytics'
import { useScreenRefreshControl } from '../hooks/useScreenRefreshControl'
import { useScreenTimeInterval } from '../hooks/useScreenTimeInterval'
import { useTracksScreenData } from '../hooks/useTracksScreenData'
import { Strings } from '../i18n'
import { getTracksWithAllDsp } from '../streams'
import { defaultTimeInterval } from '../types/TimeInterval'
import { Mode } from '../types/helpers'
import { Dsp } from '../types/types'
import { filterTopTrendingTracks } from './TrackListScreen'
import { GetTracksFn, TrackListStreamsTab } from './tabs/TrackListStreamsTab'

const TracksScreenModes = [
  'streams',
  'release',
  'all',
  'favorites',
  'trending',
] as const
export type TracksScreenMode = typeof TracksScreenModes[number]

const screenName = 'Tracks Screen'

export const TracksScreen: React.FC<
  ReactNavigationProps<ScreenNames.Tracks>
> = ({ navigation, route }) => {
  const artist = useContext(ArtistContext)

  const [timeInterval, setTimeInterval] = useScreenTimeInterval(
    defaultTimeInterval,
    {
      screenName,
      artistName: artist.name,
      entityId: artist.sonyArtistId,
    }
  )

  const modeOptions: Record<
    TracksScreenMode,
    {
      title: string
      titleInfoModal?: {
        title: string
        text: string
      }
      getTracks: GetTracksFn
      showDspSelector: boolean
      analyticsTabName: string
      ListItem: React.FC<Item>
      displayRank: boolean
      top?: React.ReactNode
    }
  > = {
    [Mode.STREAMS]: {
      title: Strings.Shared.MostStreamed,
      getTracks: (x: TrackListItem[]) => {
        return x.sort(sortByStreams)
      },
      showDspSelector: true,
      analyticsTabName: 'Streams',
      ListItem: StreamsListItem,
      displayRank: true,
    },
    [Mode.RELEASE]: {
      title: Strings.Shared.NewestReleases,
      top: <FilterText>{Strings.Shared.AllTime}</FilterText>,
      getTracks: (tracks: TrackListItem[]) => {
        return tracks.sort(sortByReleaseDate)
      },
      showDspSelector: false,
      analyticsTabName: 'Release Date',
      ListItem: DateListItem,
      displayRank: false,
    },
    [Mode.ALL]: {
      title: Strings.Shared.AllTracks,
      getTracks: (tracks: TrackListItem[]) => {
        return tracks.sort(sortByName)
      },
      showDspSelector: true,
      analyticsTabName: 'All',
      ListItem: StreamsListItem,
      displayRank: false,
    },
    [Mode.FAVORITES]: {
      title: Strings.Shared.Favorites,
      getTracks: (tracks: TrackListItem[]) => {
        return tracks.filter((track) => track.track.isFavorite).sort(sortByName)
      },
      showDspSelector: false,
      analyticsTabName: 'Favorites',
      ListItem: StreamsListItem,
      displayRank: false,
    },
    [Mode.TRENDING]: {
      title: Strings.Shared.TopTrending,
      titleInfoModal: {
        title: Strings.Shared.TopTrending,
        text: Strings.Info.TopTrending,
      },
      getTracks: (tracks: TrackListItem[]) =>
        filterTopTrendingTracks(tracks).sort(sortByChangePercentage),
      showDspSelector: true,
      analyticsTabName: 'Trending',
      ListItem: StreamsListItem,
      displayRank: false,
    },
  }

  const options = modeOptions[route.params.mode as TracksScreenMode]
  const { data, showToast, error, retry, refreshing } =
    useTracksScreenData(timeInterval)

  const onPullToRefresh = () => {
    sendAnalyticsEvent(EventType.PULL_TO_REFRESH, {
      artist_selected: artist.name,
      timeframe_selected: timeInterval,
      page: 'Tracks Screen',
      subject: 'user',
      verb: 'refreshed',
      object: 'tracks',
    })
    retry()
  }

  const { refreshControl } = useScreenRefreshControl(
    onPullToRefresh,
    refreshing
  )

  const tracksWithAll = data?.tracks
    ? getTracksWithAllDsp(data.tracks)
    : undefined

  return (
    <CommonScreenContainer screenName={screenName}>
      <HeaderNav
        title={options.title}
        showToast={showToast}
        navigation={navigation}
        style={{
          zIndex: 10,
        }}
        top={options.top}
        titleInfoModal={options.titleInfoModal}
        timeInterval={timeInterval}
        setTimeInterval={setTimeInterval}
      />
      <View
        style={{
          flex: 1,
          paddingHorizontal: 8,
        }}
      >
        <TrackListStreamsTab
          tracks={tracksWithAll}
          onPressTrack={(isrc: string) =>
            navigation.navigate(ScreenNames.Track, {
              isrc,
            })
          }
          refreshControl={refreshControl}
          error={error}
          onLoad={(dsp: Dsp) =>
            useAnalytics(
              EventType.TAB_VIEWED,
              {
                screen: screenName,
                dsp,
                tab: options.analyticsTabName,
                subject: 'user',
                verb: 'viewed',
                object: 'dsp',
              },
              true,
              timeInterval
            )
          }
          {...options}
        />
      </View>
    </CommonScreenContainer>
  )
}
