import { inject, observer } from 'mobx-react';
import React, { PureComponent } from 'react';
import { IRow, IColumn } from '../../store/table';
import { RendererProps } from '../../factory';
import { Action } from '../Action';
import { createObject, isClickOnInput, isMobile } from '../../utils/helper';
import cloneDeep from 'lodash/cloneDeep';
import { SimpleSpan, SimpleSpanType, fakeQuickEdit } from './simpleTableCell/SimpleSpan';
import { resolveVariable } from '../../utils/tpl-builtin';
import { isNil } from 'lodash';
import { EventEnum, EventSub } from '../../utils/sub';
import { filter } from '../../utils/tpl';
import { PlusSquareOutlined, MinusSquareOutlined } from '@ant-design/icons';
interface TableRowProps extends Pick<RendererProps, 'render'> {
  autoWidth: boolean;
  tableLayout: 'vertical' | 'horizontal' | 'line-tiled';
  tableId: string;
  onCheck: (item: IRow, value?: boolean, shift?: boolean,) => void;
  scrollLeft: number;  // 滑动左侧距离
  leftDistances: number[]; // 根据表格头计算的每个元素距离左侧的距离
  scrollWindowWidth: number; // 滑动窗口宽度
  // showContextMenu: (...rest: any) => void;
  classPrefix: string;
  setBorder: boolean;
  checkItem: (item: any) => void;
  renderCell: (
    region: string,
    column: IColumn,
    item: IRow,
    props: any
  ) => React.ReactNode;
  columns: Array<IColumn>
  multiple: boolean;
  item: IRow;
  parent?: IRow;
  itemClassName?: string;
  tableName?: string
  itemIndex: number;
  regionPrefix?: string;
  checkOnItemClick?: boolean;
  ignoreFootableContent?: boolean;
  startShowIndex: number; // 开始渲染的位置-给合并的时候使用
  [propName: string]: any;
  canAccessSuperData: boolean;
  // Jay
  stickyWidths: { [key: string]: number };
  headCurrentRows?: (index: number, val: any, inited?: boolean) => void;
  itemHighlight?: boolean
  currentHighlight?: boolean
  activeCol?: string;
  activeRow?: number;
  extraRowSpan?: { [key: string]: number };
}
@inject('tableCtxMenuStore')
@observer
export class TableRow extends PureComponent<TableRowProps> {
  // reaction?: () => void;
  dom: any = React.createRef();
  state = {
    visited: false,
  }
  clearVistiMapEventId = ''
  showVistiMapEventId = ''

  constructor(props: TableRowProps) {
    super(props);
    this.state = {
      visited: false,
    }


    this.handleAction = this.handleAction.bind(this);
    this.handleQuickChange = this.handleQuickChange.bind(this);
    this.handleChange = this.handleChange.bind(this);
    this.handleItemClick = this.handleItemClick.bind(this);
  }

  componentDidMount() {
    if (!this.clearVistiMapEventId)
      this.clearVistiMapEventId = EventSub.on(`${this.props.tableId}/${EventEnum.ClearVistiMap}`, () => {
        this.setState({ visited: false })
      })
    if (!this.showVistiMapEventId)
      this.showVistiMapEventId = EventSub.on(`${this.props.tableId}/${EventEnum.ShowVistiMap}`, (rowIndex, columnIndex, byKey) => {
        if (rowIndex === this.props.itemIndex && byKey) this.props?.headCurrentRows?.(this.props.itemIndex, this.dom) // 如果用键盘触发才选中
        if (Math.abs(this.props.itemIndex - rowIndex) === 1 || this.props.itemIndex === rowIndex) {
          // 如果时第一次聚焦？
          if (!this.state.visited) {
            this.setState({ visited: true })
          }
        }
      })
    const { item, headCurrentRows } = this.props;
    if (this.props.itemIndex === 0) {
      headCurrentRows?.(0, this.dom, true)
    }

  }

  componentWillUnmount(): void {
    EventSub.off(`${this.props.tableId}/${EventEnum.ClearVistiMap}`, this.clearVistiMapEventId)
    EventSub.off(`${this.props.tableId}/${EventEnum.ShowVistiMap}`, this.showVistiMapEventId)
  }

