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 { TrackPlaylists } from '../components';
import reducer, { ACTION } from '../reducer';
import * as epics from '../epics';
import { withErrorBoundary } from '../../common/hoc/with-error-boundary';
import {
  makeFilteredSelector,
  makeActiveTabSelector,
  makeVisibilityFilteredSelector,
  makeAddsExtendedSelector,
  makeVisibilityAddsSelector,
  makeVisibilityRemovalsSelector,
  makeVisibilityTopSelector,
  makeTopExtendedSelector,
  makeRemovalsExtendedSelector,
  makeMarketsSelector,
} from '../selectors';
import {
  TMarkets,
  TRootTrackPlaylistsState,
  TSetActiveTab,
  TSetMarkets,
  TState,
} from '../types';
import {
  ContextHeader,
  ContextPills,
  ContextFiltered,
  ContextLatestAdds,
  ContextLatestRemovals,
  ContextTop,
} from '../contexts';
import { composeContexts } from '../../common/utils/react-better-context';
import {
  makeLastStreamDateAmazonSelector,
  makeLastStreamDateSelector,
} from '../../common/selectors/stream-latest-date/stream-latest-date-selectors';
import {
  makeRefreshSelector,
  makeErrorGlobalSelector,
  makeIsSonySelector,
  makeTrackSelector,
  makeDistributorFlagsSelector,
} from '../../track/selectors';
import { TState as TTrackState } from '../../track/types';
import { TEntityVisibility } from '../../common/types';
import { makeMarketCodeSelector } from '../../common/selectors';
import { setInitialMarkets } from '../transducers';
import { withNavigation } from '../../common/hoc/with-navigation';
import { withStreamLatestDate } from '../../common/hoc/with-stream-latest-date';

type TStructured = {
  filtered: TState['filtered'];
  filteredVisibility: TEntityVisibility;
  adds: TState['adds'];
  addsVisibility: TEntityVisibility;
  removals: TState['removals'];
  removalsVisibility: TEntityVisibility;
  top: TState['top'];
  topVisibility: TEntityVisibility;
  activeTab: TState['activeTab'];
  lastStreamDate: Undefinable<string>;
  lastStreamAmazonDate: Undefinable<string>;
  isSony: Undefinable<boolean>;
  track: TTrackState['track'];
  distributorFlags: TTrackState['distributorFlags'];
  trackRefresh: TTrackState['refresh'];
  globalError: boolean;
  markets: TMarkets;
  userMarket: Undefinable<string>;
};
type TConnected = TStructured & {
  setActiveTab: TSetActiveTab;
  setMarkets: TSetMarkets;
};
type TPropsExternal = {};

const mapStateToProps = createStructuredSelector<
  TRootTrackPlaylistsState,
  TStructured
>({
  filtered: makeFilteredSelector(),
  filteredVisibility: makeVisibilityFilteredSelector(),
  adds: makeAddsExtendedSelector(),
  addsVisibility: makeVisibilityAddsSelector(),
  removals: makeRemovalsExtendedSelector(),
  removalsVisibility: makeVisibilityRemovalsSelector(),
  top: makeTopExtendedSelector(),
  topVisibility: makeVisibilityTopSelector(),
  activeTab: makeActiveTabSelector(),
  lastStreamDate: makeLastStreamDateSelector(),
  lastStreamAmazonDate: makeLastStreamDateAmazonSelector(),
  isSony: makeIsSonySelector(),
  track: makeTrackSelector(),
  distributorFlags: makeDistributorFlagsSelector(),
  trackRefresh: makeRefreshSelector(),
  globalError: makeErrorGlobalSelector(),
  markets: makeMarketsSelector(),
  userMarket: makeMarketCodeSelector(),
  //†prop
});
const mapDispatchToProps = {
  setActiveTab: ACTION.setActiveTab,
  setMarkets: ACTION.setMarkets,
  //†action
};

const Connected: React.FC<TConnected> = ({ globalError, ...rest }) => {
  const { markets, userMarket, setMarkets } = rest;

  if (globalError) return null;

  useEffect(() => {
    if (markets.dirty) return;
    setMarkets(setInitialMarkets(userMarket!, 'spotify'));
  }, []);

  const {
    activeTab,
    setActiveTab,
    filtered,
    filteredVisibility,
    adds,
    addsVisibility,
    removals,
    removalsVisibility,
    top,
    topVisibility,
    lastStreamDate,
    lastStreamAmazonDate,
    isSony,
    distributorFlags,
    track,
    trackRefresh,
  } = rest;

  return composeContexts(
    [
      [
        ContextHeader,
        {
          activeTab,
          setActiveTab,
          loading: distributorFlags.loading || track.loading,
          refresh: trackRefresh,
        },
      ],
      [
        ContextPills,
        {
          activeTab,
          markets,
          loading: distributorFlags.loading || track.loading,
          refresh: trackRefresh,
        },
      ],
      [
        ContextFiltered,
        {
          entity: filtered,
          visibility: filteredVisibility,
          activeTab,
          trackName: _.path('data.name', track),
          markets,
        },
      ],
      [
        ContextLatestAdds,
        {
          entity: adds,
          visibility: addsVisibility,
          activeTab,
          lastStreamDate,
          lastStreamAmazonDate,
        },
      ],
      [
        ContextLatestRemovals,
        {
          entity: removals,
          visibility: removalsVisibility,
          activeTab,
        },
      ],
      [
        ContextTop,
        {
          entity: top,
          visibility: topVisibility,
          activeTab,
          lastStreamDate,
          lastStreamAmazonDate,
          isSony,
        },
      ],
    ],
    <TrackPlaylists />
  );
};

export default compose(
  _.hoistStatics(TrackPlaylists),
  withReducer('trackPlaylists', reducer),
  withEpics('trackPlaylists', epics),
  withNavigation,
  withStreamLatestDate,
  withErrorBoundary('trackPlaylists'),
  connect(
    mapStateToProps,
    mapDispatchToProps
  )
)(Connected) as React.FC<TPropsExternal>;
