import React, { useEffect } from 'react';
import { useIsFocused } from '@react-navigation/native';
import { connect } from 'react-redux';
import { compose } from 'redux';
import { createStructuredSelector } from 'reselect';
import { withReducer } from '../../app/core/with-reducer';
import { withEpics } from '../../app/core/with-epics';
import { fp as _ } from '../../common/utils/fp';
import { Nmf } 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 {
  makeRefreshSelector,
  makeConfigSelector,
  makeDataVisibilitySelector,
  makeDataSelector,
  makeSettingsSelector,
  makeSettingsVisibilitySelector,
  makeMarketsDataSelector,
  makeMarketsDataVisibilitySelector,
  makePageVariantSelector,
  makeLatestDateSelector,
} from '../selectors';
import { TNavigation, TRootNmfState, TState } from '../types';
import { NEntityInfinite, TEntityVisibility } from '../../common/types';
import { composeContexts } from '../../common/utils/react-better-context';
import {
  ContextHeader,
  ContextMetrics,
  ContextRegions,
  ContextList,
  ContextInfoPopup,
} from '../contexts';
import { withStarredPlaylists } from '../../common/submodules/starring-playlists/hoc/with-starred-playlists';
import { withStreamLatestDate } from '../../common/hoc/with-stream-latest-date';
import { MODULE_NAME } from '../constants';
import { makeTrackDataSelector } from '../../track/selectors';
import { TData } from '../../track/types';
import { useNavKeyMap } from '../../common/hooks/use-nav-key-map';
import { ROUTES } from '../../app/constants';
import { useStateLocked } from '../../common/hooks/use-state-locked';

type TStructured = {
  visibilityData: TEntityVisibility;
  visibilitySettings: TEntityVisibility;
  refreshing: boolean;
  config: TState['config'];
  data: TState['data'];
  settings: TState['settings'];
  trackData: TData | {};
  visibilityMarketsData: TEntityVisibility;
  marketsData: TState['marketsData'];
  pageVariant: string;
  latestDate: TState['latestDate'];
};
type TConnected = TStructured & {
  setConfig: (config: TState['config']) => void;
  getSettings: () => void;
  getMarketsData: () => void;
  getLatestDate: () => void;
  getData: NEntityInfinite.TEntityInfiniteGet;
  flush: () => void;
  refresh: () => void;
  navigation: TNavigation;
  route: { name: string; params: { nmfPageVariant: string } };
};
type TPropsExternal = {};

const mapStateToProps = createStructuredSelector<TRootNmfState, TStructured>({
  visibilityData: makeDataVisibilitySelector(),
  visibilitySettings: makeSettingsVisibilitySelector(),
  refreshing: makeRefreshSelector(),
  config: makeConfigSelector(),
  data: makeDataSelector(),
  settings: makeSettingsSelector(),
  trackData: makeTrackDataSelector(),
  visibilityMarketsData: makeMarketsDataVisibilitySelector(),
  marketsData: makeMarketsDataSelector(),
  pageVariant: makePageVariantSelector(),
  latestDate: makeLatestDateSelector(),
  //†prop
});
const mapDispatchToProps = {
  setConfig: ACTION.setConfig,
  getSettings: ACTION.getSettings,
  flush: ACTION.flush,
  refresh: ACTION.refresh,
  getData: ACTION.getData,
  getMarketsData: ACTION.getMarketsData,
  getLatestDate: ACTION.getLatestDate,
  //†action
};

const Connected: React.FC<TConnected> = ({ flush, ...rest }) => {
  const {
    // navigation,
    getSettings,
    getData,
    visibilityData,
    visibilitySettings,
    config,
    data,
    settings,
    trackData,
    setConfig,
    marketsData,
    visibilityMarketsData,
    getMarketsData,
    getLatestDate,
    pageVariant,
    route,
  } = rest;

  useNavKeyMap({
    page: route.name.includes(ROUTES.nmf) ? ROUTES.nmf : ROUTES.hh,
    route,
  });

  const isFocused = useIsFocused();
  const [lockedPageVariant] = useStateLocked(pageVariant, isFocused);

  useEffect(() => {
    if (!lockedPageVariant) return;
    getSettings();
    getMarketsData();
    getLatestDate();
  }, [lockedPageVariant]);

  useEffect(() => {
    return () => {
      flush();
    };
  }, []);

  if (!lockedPageVariant) return null;

  return composeContexts(
    [
      [
        ContextHeader,
        {
          visibilityData,
          visibilitySettings,
          data,
          getData,
          getSettings,
          config,
          trackData,
          visibilityMarketsData,
        },
      ],
      [
        ContextMetrics,
        {
          visibilityData,
          visibilitySettings,
          settings,
          data,
          config,
        },
      ],
      [
        ContextRegions,
        {
          visibilityData,
          visibilitySettings,
          data,
          settings,
          config,
          setConfig,
          getData,
          pageVariant: lockedPageVariant,
        },
      ],
      [
        ContextList,
        {
          visibilityData,
          data,
          config,
          pageVariant: lockedPageVariant,
        },
      ],
      [
        ContextInfoPopup,
        {
          visibilityMarketsData,
          marketsData,
          config,
        },
      ],
    ],
    <Nmf {...rest} pageVariant={lockedPageVariant} />
  );
};

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