import React, { useEffect } from 'react';
import { connect } from 'react-redux';
import { compose } from 'redux';
import { createStructuredSelector } from 'reselect';
import { NavigationProp, ParamListBase } from '@react-navigation/native';
import { withReducer } from '../../app/core/with-reducer';
import { withEpics } from '../../app/core/with-epics';
import { fp as _ } from '../../common/utils/fp';
import { PlaylistPlacement } from '../components';
import reducer, { ACTION } from '../reducer';
import * as epics from '../epics';
import { withErrorBoundary } from '../../common/hoc/with-error-boundary';
import { withNavigationSync } from '../../common/hoc/with-navigation-sync';
import {
  makeVisibilityConfigSelector,
  makeRefreshSelector,
  makeDataSelector,
  makeTrackDataSelector,
  makeTrackStreamsSelector,
  makeTracklistExtendedSelector,
  makeIsTrackStarredSelector,
  makeIsPlaylistStarredSelector,
  makeConfigSelector,
} from '../selectors';
import { NEntityInfinite, TEntityVisibility } from '../../common/types';
import { ACTION as COMMON_ACTION } from '../../common/reducer';
import {
  TNavOnlyParams,
  TRootPlaylistPlacementState,
  TState,
  TRoute,
} from '../types';
import { FETCH_TYPE } from '../../common/constants';
import { useNavKeyMap } from '../../common/hooks/use-nav-key-map';
import { ROUTES } from '../../app/constants';
import { withStarred } from '../../common/submodules/starring-tracks/hoc/with-starred';
import { withStreamLatestDate } from '../../common/hoc/with-stream-latest-date';
import { ORDER_BY } from '../../playlist-tracklist-core/constants';
import { TTracklistExtended } from '../../playlist-tracklist-core/types';
import { TToggleStarred } from '../../common/submodules/starring-tracks/types';

type TStructured = {
  visibility: TEntityVisibility;
  refreshing: boolean;
  data: TState['data'];
  trackData: TState['trackData'];
  playlistData: TState['playlistData'];
  tracklist: TTracklistExtended;
  trackStreams: TState['trackStreams'];
  isTrackStarred: boolean;
  config: TState['config'];
};
type TConnected = TStructured & {
  getData: (params: Partial<TNavOnlyParams>) => void;
  getTrackData: () => void;
  getPlaylistData: () => void;
  getTracklist: NEntityInfinite.TEntityInfiniteGet;
  getTrackStreams: () => void;
  setConfig: (placementVariant: any) => void;
  flush: () => void;
  refresh: () => void;
  navigation: NavigationProp<ParamListBase>;
  route: TRoute;
  toggleStarred: TToggleStarred;
};
type TPropsExternal = {};

const mapStateToProps = createStructuredSelector<
  TRootPlaylistPlacementState,
  TStructured
>({
  visibility: makeVisibilityConfigSelector(),
  refreshing: makeRefreshSelector(),
  data: makeDataSelector(),
  trackData: makeTrackDataSelector(),
  playlistData: makeIsPlaylistStarredSelector(),
  tracklist: makeTracklistExtendedSelector(),
  trackStreams: makeTrackStreamsSelector(),
  isTrackStarred: makeIsTrackStarredSelector(),
  config: makeConfigSelector(),
  //†prop
});
const mapDispatchToProps = {
  getData: ACTION.getData,
  getTrackData: ACTION.getTrackData,
  getPlaylistData: ACTION.getPlaylistData,
  getTracklist: ACTION.getTracklist,
  getTrackStreams: ACTION.getTrackStreams,
  flush: ACTION.flush,
  refresh: ACTION.refresh,
  toggleStarred: COMMON_ACTION.toggleStarred,
  setConfig: ACTION.setConfig,
  //†action
};

const Connected: React.FC<TConnected> = ({
  getData,
  getTrackData,
  getPlaylistData,
  getTracklist,
  getTrackStreams,
  flush,
  setConfig,
  ...rest
}) => {
  const { navigation, route } = rest;
  const params = _.path('params', route);
  const { placementVariant } = params;

  useNavKeyMap({ page: ROUTES.playlistplacement, route });

  useEffect(() => {
    getData(params);
    getTrackData();
    getPlaylistData();
    getTracklist({ orderBy: ORDER_BY.position }, FETCH_TYPE.force);
    getTrackStreams();
    setConfig({ placementVariant });
    setTimeout(() => {
      navigation.setParams({ noAnimation: false });
    }, 100);
    return () => flush();
  }, []);

  return <PlaylistPlacement {...rest} getTracklist={getTracklist} />;
};

export default compose(
  _.hoistStatics(PlaylistPlacement),
  withReducer('playlistPlacement', reducer),
  withEpics('playlistPlacement', epics),
  withErrorBoundary('playlistPlacement'),
  withNavigationSync(),
  withStarred,
  withStreamLatestDate,
  connect(
    mapStateToProps,
    mapDispatchToProps
  )
)(Connected) as React.FC<TPropsExternal>;
