import { SettingOutlined } from '@ant-design/icons';
import update from 'immutability-helper';
import React, { ReactElement, useCallback, useMemo, useRef } from 'react';
import { createDndContext, DndProvider } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import styled from '@emotion/styled';
import Checkbox from '../../../checkbox';
import Popover from '../../../popover';

import { ColumnSettingType } from '../../interfaces/ColumnSettingType';
import { PositionType } from '../../interfaces/PositionType';
import { ColumnSettingProps } from '../../interfaces/ColumnSettingProps';
import DndCheckbox from './components/DndCheckbox';
import Button from '../../../button';
import { findColumn } from '../../utils/findColumn';
import { ConfigContext } from '../../../config-provider';
import defaultLocale from '../../../locale/en_US';

const ResetButtonWrapper = styled.div`
  display: flex;
  justify-content: flex-end;
  margin: 6px 0;
`;

const RNDContext = createDndContext(HTML5Backend);

const resortColumnsSettings = (columnsSettings: ColumnSettingType[]): ColumnSettingType[] => {
  let fixedLeftIndex = 0;
  let noFixedIndex = 0;
  const newArr: ColumnSettingType[] = [];
  columnsSettings.forEach(item => {
    if (!item.fixed) {
      newArr.splice(noFixedIndex, 0, item);
      noFixedIndex++;
    } else if (item.fixed === 'left') {
      newArr.splice(fixedLeftIndex, 0, item);
      fixedLeftIndex++;
      noFixedIndex++;
    } else {
      newArr.push(item);
    }
  });
  return newArr;
};

export const ColumnsSetting = <T extends {}>({
  columns,
  columnSettings,
  shouldSpace,
  onColumnSettingsChange,
}: ColumnSettingProps<T>): ReactElement => {
  const manager = useRef(RNDContext);

  const showColumnKeys = useMemo(
    (): string[] =>
      columnSettings
        .filter((columnSetting): boolean => !columnSetting.hidden)
        .map((columnSetting): string => `${columnSetting.key}`),
    [columnSettings],
  );

  const { locale: { ApolloTable: locale } = { ApolloTable: defaultLocale.ApolloTable } } =
    React.useContext(ConfigContext);

  const handleConfigsChange = useCallback(
    (dragIndex: number, hoverIndex: number, fixed?: PositionType): void => {
      if (fixed || fixed === false) {
        // 设置固定列
        const tempColumnSettings = [...columnSettings];
        tempColumnSettings[dragIndex].fixed = fixed;
        // 更新顺序，fixed 放到数组两边
        const resortedColumnSettings = resortColumnsSettings(tempColumnSettings);
        onColumnSettingsChange(resortedColumnSettings);
      } else {
        // 更新列顺序
        // eslint-disable-next-line no-lonely-if
        if (!columnSettings[hoverIndex]?.fixed) {
          onColumnSettingsChange(
            resortColumnsSettings(
              update(columnSettings, {
                $splice: [
                  [dragIndex, 1],
                  [hoverIndex, 0, columnSettings[dragIndex]],
                ],
              }),
            ),
          );
        }
      }
    },
    [columnSettings, onColumnSettingsChange],
  );

  return (
    <DndProvider backend={HTML5Backend} manager={manager.current.dragDropManager}>
      <Popover
        title={
          <ResetButtonWrapper>
            <a onClick={() => onColumnSettingsChange([])}>{locale?.reset}</a>
          </ResetButtonWrapper>
        }
        trigger="click"
        content={
          <>
            <Checkbox.Group
              value={showColumnKeys}
              onChange={(value): void => {
                onColumnSettingsChange(
                  columnSettings.map(
                    (columnSetting): ColumnSettingType => ({
                      ...columnSetting,
                      hidden: value.indexOf(`${columnSetting.key}`) < 0,
                    }),
                  ),
                );
              }}
            >
              {columnSettings.map(
                (item, index): ReactElement => (
                  <DndCheckbox
                    index={index}
                    key={item.key}
                    value={item.key}
                    fixed={item?.fixed}
                    onConfigsChange={handleConfigsChange}
                  >
                    {findColumn(columns, item.key).title}
                  </DndCheckbox>
                ),
              )}
            </Checkbox.Group>
          </>
        }
        placement="bottomRight"
      >
        <Button style={shouldSpace ? { marginLeft: 8 } : undefined} icon={<SettingOutlined />} />
      </Popover>
    </DndProvider>
  );
};
