import React, { Suspense } from 'react';
import { useSelector, connect } from 'react-redux';
import {
  ScreenProvider,
  ScreenDataProvider,
  PanelDataProvider,
  DataContainerProvider,
  ComponentDataProvider,
  FilterDataProvider,
  CallbackProvider,
  InteractionProvider,
} from 'components/ScreenPreview/Context';
import { getComponentData } from 'models/component';
import { emitCallback } from 'models/callback';
import { switchPanelState } from 'models/interaction';
import DataContainer from '../DataContainer';
import { getPanelInfoForScreenPreview } from 'models/panel';
import { RootState } from 'models';

// 只有预览页在使用
interface Props {
  getScreenInfo: any;
  emitEvent: any;
  getComponentData?: (id: number) => void;
  getPanelInfo?: (id: number) => void;
  switchPanelState?: (id: number) => void;
  emitCallback?: (id: number, value: any) => void;
}

export const ScreenContainer: React.FC<Props> = ({
  getComponentData,
  getPanelInfo,
  switchPanelState,
  emitCallback,
  getScreenInfo,
  emitEvent,
  children,
}) => {
  const state = useSelector<RootState>((state) => state) || {};
  const {
    screenDetail,
    componentsById,
    screensById,
    panelsById,
    filters,
    callback,
    interactions,
    dataContainers,
  } = state as RootState;
  const { id } = screenDetail;
  const { callbackKeys, callbackValues } = callback;
  const screen = screensById[id];
  const { filterResult: dataFilterResult, list } = dataContainers;
  const currentScreenIds = Object.keys(screensById) || [];
  const dataContainerList = list.filter((d) => currentScreenIds.includes(d.screenId + ''));
  const { filter: _filter = {}, data: _data = {} } = callbackKeys || {};

  const currentCallbackFilter = (id) => {
    const _callbackValues = {};
    const callbackFilterKeys = _filter[`containers_${id}`] || [];
    callbackFilterKeys.map((key) => {
      _callbackValues[key] = callbackValues[key];
    });
    return _callbackValues;
  };

  const currentCallbackDataValues = (id) => {
    const dataIds = _data[`containers_${id}`] || [];
    return dataIds.map((key) => callbackValues[key]);
  };

  return (
    <ScreenProvider
      getComponentData={getComponentData}
      getScreenData={getScreenInfo}
      getPanelData={getPanelInfo}
      emitEvent={emitEvent}
      emitCallback={emitCallback}
      switchPanelState={switchPanelState}
      tenantId={screen?.tenantId}>
      <ScreenDataProvider screensById={screensById}>
        <PanelDataProvider panelsById={panelsById}>
          <ComponentDataProvider componentsById={componentsById}>
            <CallbackProvider callbackKeys={callbackKeys} callbackValues={callbackValues}>
              <FilterDataProvider filters={filters.list}>
                <InteractionProvider interactions={interactions}>
                  <DataContainerProvider dataFilterResult={dataFilterResult}>
                    <Suspense fallback="">{children}</Suspense>
                  </DataContainerProvider>
                </InteractionProvider>
              </FilterDataProvider>
            </CallbackProvider>
          </ComponentDataProvider>
        </PanelDataProvider>
      </ScreenDataProvider>
      {dataContainerList.map((d) => {
        /**
         * 该组件处理数据容器
         * 1、定时更新
         * 2、回调变化
         */
        const currnetFilters: any[] = d.useFilter
          ? d.filters
              .filter((f) => f.enable)
              .map((x) => filters.list.find((v) => v.id === x.id))
              .filter((d) => d)
          : [];
        const data = d.dataConfigs[d.dataType]?.data;
        return (
          <DataContainer
            currentCallbackFilter={currentCallbackFilter(d.id)}
            currentCallbackDataValues={currentCallbackDataValues(d.id)}
            filters={currnetFilters}
            data={data}
            container={d}
            key={d.id}
            autoUpdate={d.autoUpdate}
          />
        );
      })}
    </ScreenProvider>
  );
};

const mapDispatchToProps = {
  getComponentData,
  getPanelInfo: getPanelInfoForScreenPreview,
  emitCallback,
  switchPanelState,
};

const WrapperContainer = connect(null, mapDispatchToProps)(ScreenContainer);

const WrappedScreenContext = (props: Props) => {
  return (W: React.FunctionComponent) => (
    <WrapperContainer {...props}>
      <W />
    </WrapperContainer>
  );
};

export default WrappedScreenContext;
