/* eslint-disable react/self-closing-comp */
/* eslint-disable @typescript-eslint/ban-ts-comment */
/* eslint-disable import/no-extraneous-dependencies */
/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/unbound-method */
import React, {
  Children,
  Component,
  JSXElementConstructor,
  ReactElement,
} from 'react';
import classnames from 'classnames';
import './index.scss';

export enum Direction {
  '横向' = 'hoz',
  '纵向' = 'ver',
  '未知' = 'unknown',
}

const verDirect = ['top', 'bottom'];
const hozDirect = ['left', 'right'];

const arrangeStyle = {
  'flex-wrap': 'wrap',
  'justify-content': 'flex-start',
  'align-content': 'flex-start',
  'flex-direction': 'row',
};

// 默认纵向, 垂直方向
function getDirection(children: any) {
  let direction: Direction = Direction.未知;

  Children.forEach(children, (item) => {
    if (
      item?.type?.role !== 'content' &&
      direction === Direction.未知 &&
      typeof item === 'object'
    ) {
      const role: string = item?.type?.role || '';
      const isVer = verDirect.includes(role);
      const isHoz = hozDirect.includes(role);
      if (isVer) {
        direction = Direction.纵向;
      } else if (isHoz) {
        direction = Direction.横向;
      }
    }
  });
  return direction === Direction.未知 ? Direction.纵向 : direction;
}

// 默认所有项都是自动撑开，左右top、bottom、right、left、或者定义了size的分别是根据孩子宽度或者具体大小固定的。
function renderChildren(
  child: any,
  inDirection: Direction,
  interval: number,
): null | ReactElement {
  if (!child) {
    return null;
  }
  if (Symbol.for('react.fragment') === child.type) {
    return React.cloneElement(child, {
      ...child.props,
      children: Children.map(child.props.children, (item) => {
        renderChildren(item, inDirection, interval);
      }),
    });
  }
  if (React.isValidElement(child)) {
    const $type: any = child.type;
    const props: any = child.props;
    const newPorps = { ...props };

    // 这种写法 对于百分比难以控制, 故而放弃掉了
    // if (interval && $type.role) {
    //   newPorps.style = Object.assign({}, newPorps.style, {
    //     [inDirection === Direction.横向 ? 'marginRight' : 'marginBottom']:
    //       interval,
    //   });
    // }

    if (props.size) {
      newPorps.style = Object.assign({ overflow: 'auto' }, newPorps.style, {
        'flex-basis': props.size,
      });
    } else {
      if (props.auto || $type.role === 'layout' || $type.role === 'content') {
        newPorps.className = classnames(
          newPorps.className,
          newPorps.className ?? '',
          'auto',
        );
      }
    }

    return React.cloneElement(child, newPorps);
  }
  return child;
}

type childType =
  | ReactElement
  | (() => ReactElement<any, string | JSXElementConstructor<any>>);
type childArrayType = childType[];
export interface baselayoutI {
  children: childType;
  style: object | undefined;
  className: string;
  padding?: boolean | number;
  hoz?: boolean;
  // 下面6个设置子节点排列
  middle?: boolean;
  center?: boolean;
  left?: boolean;
  right?: boolean;
  top?: boolean;
  bottom?: boolean;
  // 排列，默认的排列方式
  arrange?: number | false | number[];
  arrangeInterval: number;
  interval?: number;
  maxHeight?: number;
  minHeight?: number;
  // 样式
  white?: boolean;
  radius?: boolean;
  radiusTop?: boolean;
  radiusBottom?: boolean;
}

export default function BaseLayout(props: baselayoutI) {
  const {
    children,
    className,
    style = {},
    padding = false,
    hoz,
    middle,
    center,
    left,
    right,
    top,
    bottom,
    arrange = false,
    interval = 0,
    arrangeInterval = 0,
    maxHeight,
    minHeight,
    white = false,
    radius = false,
    radiusTop = false,
    radiusBottom = false,
    ...restProp
  } = props;
  let direction = hoz ? Direction.横向 : getDirection(children);

  // 排列 > direction
  // interval 能力  垂直下面

  let finalChildren = Children.toArray(children).map((item, index) =>
    renderChildren(
      item,
      direction,
      index === Children.count(children) - 1 ? 0 : interval ?? 0,
    ),
  );

  // 排列能力构建
  if (
    parseInt(arrange as unknown as string, 10) > 0 ||
    Array.isArray(arrange)
  ) {
    const spitNum: number = (
      Array.isArray(arrange) ? arrange.length : arrange
    ) as number;
    direction = Direction.横向;
    const splitChildArray = Array(spitNum)
      .fill(false)
      .map(() => []);
    for (let i = 0; i < finalChildren.length; i++) {
      const splitBelong = i % spitNum;
      // @ts-ignore
      splitChildArray[splitBelong].push(finalChildren[i]);
      if (
        arrangeInterval > 0 &&
        Math.floor(i / spitNum) !== Math.floor(finalChildren.length / spitNum)
      ) {
        splitChildArray[splitBelong].push(
          /* @ts-ignore */
          <div style={{ height: arrangeInterval }}></div>,
        );
      }
    }
    finalChildren = Array(spitNum)
      .fill(false)
      .map((item, index: number) => (
        <div
          style={{ flexBasis: `${100 / spitNum}%` }}
          className='operate-layout-split-item'
        >
          {splitChildArray[index]}
        </div>
      ));
  }

  if (interval) {
    const len = finalChildren.length;
    for (let i = 0; i < len - 1; i++) {
      finalChildren.splice(
        i * 2 + 1,
        0,
        <div
          className='operate-layout-interval-item'
          style={{ flexBasis: interval }}
        ></div>,
      );
    }
  }

  const finalClassName = classnames(
    'operate-components-layout-item',
    className,
    {
      ver: direction === 'ver',
      hoz: direction === 'hoz',
      middle,
      center,
      left,
      right,
      top,
      bottom,
      white,
      radius,
      'radius-top': radiusTop,
      'radius-bottom': radiusBottom,
    },
  );
  const finalStyle = {
    padding: padding === true ? '0 16px' : padding || '',
    minHeight,
    maxHeight,
    ...(style || {}),
  };

  return (
    <div {...restProp} className={finalClassName} style={finalStyle}>
      {finalChildren}
    </div>
  );
}