  // 定义点击一行的行为，通过 itemAction配置
  handleItemClick(e: React.MouseEvent<HTMLTableRowElement>) {
    if (isClickOnInput(e)) {
      return;
    }
    const { itemAction, itemIndex, onAction, item, headCurrentRows, checkOnItemClick, onCheck, store } = this.props;
    headCurrentRows?.(itemIndex, this.dom)
    if (itemAction) {
      //itemAction中的某个字段在当前表格中不存在，会被赋值为undefined传到目标组件，导致目标组件获取不到该字段
      const ctx = createObject(store.data, item?.data || {}, {}, true)
      onAction?.(e, itemAction, ctx, true);
    }
    if (checkOnItemClick) {
      onCheck?.(item);
    }
  }
  handleAction(e: React.UIEvent<any>, action: Action, ctx: any) {
    const { onAction, item } = this.props;
    onAction && onAction(e, action, ctx || item.data);
  }

  handleQuickChange(
    values: object,
    saveImmediately?: boolean,
    savePristine?: boolean,
    resetOnFailed?: boolean
  ) {
    const { onQuickChange, item } = this.props;
    onQuickChange &&
      onQuickChange(item, values, saveImmediately, savePristine, resetOnFailed);
  }

  handleChange(
    value: any,
    name: string,
    submit?: boolean,
    changePristine?: boolean
  ) {
    if (!name || typeof name !== 'string') {
      return;
    }

    const { item, onQuickChange } = this.props;

    onQuickChange?.(
      item,
      {
        [name]: value
      },
      submit,
      changePristine
    );
  }

  renderMobileRow() { // Aug
    const {
      itemClassName,
      itemIndex,
      item,
      renderCell,
      children,
      footableMode,
      ignoreFootableContent,
      footableColSpan,
      regionPrefix,
      checkOnItemClick,
      classPrefix: ns,
      render,
      classnames: cx,
      parent,
      itemAction,
      handleJump,
      tableLayout,
      ...rest
    } = this.props;

    let columns = cloneDeep(this.props.columns)
    const checkIndex = columns.findIndex(item => item.type === '__checkme')
    // 勾选框单独一列放置
    const checkColumn = ~checkIndex ? columns.splice(checkIndex, 1)[0] : null

    return (<>
      {checkColumn && renderCell(
        `${regionPrefix}${itemIndex}/${checkColumn.index}`,
        checkColumn,
        item,
        {
          ...rest,
          width: null,
          rowIndex: itemIndex,
          colIndex: checkColumn.index,
          key: checkColumn.index,
          onAction: this.handleAction,
          onQuickChange: this.handleQuickChange,
          onChange: this.handleChange,
          handleJump: handleJump,
          tableLayout: tableLayout
        }
      )}
      <td className={cx(`Table-foot`)} colSpan={footableColSpan}>
        <table className={cx(`Table-footTable`)}>
          <tbody>
            {ignoreFootableContent
              ? columns.map(column => (
                <tr key={column.index}>
                  {column.label !== false ? <th></th> : null}
                  <td></td>
                </tr>
              ))
              : columns.map(column => (
                <tr key={column.index}>
                  {column.label !== false ? (
                    <th>
                      {render(
                        `${regionPrefix}${itemIndex}/${column.index}/tpl`,
                        column.label
                      )}
                    </th>
                  ) : null}

                  {renderCell(
                    `${regionPrefix}${itemIndex}/${column.index}`,
                    column,
                    item,
                    {
                      ...rest,
                      width: null,
                      rowIndex: itemIndex,
                      colIndex: column.index,
                      key: column.index,
                      onAction: this.handleAction,
                      onQuickChange: this.handleQuickChange,
                      onChange: this.handleChange,
                      handleJump: handleJump,
                      tableLayout: tableLayout
                    }
                  )}
                </tr>
              ))}
          </tbody>
        </table>
      </td>
    </>)
  }

