import React, { useEffect } from 'react';
import { connect } from 'react-redux';
import { compose } from 'redux';
import { createStructuredSelector } from 'reselect';
import { Undefinable } from 'tsdef';
import { withReducer } from '../../app/core/with-reducer';
import { withEpics } from '../../app/core/with-epics';
import { fp as _ } from '../../common/utils/fp';
import { Playlists } from '../components/playlists';
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 {
  makeActiveVisibilitySelector,
  makeRefreshSelector,
  makeCurrentExtendedSelector,
  makeConfigSelector,
  makePastExtendedSelector,
  makePlaylistsOptionsSelector,
  makeIsFailedSelector,
  makeCategoryOptionsSelector,
  makeIsDirtySortingSelector,
} from '../selectors';
import {
  TNavigation,
  TRootPlaylistsState,
  TState,
  TActiveVisibilityConfig,
  TPlaylistsOption,
} from '../types';
import { NEntityInfinite, NSelect } from '../../common/types';
import { FETCH_TYPE } from '../../common/constants';
import { composeContexts } from '../../common/utils/react-better-context';
import { ContextHeader, ContextCurrent, ContextPast } from '../contexts';
import { withStarredPlaylists } from '../../common/submodules/starring-playlists/hoc/with-starred-playlists';
import { makeTrackSelector } from '../../track/selectors';
import { TState as TTrackState } from '../../track/types';
import { withStreamLatestDate } from '../../common/hoc/with-stream-latest-date';
import { makeMarketCodeSelector } from '../../common/selectors';
import { useNavKeyMap } from '../../common/hooks/use-nav-key-map';
import { ROUTES } from '../../app/constants';
import { TRoute } from '../../playlist-placement/types';

type TStructured = {
  activeVisibility: TActiveVisibilityConfig;
  refreshing: boolean;
  current: TState['current'];
  past: TState['past'];
  config: TState['config'];
  trackData: TTrackState['track'];
  isFailed: boolean;
  playlistOptions: TPlaylistsOption[];
  categoryOptions: NSelect.TOption[];
  market: Undefinable<string>;
  isDirtySorting: boolean;
};
type TConnected = TStructured & {
  setConfig: (config: TState['config']) => void;
  getSettings: NEntityInfinite.TEntityInfiniteGet;
  getData: NEntityInfinite.TEntityInfiniteGet;
  flush: () => void;
  refresh: () => void;
  navigation: TNavigation;
  route: TRoute;
};
type TPropsExternal = {};

const mapStateToProps = createStructuredSelector<
  TRootPlaylistsState,
  TStructured
>({
  activeVisibility: makeActiveVisibilitySelector(),
  refreshing: makeRefreshSelector(),
  current: makeCurrentExtendedSelector(),
  past: makePastExtendedSelector(),
  config: makeConfigSelector(),
  trackData: makeTrackSelector(),
  isFailed: makeIsFailedSelector(),
  playlistOptions: makePlaylistsOptionsSelector(),
  categoryOptions: makeCategoryOptionsSelector(),
  market: makeMarketCodeSelector(),
  isDirtySorting: makeIsDirtySortingSelector(),
  //†prop
});
const mapDispatchToProps = {
  setConfig: ACTION.setConfig,
  getSettings: ACTION.getSettings,
  flush: ACTION.flush,
  refresh: ACTION.refresh,
  getData: ACTION.getData,
  //†action
};

const Connected: React.FC<TConnected> = ({ flush, ...rest }) => {
  const {
    // navigation,
    getSettings,
    getData,
    activeVisibility,
    config,
    past,
    current,
    route,
  } = rest;

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

  useEffect(() => {
    getSettings(null, FETCH_TYPE.force);
    return () => {
      flush();
    };
  }, []);

  return composeContexts(
    [
      [
        ContextHeader,
        {
          activeVisibility,
          entityCurrent: current,
          entityPast: past,
          getData,
          getSettings,
          config,
        },
      ],
      [
        ContextCurrent,
        {
          activeVisibility,
          entity: current,
          getData,
          getSettings,
        },
      ],
      [
        ContextPast,
        {
          activeVisibility,
          entity: past,
          getData,
          getSettings,
        },
      ],
    ],
    <Playlists {...rest} />
  );
};

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