import React, { useContext, memo } from 'react';
import isEqual from 'lodash/isEqual';
import EasyvComponent from './EasyComponent';
import { ScreenContext } from './Context';
import { mappingData, filterData } from 'utils/convert';
import Transition from './Transition';
import { Utils } from '@easyv/react-gui';
import { DataFrom } from 'models/component.types';
import { filterContainersResult } from 'utils/containers';
import { useSelector } from 'react-redux';
import { RootState } from 'models';

function Component({
  edit,
  modalEdit,
  hideDefault,
  dataFilterResult, // 当前数据容器处理完的数据
  mountAnimation = {},
  component,
  childrenComponent,
  filters,
  childrenFilters,
  iState,
  iActiveState,
  bindedInteractionState,
  dataCallbackValues,
  filterCallbackValues,
  interactionCallbackValues,
  childrenDataCallbackValues,
  childrenFilterCallbackValues,
  childrenInteractionCallbackValues,
}) {
  const createApp = useSelector<RootState>((state) => state.createApp) as RootState['createApp'];
  const { editId } = createApp;

  const {
    emitEvent,
    emitCallback,
    getComponentData,
    updateConfig,
    updateAction,
    updateTrigger,
    updateData,
    tenantId,
  } = useContext(ScreenContext);
  const {
    id,
    uniqueTag,
    base,
    config,
    dataFrom,
    dataConfigs = {},
    dataType,
    autoUpdate = {},
    useFilter,
    dataContainers = [],
    events,
    actions = [],
    from,
    name,
  } = component;
  const { width, height, left, top } = Utils.getComponentDimension(config);
  const { data = [], fields = [] } = dataConfigs[dataType] || {};
  const isDataContainer = dataFrom === DataFrom.DATA_CONTAINER;
  let componentData = isDataContainer
    ? filterContainersResult(dataContainers.map((d) => dataFilterResult?.[d.id]))
    : data;

  if (useFilter) {
    componentData = filterData({
      data: componentData,
      filters,
      callbackValues: filterCallbackValues,
      id,
      name,
    });

    if (!componentData || componentData.isError) {
      componentData = [];
    }
  }

  componentData = mappingData(componentData, fields);

  const childrenConfig = childrenComponent.map((child) => {
    const {
      id,
      base,
      config,
      dataConfigs,
      dataType,
      autoUpdate,
      actions = [],
      events = [],
    } = child;

    return {
      id,
      base,
      configuration: Utils.getComponentConfig(config),
      dataType,
      dataConfig: dataConfigs[dataType],
      autoUpdate,
      edit: modalEdit === id,
      actions,
      events,
    };
  });

  const childrenData = childrenComponent.map((child, i) => {
    const {
      id: childId,
      dataConfigs = {},
      dataType,
      useFilter,
      dataFrom,
      dataContainers = [],
      name,
    } = child;
    const { data: childData = [], fields = [] } = dataConfigs[dataType] || {};

    const isDataContainer = dataFrom === DataFrom.DATA_CONTAINER;
    let childComponentData = isDataContainer
      ? filterContainersResult(dataContainers.map((d) => dataFilterResult?.[d.id]))
      : childData;

    if (useFilter) {
      childComponentData = filterData({
        data: childComponentData,
        filters: childrenFilters[i],
        callbackValues: childrenFilterCallbackValues[i],
        id,
        name,
      });
      if (!childComponentData || childComponentData.isError) {
        childComponentData = [];
      }
    }
    childComponentData = mappingData(childComponentData, fields);

    return {
      id: childId,
      dataType: dataType,
      data: childComponentData,
      callbackValues: childrenInteractionCallbackValues[i],
    };
  });

  const childrenEvents = childrenComponent.map((child) => {
    const { id, base, events = [] } = child;

    return {
      id,
      base,
      events,
    };
  });
  return (
    <Transition config={mountAnimation}>
      <EasyvComponent
        editId={editId}
        id={id}
        tenantId={from ? tenantId : undefined}
        width={width}
        height={height}
        left={left}
        top={top}
        edit={edit}
        modalEdit={modalEdit}
        uniqueTag={uniqueTag}
        hideDefault={hideDefault}
        base={base}
        data={componentData}
        dataType={dataType}
        autoUpdate={autoUpdate}
        configuration={Utils.getComponentConfig(config)}
        events={events}
        dataCallbackValues={dataCallbackValues}
        interactionCallbackValues={interactionCallbackValues}
        iState={iState}
        iActiveState={iActiveState}
        actions={actions}
        bindedInteractionState={bindedInteractionState}
        childrenData={childrenData}
        childrenConfig={childrenConfig}
        childrenEvents={childrenEvents}
        childrenDataCallbackValues={childrenDataCallbackValues}
        onRelative={emitCallback}
        emitEvent={emitEvent}
        updateComponentData={getComponentData}
        updateConfig={updateConfig}
        updateAction={updateAction}
        updateData={updateData}
        updateTrigger={updateTrigger}
      />
    </Transition>
  );
}

function equalLength(a, b) {
  return a.length === b.length;
}
function areEqual(props, nextProps) {
  // todo: xy改变不用重新渲染
  const isChildrenEqual =
    equalLength(props.childrenComponent, nextProps.childrenComponent) &&
    nextProps.childrenComponent.every((component, i) => component === props.childrenComponent[i]);

  const isChildrenDataCallbackEqual = nextProps.childrenDataCallbackValues.every(
    (childDataCallbackValues, i) =>
      isEqual(childDataCallbackValues, props.childrenDataCallbackValues[i]),
  );
  const isChildrenInteractionCallbackEqual = nextProps.childrenInteractionCallbackValues.every(
    (childInteractionCallbackValues, i) =>
      isEqual(childInteractionCallbackValues, props.childrenInteractionCallbackValues[i]),
  );
  const isChildrenFilterCallbackEqual = nextProps.childrenFilterCallbackValues.every(
    (childFilterCallbackValues, i) =>
      isEqual(childFilterCallbackValues, props.childrenFilterCallbackValues[i]),
  );

  return (
    props.component === nextProps.component &&
    isChildrenEqual &&
    isEqual(nextProps.filterCallbackValues, props.filterCallbackValues) &&
    isEqual(nextProps.dataCallbackValues, props.dataCallbackValues) &&
    isEqual(nextProps.interactionCallbackValues, props.interactionCallbackValues) &&
    isChildrenDataCallbackEqual &&
    isChildrenInteractionCallbackEqual &&
    isChildrenFilterCallbackEqual &&
    isEqual(nextProps.iState, props.iState) &&
    isEqual(nextProps.iActiveState, props.iActiveState) &&
    isEqual(nextProps.bindedInteractionState, props.bindedInteractionState) &&
    isEqual(nextProps.filters, props.filters) &&
    isEqual(nextProps.childrenFilters, props.childrenFilters) &&
    isEqual(nextProps.modalEdit, props.modalEdit) &&
    isEqual(nextProps.dataFilterResult, props.dataFilterResult) &&
    isEqual(nextProps.editId, props.editId)
  );
}

export default memo(Component, areEqual);