  render() {
    const {
      itemClassName,
      itemIndex,
      item,
      renderCell,
      handleJump,
      children,
      footableMode,
      ignoreFootableContent,
      footableColSpan,
      regionPrefix,
      checkOnItemClick,
      classPrefix: ns,
      tableLayout,
      render,
      classnames: cx,
      parent,
      itemAction,
      headCurrentRows,
      itemHighlight,
      currentHighlight,
      primaryField,
      hasEdit,
      columns,
      activeCol,
      activeRow,
      startShowIndex,
      ...rest
    } = this.props;
    if (footableMode) {
      if (!item.expanded) {
        return null;
      }

      return (
        <tr
          data-id={item.id}
          key={item.id}
          data-index={item.newIndex}
          onClick={this.handleItemClick}
          className={cx(itemClassName, {
            // 'is-hovered': item.isHover,
            'is-checked': item.checked,
            'is-modified': hasEdit ? item.modified : '',
            'is-moved': item.moved,
            [`Table-tr--hasItemAction`]: itemAction, // 就是为了加鼠标效果
            [`Table-tr--odd`]: itemIndex % 2 === 0,
            [`Table-tr--even`]: itemIndex % 2 === 1
          })}
        >
          <td className={cx(`Table-foot`)} colSpan={footableColSpan}>
            <table className={cx(`Table-footTable`)}>
              <tbody>
                {ignoreFootableContent
                  ? columns.map(column => (
                    <tr key={column.index}>
                      {column.label !== false ? <th></th> : null}
                      <td></td>
                    </tr>
                  ))
                  : columns.map(column => (
                    <tr key={column.index}>
                      {column.label !== false ? (
                        <th>
                          {render(
                            `${regionPrefix}${itemIndex}/${column.index}/tpl`,
                            column.label
                          )}
                        </th>
                      ) : null}


                      {
                        renderCell(
                          `${regionPrefix}${itemIndex}/${column.index}`,
                          column,
                          item,
                          {
                            ...rest,
                            width: null,
                            rowIndex: itemIndex,
                            colIndex: column.index,
                            key: column.index,
                            onAction: this.handleAction,
                            onQuickChange: this.handleQuickChange,
                            onChange: this.handleChange,
                            handleJump: handleJump,
                            tableLayout: tableLayout
                          }
                        ) as any
                      }
                    </tr>
                  ))}
              </tbody>
            </table>
          </td>
        </tr>
      );
    }

    if (parent && !parent.expanded) {
      return null;
    }
    // Jay
    const { stickyWidths, store, leftDistances, scrollLeft, scrollWindowWidth, extraRowSpan } = this.props
    const leftFixedColumns = store.leftFixedColumns
    const lastLeftFixedIndex = leftFixedColumns[leftFixedColumns.length - 1]?.index
    const rightFixedColumns = store.rightFixedColumns
    const firstRightFixedIndex = rightFixedColumns[0]?.index

    const operationColumn = store.columns.find((column: any) => column.name == 'operation')

    // 最左最右渲染元素
    // const minRenderIndex = Math.max(leftDistances.findIndex(_ => _ > (scrollLeft - 0.5 * scrollWindowWidth)) - 1, 0)
    // let maxRenderIndex = leftDistances.findIndex(_ => _ > (scrollLeft + 1.5 * scrollWindowWidth))
    // // 如果找不到就到右侧为止全渲染
    // maxRenderIndex = maxRenderIndex > 0 ? maxRenderIndex : leftDistances.length
    const firstColumn = columns?.filter(col => col.name && !col.name.includes('__'))?.[0];
    return (
      <tr
        key={item.id}
        ref={this.dom}
        onMouseEnter={() => {
          if (!this.state.visited && columns.some(_ => _.pristine.quickEdit)) {
            this.setState({ visited: true })
            EventSub.emit(`${this.props.tableId}/${EventEnum.ShowVistiMap}`, itemIndex) // 广播订阅事件
          }
        }
        }
        onClick={this.handleItemClick}
        data-index={item.depth === 1 ? item.newIndex : undefined}
        data-id={item.id}
        className={cx(
          itemClassName,
          {
            // 'is-hovered': item.isHover,

            'is-checked': item.checked,
            'is-Highlight': itemHighlight,
            'is-current': currentHighlight,
            'is-modified': hasEdit ? item.modified : '',
            'is-moved': item.moved,
            'is-expanded': item.expanded,
            'is-expandable': item.expandable,
            [`Table-tr--hasItemAction`]: itemAction,
            [`Table-tr--odd`]: itemIndex % 2 === 0,
            [`Table-tr--even`]: itemIndex % 2 === 1,
            'is-border': isMobile() && !operationColumn
          },
          `Table-tr--${item.depth}th`
        )}
      >
        {/* Aug 加入mobileUI */}
        {!(store.mobileUI && tableLayout === 'vertical') ?
          columns?.map((column, index) => {
            // // // 如果元素在视野之外 并且不是固定在页面上的 不渲染
            // if ((index < minRenderIndex) && !column.fixed) { return <td></td> }
            // if (index > maxRenderIndex && !column.fixed) { return null }

            let groupValue = {};
            if (column.pristine.group?.length) {
              column.pristine.group.forEach((ele: any) => {
                groupValue = {
                  ...groupValue,
                  [ele.name]: item.locals[ele.name]
                }
              });
            }
            const classNameExpr = column.pristine.classNameExpr
            const showExpand = column.name === firstColumn?.name
            const tdClassName = `${itemClassName} ${cx(column.pristine.className, this.props.setBorder ? 'td-border' : '',
              {
                'active-cell': activeCol === column.name && activeRow === itemIndex,
                'fixed-left-last': column.index === lastLeftFixedIndex,
                'fixed-right-first': column.index === firstRightFixedIndex
              },
              classNameExpr ? filter(classNameExpr.replaceAll(`.${column.pristine.rawName}`, `['${column.name}']`), item.data) : null
            )}`

            // const itemValue = item.data[column.name]
            const itemValue = column.pristine.group?.length ? groupValue :
              column.name
                ? resolveVariable(
                  column.name,
                  this.props.canAccessSuperData ? item.locals : item.data,
                ) : column.value

            // 获取文字计算长度 快速编辑的不用算
            let textWidth = ''
            if (!column.pristine.quickEdit) {
              if (this.props.autoWidth) {
                textWidth = Array.isArray(itemValue) ? 5 : this.props.store?.textWidhMap?.[column.pristine.name]?.textLength
              }

            }
            const tdStyle = {
              position: column.fixed && "sticky",
              left: column.fixed === 'left' && stickyWidths?.[`${column.index}`],
              right: column.fixed === 'right' && stickyWidths?.[`${column.index}`],
              zIndex: column.fixed && 1,
              textAlign: column.align,
            } as any

            if (!['__checkme'].includes(column.type)) {
              // 取的顺序为 用户编辑宽度 一键列宽宽度 原始宽度
              tdStyle.maxWidth = column.pristine.editWidth || column.pristine.width || textWidth || (!['operation'].includes(column.type) && "200px")
              tdStyle.width = column.pristine.editWidth || column.pristine.width || textWidth || '200px'
            } else {
              tdStyle.textAlign = "center"
            }

            // console.log(itemValue)
            // 直接展示原有效果的类型
            // 类型为 检查 拖拽 拖拽 操作 文件

            // 已经记录过的mapping 也简单展示
            const hasRecordMaping = column.type === 'mapping' && !isNil(itemValue) && column?.map?.[itemValue] && !column.pristine.quickEdit

            // 或者 含有模板字符 配置defaultOpen(备注效果) 配置跳转 有远程资源 或者值不为空的对象
            // 或者有远程资源但是是map类型 并且有map值的情况
            const showOriginTd = ['__dragme', 'formula', '__expandme', 'progress', 'operation', 'color', 'lion-calc-tpl', 'link', '__pseudoColumn', 'images'].includes(column.type) || column.pristine.defaultOpen || column.pristine.tpl || column.pristine.linkUrl || column.pristine.href || (column.pristine.source && !hasRecordMaping) || (typeof itemValue === 'object' && !isNil(itemValue))  // 正式用
            // const showOriginTd = ['__dragme', '__expandme', 'progress', 'operation', 'color'].includes(column.type) || column.pristine.defaultOpen || column.pristine.tpl || column.pristine.source || column.pristine.linkUrl || (typeof itemValue === 'object' && !isNil(itemValue)&& !['lion-upload'].includes(column.type))// 测试用
            // const showOriginTd = false
            // const showOriginTd = true

            // 可见性根据展示字段变化的类型
            const visialbeChangeTd = column.pristine.quickEdit && fakeQuickEdit.includes(column.pristine.quickEdit.type)

            // 不需要变化的快速编辑类型类型
            const unChangeQuickEditTd = column.pristine.quickEdit && !fakeQuickEdit.includes(column.pristine.quickEdit.type)

            // 展示简单文本的情况
            const showSimpleText =
              // 不是展示原有类型 并且 不是做假快速编辑的类型  或者 是假快速编辑的类型 但可见性为false
              !(showOriginTd || (visialbeChangeTd && this.state.visited) || unChangeQuickEditTd)
            // rowSpans集合 有额外rowspasn的优先使用
            const trRowSpans = extraRowSpan || item.rowSpans
            // 合并效果完善
            if (column.name && trRowSpans[column.name] === 0) {
              return null;
            }
            //this.state.visitMap 内部存放移上去才展示原有效果的 cell类型
            return (showSimpleText) ? <td key={item.id + index} rowSpan={trRowSpans[column?.name || '']} table-name={this.props.tableName} column-name={column.name}
              // return !showOriginTd ? <td
              onClick={(e) => {
                if (column.type === '__checkme') {
                  if (!this.props.checkOnItemClick) { e.stopPropagation() };
                  if (!e.shiftKey) this.props.checkItem(item);
                  if (e.shiftKey) this.props.onCheck(item, false, true);
                }
              }}
              onMouseEnter={() => {
                if (visialbeChangeTd) {
                  this.setState({ visited: true })
                  EventSub.emit(`${this.props.tableId}/${EventEnum.ShowVistiMap}`, itemIndex, column.index) // 广播订阅事件
                }
              }}
              className={tdClassName + (showExpand && store.rows.some((rowItem: any) => rowItem.children?.length) ? ' expand-cell' : '')}
              onContextMenu={() => {
                this.props.tableCtxMenuStore.showContextMenu(itemIndex, column.name, this.props.tableId);
              }}
              style={{ ...tdStyle }} // 不懂为什么minheight失效 直接用height
            > <SimpleSpan prefixContent={showExpand && store.rows.some((rowItem: any) => rowItem.children?.length) ? <span className='expand-tag' onClick={() => {
              item.toggleExpanded();
            }}>
              {item.expandable ? (item.expanded ? <MinusSquareOutlined /> : <PlusSquareOutlined />) : <PlusSquareOutlined style={{ opacity: 0 }} />}
            </span> : null} env={this.props.env} primaryField={this.props.store.primaryField} tableId={this.props.tableId} key={item.id + index} prefix={column.pristine.prefix} suffix={column.pristine.suffix} multiple={this.props.multiple} ns={ns} value={itemValue} column={column} render={render} cx={this.props.classnames} item={item} itemIndex={itemIndex} className={tdClassName}></SimpleSpan>
            </td> : renderCell(`${itemIndex}/${column.index}`, column, item, {
              ...rest,
              rowIndex: itemIndex,
              colIndex: column.index,
              key: column.index,
              onAction: this.handleAction,
              onQuickChange: this.handleQuickChange,
              onChange: this.handleChange,
              handleJump: handleJump,
              // Jay
              className: tdClassName,
              style: tdStyle,
              tableLayout: tableLayout
            }
            )
          }) : (
            <td className={cx(`Table-foot`)} colSpan={footableColSpan} style={{ padding: operationColumn ? '0 0 12px 0' : '0' }}>
              <table className={cx(`Table-footTable`)}>
                <tbody>
                  {ignoreFootableContent
                    ? columns.map(column => (
                      <tr key={column.index}>
                        {column.label !== false ? <th></th> : null}
                        <td></td>
                      </tr>
                    ))
                    : columns.filter(column => column.type != 'operation').map(column => {
                      let groupValue = {};
                      if (column.pristine.group?.length) {
                        column.pristine.group.forEach((ele: any) => {
                          groupValue = {
                            ...groupValue,
                            [ele.name]: item.locals[ele.name]
                          }
                        });
                      }
                      const tdClassName = ''

                      const itemValue = column.pristine.group?.length ? groupValue :
                        column.name
                          ? resolveVariable(
                            column.name,
                            this.props.canAccessSuperData ? item.locals : item.data
                          ) : column.value
                      const showOriginTd = ['__dragme', '__expandme', 'progress', 'operation', 'color', '__checkme', '__pseudoColumn'].includes(column.type) || column.pristine.defaultOpen || column.pristine.tpl || column.pristine.linkUrl || (column.pristine.source && !column?.map?.[itemValue]) || (typeof itemValue === 'object' && !isNil(itemValue))  // 正式用
                      const trRowSpans = extraRowSpan || item.rowSpans
                      // 合并表格
                      if (column.name && trRowSpans[column.name] === 0) {
                        return null;
                      }
                      return (
                        <tr key={column.index}>
                          {column.label !== false ? (
                            column.type == '__expandme' ? null : <th>
                              {isMobile() ? <span>{column.label}</span> : render(
                                `${regionPrefix}${itemIndex}/${column.index}/tpl`,
                                column.label
                              )}
                            </th>
                          ) : null}
                          {!showOriginTd ? <td rowSpan={trRowSpans[column?.name || '']}> <SimpleSpan key={item.id + column.index} prefix={column.pristine.prefix} suffix={column.pristine.suffix} multiple={this.props.multiple} ns={ns} value={itemValue} column={column} render={render} cx={this.props.classnames} item={item} className={tdClassName}></SimpleSpan></td> : renderCell(
                            `${regionPrefix}${itemIndex}/${column.index}`,
                            column,
                            item,
                            {
                              ...rest,
                              width: null,
                              rowIndex: itemIndex,
                              colIndex: column.index,
                              key: column.index,
                              tableLayout: tableLayout,
                              onAction: this.handleAction,
                              onQuickChange: this.handleQuickChange,
                              onChange: this.handleChange
                            }
                          )}
                        </tr>
                      )
                    })}
                </tbody>
                {operationColumn && <tfoot>
                  <th style={{ textAlign: 'right' }} colSpan={2}>
                    {render('operations-buttons', operationColumn?.pristine?.buttons, { data: item.data })}
                  </th>
                </tfoot>}
              </table>
            </td>
          )
        }
      </tr>
    );
  }
}
