import React, { useEffect, useRef, useState } from 'react';
import { ClassNamesFn } from '../../theme';
import { IColumn, IRow, ITableStore } from '../../store/table';
import { SchemaNode, Action } from '../../types';
import { TableBody } from './TableBody';
import { LocaleProps } from '../../locale';
import { observer } from 'mobx-react';
import { ActionSchema } from '../Action';
import ItemActionsWrapper from './ItemActionsWrapper';
import InfinteSroll from '../Lion/components/InfinteSroll';
import { anyChanged, isMobile, noop } from '../../utils/helper';
import { CountItem } from '.';
import { Empty, List } from 'antd';
import { RendererEnv } from '../../env';
import VirtualList from 'rc-virtual-list';
import { isNil } from 'lodash';
import { resolveVariable } from '../../utils/tpl-builtin';
import { SimpleSpan } from './simpleTableCell/SimpleSpan';
import { linkJump, ModleHandleClick } from '../../utils/utils';
import { filter } from '../../utils/tpl';
import { DATAKEYID } from '../../store/crud';
import { Checkbox } from '../../components';

export interface TableContentProps extends LocaleProps {
  tableLayout: 'vertical' | 'horizontal';
  tableId: string;
  tableName?: string
  className?: string;
  autoWidth: boolean;
  tableClassName?: string;
  classnames: ClassNamesFn;
  columns: Array<IColumn>;
  multiple: boolean;
  canAccessSuperData: any;
  setBorder: boolean;
  // showContextMenu: (...rest: any) => void;
  rows: Array<IRow>;
  placeholder?: string;
  render: (region: string, node: SchemaNode, props?: any) => JSX.Element;
  onMouseMove: (event: React.MouseEvent) => void;
  onScroll: (event: React.UIEvent) => void;
  tableRef: (table?: HTMLTableElement | null) => void;
  renderHeadCell: (column: IColumn, props?: any) => JSX.Element;
  renderCell: (
    region: string,
    column: IColumn,
    item: IRow,
    props: any
  ) => React.ReactNode;
  onCheck: (item: IRow, value: boolean, shift?: boolean) => void;
  checkItem: (item: any) => void;
  onQuickChange?: (
    item: IRow,
    values: object,
    saveImmediately?: boolean | any,
    savePristine?: boolean
  ) => void;
  footable?: boolean;
  footableColumns: Array<IColumn>;
  checkOnItemClick?: boolean;
  handleResetData?: () => any;
  buildItemProps?: (item: IRow, index: number) => any;
  onAction?: (
    e: React.UIEvent<any> | null,
    action: Action | ActionSchema,
    ctx: object | null,
    isItemAction?: boolean
  ) => void;
  rowClassNameExpr?: string;
  rowClassName?: string;
  data?: any;
  prefixRow?: Array<any>;
  affixRow?: Array<CountItem>;
  countField?: CountItem[];
  itemAction?: ActionSchema;
  itemActions?: Array<Action>;
  store: ITableStore;
  // Jay
  autoFillHeight?: boolean;
  // position: [rowIndex: number, colName: string];
  primaryField: string;
  // contextMenuVisible: boolean;
  // onContextMenuVisibleChange: (visible: boolean) => void;
  infinteLoad: any;
  onLoadMore: () => void;
  loadHasMore: any;
  loading: boolean;
  tableType?: string;
  handleMultiColumnSort: (name: string, isMultiple?: boolean, columnMapValue?: object) => void;
  tableRotate?: boolean;
  tableWindowInstance: any,
  handleJump?: (val: any) => void,
  loadDataOnce?: boolean,
  classPrefix: string,
  loadmoreLoading: boolean,
  showPerPage: boolean,
  changeSelectedRow?: (index: number) => void;
  renderAffix?: (isAll?: boolean) => any;
  type: string;
  affixRowPosition: 0 | 1 | 2;
  activeCol?: string;
  activeRow?: number;
  hiddenRowHighlight: boolean;
  env: RendererEnv;

}

@observer
export class TableContent extends React.Component<TableContentProps, any> {
  tableWindowRef: React.RefObject<any | null>
  constructor(props: TableContentProps) {
    super(props);
    this.tableWindowRef = React.createRef()
    this.state = {
      itemHeight: props.columns.find(item => item.type === 'operation') ? 336 : 285,
      containerHeight: 500
    }
  }

  renderItemActions() {
    const { itemActions, render, store, classnames: cx } = this.props;
    const finalActions = Array.isArray(itemActions)
      ? itemActions.filter(action => !action.hiddenOnHover)
      : [];

    if (!finalActions.length) {
      return null;
    }

    return (
      <ItemActionsWrapper store={store} classnames={cx}>
        <div className={cx('Table-itemActions')}>
          {finalActions.map((action, index) =>
            render(
              `itemAction/${index}`,
              {
                ...(action as any),
                isMenuItem: true
              },
              {
                key: index,
                item: store.hoverRow,
                data: store.hoverRow!.locals,
                rowIndex: store.hoverRow!.index
              }
            )
          )}
        </div>
      </ItemActionsWrapper>
    );
  }

  handleMouseLeave = (e: any) => {
    e?.stopPropagation();
    const store = this.props.store;
    const row = store.hoverRow;
    row?.setIsHover(false);
  };

  componentDidUpdate(prevProps: TableContentProps) {
    const { itemAction, onAction, data } = this.props;
    //这里是处理当主表查询无数据时，从表没有清空的问题
    if (
      anyChanged(['data'], prevProps, this.props) &&
      !data?.items?.length &&
      itemAction
    ) {
      onAction?.(null, itemAction, null);
    }
    if(this.props.tableLayout !== prevProps.tableLayout && isMobile()) {
      if(this.props.tableLayout == 'vertical') {
        if(window.ResizeObserver && this.tableWindowRef.current) {
          this.resizeObserver = new window.ResizeObserver(() => {
            this.setState({containerHeight: this.tableWindowRef.current.clientHeight})
          });
          this.resizeObserver?.observe(this.tableWindowRef.current);
        }
      }else {
        this.resizeObserver?.disconnect();
      }
    } 
  }

  componentWillUnmount(): void {
    if (this.resizeObserver) {
      this.resizeObserver?.disconnect();
      this.resizeObserver = null;
    }
  }

  resizeObserver: any;
  componentDidMount() {
    const { tableLayout } = this.props;
    if (window.ResizeObserver && this.tableWindowRef.current && isMobile() && tableLayout === 'vertical') {
      this.resizeObserver = new window.ResizeObserver(() => {
        this.setState({ containerHeight: this.tableWindowRef.current.clientHeight })
      });
      this.resizeObserver?.observe(this.tableWindowRef.current);
    }
  }

  hasCachedHeight = new Map<string, number>();
  hasCachedStatus = new Map<string, boolean>();

  changeCachedHeight = (key: string, value: number) => {
    this.hasCachedHeight.set(key, value)
  }
  changeCachedStatus = (key: string, value: boolean) => {
    this.hasCachedStatus.set(key, value)
  }
  onScroll = (e: React.UIEvent<HTMLElement, UIEvent>) => {
    const { loadHasMore } = this.props;
    if (loadHasMore && Math.abs(e.currentTarget.scrollHeight - e.currentTarget.scrollTop - (this.tableWindowRef.current.clientHeight || 500)) <= 1) {
      this.props.onLoadMore?.()
    }
  };

  MyVariableSizeList = () => {
    const { rows, columns, render, primaryField, classPrefix, classnames, onCheck, multiple, env,
      tableClassName, handleJump, translate, placeholder } = this.props;
    const data = rows.map(item => item.data);
    return (
      <List className='table-vertical-virtual-list' locale={{ emptyText: translate(placeholder || 'placeholder.noData') }}>
        <VirtualList
          data={data}
          height={this.state.containerHeight}
          itemHeight={this.state.itemHeight}
          itemKey={DATAKEYID}
          onScroll={this.onScroll}
        >
          {(item: obj, index: number) => (
            <List.Item key={item[primaryField] + index}>
              <EnhancedMyComponent columns={columns.filter(col => col.name)} rowItem={rows[index]} render={render}
                cx={classnames} ns={classPrefix} itemHeigt={this.state.itemHeight} handleJump={handleJump}
                changeItemHeight={(height: number) => this.setState({ itemHeight: height })}
                keyId={item[DATAKEYID]} onCheck={onCheck} multiple={multiple} env={env}
                initExpanded={this.hasCachedStatus.get(item[DATAKEYID])} changeCachedStatus={this.changeCachedStatus}
                changeCachedHeight={this.changeCachedHeight} showCheckbox={!!tableClassName?.includes('checkbox-show')}
              />
            </List.Item>
          )}
        </VirtualList>
      </List>
    );
  }

  render() {
    const {
      placeholder,
      classnames: cx,
      render,
      className,
      columns,
      onMouseMove,
      onScroll,
      tableRef,
      rows,
      renderHeadCell,
      renderCell,
      handleJump,
      onCheck,
      rowClassName,
      onQuickChange,
      footable,
      footableColumns,
      checkOnItemClick,
      buildItemProps,
      onAction,
      rowClassNameExpr,
      data,
      prefixRow,
      locale,
      translate,
      itemAction,
      affixRow,
      countField,
      store,
      // position,
      primaryField,
      infinteLoad,
      onLoadMore,
      loadHasMore,
      tableLayout,
      tableType,
      tableRotate,
      loadDataOnce,
      classPrefix,
      loadmoreLoading,
      showPerPage,
      activeCol,
      activeRow,
      env
    } = this.props;
    // const emptyWidth = this.tableWindowRef.current?.clientWidth || this.tableWindowRef.current?.closest(`.${classPrefix}Tabs-content`)?.clientWidth;
    const tableClassName = cx('Table-table', this.props.autoWidth ? 'Table--auto-width' : '', this.props.tableClassName);
    // const hideHeader = columns.every(column => !column.label);
    // Jay
    const stickyWidths = store.stickyWidths;
    const leftFixedColumns = store.leftFixedColumns;
    const lastLeftFixedIndex =
      leftFixedColumns[leftFixedColumns.length - 1]?.index;
    const rightFixedColumns = store.rightFixedColumns;
    const firstRightFixedIndex = rightFixedColumns[0]?.index;
    const { autoFillHeight, loading } = this.props;
    const tableHeadRows = store.tableHeadRows
    const level = tableHeadRows.length
    // console.log(rows, this.props.columns)
    return (
      <div
        // onMouseMove={onMouseMove}
        className={cx('Table-content', className)}
        onScroll={isMobile() && tableLayout === 'vertical' ? noop : onScroll}
        ref={this.tableWindowRef}
        style={{maxHeight: 'initial'}}
      >
        {store.hoverRow ? this.renderItemActions() : null}
        {
          isMobile() && tableLayout === 'vertical' && !!rows.length ? this.MyVariableSizeList() : <>
            <table
              table-id={this.props.tableId}
              onMouseLeave={this.handleMouseLeave}
              ref={tableRef}
              className={tableClassName}
            >
              {!(store.mobileUI && tableLayout === 'vertical') ? ( // Aug 移动端隐藏头部
                <thead>
                  {tableHeadRows.map((row, index) => (
                    <tr key={index}>
                      {row.map(item => {
                        if (item.rowspan == level - index) {
                          return renderHeadCell(item.column, {
                            'data-index': item.column.index,
                            'rowspan': item.rowspan,
                            'colspan': item.colspan,
                            'key': item.column.index + (item.column.name ?? '') + item.column.type,
                            'style': {
                              position: (item.column.fixed || autoFillHeight) && 'sticky',
                              left: item.column.fixed === 'left' && stickyWidths?.[`${item.column.index}`],
                              right: item.column.fixed === 'right' && stickyWidths?.[`${item.column.index}`],
                              zIndex: autoFillHeight && item.column.fixed ? 4 : autoFillHeight ? 3 : item.column.fixed && 2,
                              top: autoFillHeight ? (level > 1 && item.rowspan != level ? (isMobile() ? 34 : 26) * (level - 1) + (index + 2) : 0) : undefined
                            },
                            'className': item.column.index === lastLeftFixedIndex ? 'fixed-left-last' : item.column.index === firstRightFixedIndex ? 'fixed-right-first' : ''
                          })
                        }
                        return (
                          <th
                            key={item.column.index}
                            data-index={item.column.index}
                            colSpan={item.colspan}
                            rowSpan={item.rowspan}
                            className={`${item.column.index === lastLeftFixedIndex ? 'fixed-left-last ' : ''} ${item.column.index === firstRightFixedIndex ? ' fixed-right-first' : ''}`}
                            // Aug
                            style={{
                              textAlign: 'center',
                              position: 'sticky',
                              left: item.column.fixed === 'left' && stickyWidths?.[`${item.column.index}`],
                              right: item.column.fixed === 'right' && stickyWidths?.[`${item.column.index}`],
                              top: (isMobile() ? 34 : 26) * index + index,
                              zIndex: item.column.fixed || item.rowspan > 1 ? 4 : 2
                            }}
                          >
                            {render('tpl', item.label)}
                          </th>
                        )
                      })}
                    </tr>
                  ))}
                </thead>
              ) : null}

              {loading ? null : !rows.length ? (
                <tbody>
                  <tr className={cx('Table-placeholder')}>
                    <td className="empty-not-hover" colSpan={columns.length} style={{ padding: 0 }}>
                      {/* <div style={{ width: tableRotate ? document.documentElement.clientHeight : '100vw', position: 'sticky', left: 0, color: '#999', fontSize: 13, textAlign: 'center' }}> */}
                      <Empty
                        style={
                          {
                            backgroundColor: 'white',
                            position: 'sticky',
                            display: 'flex',
                            flexDirection: 'column',
                            justifyContent: 'center',
                            left: 0,
                            margin: '-8px',
                            overflow: 'hidden',
                            width: this.tableWindowRef.current?.clientWidth,
                            height: this.tableWindowRef.current?.clientHeight - 40
                          }}
                        description={translate(placeholder || 'placeholder.noData')}
                      />
                      {/* </div> */}
                    </td>
                  </tr>
                </tbody>
              ) : (
                // 有了表格实例渲染
                (this.tableWindowRef.current || this.props.tableWindowInstance.current) &&
                <TableBody
                  renderAffix={this.props.renderAffix}
                  tableId={this.props.tableId}
                  tableName={this.props.tableName}
                  autoWidth={this.props.autoWidth}
                  contentDom={this.tableWindowRef}
                  // showContextMenu={this.props.showContextMenu}
                  multiple={this.props.multiple}
                  setBorder={this.props.setBorder}
                  canAccessSuperData={this.props.canAccessSuperData}
                  tabeleDom={this.props.tableWindowInstance}
                  itemAction={itemAction}
                  classnames={cx}
                  render={render}
                  renderCell={renderCell}
                  onCheck={onCheck}
                  onQuickChange={onQuickChange}
                  footable={footable}
                  checkItem={this.props.checkItem}
                  footableColumns={footableColumns}
                  checkOnItemClick={checkOnItemClick}
                  buildItemProps={buildItemProps}
                  onAction={onAction}
                  rowClassNameExpr={rowClassNameExpr}
                  rowClassName={rowClassName}
                  autoFillHeight={autoFillHeight}
                  rows={rows}
                  columns={columns}
                  locale={locale}
                  translate={translate}
                  prefixRow={prefixRow}
                  affixRow={affixRow}
                  countField={countField}
                  data={data}
                  handleResetData={this.props.handleResetData}
                  // Jay
                  store={store}
                  stickyWidths={stickyWidths}
                  // position={position}
                  primaryField={primaryField}
                  // contextMenuVisible={this.props.contextMenuVisible}
                  // onContextMenuVisibleChange={this.props.onContextMenuVisibleChange}
                  tableLayout={tableLayout}
                  handleJump={handleJump}
                  loadDataOnce={loadDataOnce}
                  onLoadMore={onLoadMore}
                  loadHasMore={loadHasMore}
                  tableRotate={tableRotate}
                  classPrefix={classPrefix}
                  showPerPage={showPerPage}
                  changeSelectedRow={this.props.changeSelectedRow}
                  type={this.props.type}
                  affixRowPosition={this.props.affixRowPosition}
                  activeCol={activeCol}
                  activeRow={activeRow}
                  hiddenRowHighlight={this.props.hiddenRowHighlight}
                  env={env}
                ></TableBody>
              )}
            </table>
            {
              !loading && infinteLoad && !!rows.length && (
                <InfinteSroll autoFillHeight={autoFillHeight} loadmoreLoading={loadmoreLoading} loadMore={onLoadMore} hasMore={loadHasMore} hasData={!!data?.items?.length} tableRotate={tableRotate} ns={this.props.classPrefix} tableLayout={tableLayout} loadDataOnce={loadDataOnce} />
              )
            }
          </>
        }
        {/* <Table
          pagination={{ pageSize: 3000 }}
          virtual={true} scroll={{ x: 2000, y: 400 }} dataSource={rows.toJSON().map(_ => _.data)} key={'id'} columns={this.props.columns.map(_ => ({
            title: _.label,
            width: _.pristine.width || 200,
            dataIndex: _.name,
            fixed: _.align as any,
            render: (value, index) => { }
          }))}></Table> */}
      </div >
    );
  }
}
type SimpleTableRowProps = {
  columns: any[];
  rowItem: obj;
  render: (region: string, node: SchemaNode, props?: any) => JSX.Element;
  cx: ClassNamesFn;
  ns: string;
  itemHeigt: number;
  changeItemHeight: (height: number) => void;
  initExpanded?: boolean;
  changeCachedStatus: (key: string, value: boolean) => void;
  changeCachedHeight: (key: string, value: number) => void;
  keyId: string;
  onCheck: (item: any, value: boolean) => void;
  multiple: boolean;
  showCheckbox: boolean;
  env: RendererEnv;
  handleJump: ((val: any) => void) | undefined;
}

const SimpleTableRow = ({ columns, rowItem, render, cx, ns, itemHeigt, changeItemHeight, initExpanded,
  changeCachedHeight, changeCachedStatus, keyId, onCheck, multiple, showCheckbox, env, handleJump
}: SimpleTableRowProps) => {
  const [expanded, setExpanded] = useState(!!initExpanded);
  useEffect(() => {
    changeCachedStatus(keyId, expanded)
  }, [expanded])
  const initCols = () => {
    const operationCol = columns.filter(item => item.type === 'operation')
    return columns.slice(0, 6).concat(operationCol)
  }
  const [renderColumns, setRenderColumns] = useState<any[]>(initCols());
  const virtualListItemDom = useRef<HTMLDivElement | null>(null);
  useEffect(() => {
    if (virtualListItemDom.current) {
      const height = virtualListItemDom.current.clientHeight
      changeCachedHeight(keyId, height)
      // if(height && height !== itemHeigt) changeItemHeight(height)
    }
  }, [])
  const renderField = (colItem: IColumn) => {
    const column = colItem.pristine;
    const { affix, linkId, linkUrl } = column;
    const data = rowItem.locals;
    const schema = {
      ...column,
      className: column.innerClassName,
      type: (column && column.type) || 'plain'
    };
    let type = schema.type;
    if (type === 'lion-upload') type = 'simple-upload-table-cell';
    // if(type === 'mapping') type = 'simple-table-cell';
    let body = render('', { ...schema, type }, {
      style: {},
      value: rowItem.data[column.name],
      data,
      className: cx(column.innerClassName)
    });
    const canJumpUrl = linkJump(linkId, data, column.jumpDisabledOn)
    return <div
      className={cx(
        column.classNameExpr ? filter(column.classNameExpr, data) : null,
        linkUrl && canJumpUrl ? 'is-linkUrl' : '',
      )}
      onClick={(e: any) => {
        if (canJumpUrl) {
          e.stopPropagation()
          ModleHandleClick({ ...column, value: rowItem.data[column.name], env, classnames: cx, handleJump, data }, e.target)
        }
      }}
    >
      {body}
      {affix}
    </div>
  }
  useEffect(() => {
    const operationCol = columns.filter(item => item.type === 'operation');
    setRenderColumns(expanded ? columns.concat() : columns.slice(0, 6).concat(operationCol));
  }, [expanded])
  //起始位置
  const originX = useRef(0);
  const originY = useRef(0);
  //拖动过程中的临时位置
  const movingX = useRef(0);
  const movingY = useRef(0);
  const ontouchstart = (e: React.TouchEvent<HTMLDivElement>) => {
    e.persist()
    // e.preventDefault()
    e.stopPropagation()
    if (e.touches.length > 0) {
      const touch = e.touches[0];
      originX.current = movingX.current = touch.clientX; // 记录触摸开始的横坐标
      originY.current = movingY.current = touch.clientY; // 记录触摸开始的纵坐标
    }
  }
  const onTouchMove = (e: React.TouchEvent<HTMLDivElement>) => {
    e.persist()
    // e.preventDefault()
    e.stopPropagation()
    if (e.changedTouches.length > 0) {
      const touch = e.changedTouches[0];
      const endX = touch.clientX; // 触摸结束的横坐标
      const endY = touch.clientY; // 触摸结束的纵坐标
      const moveX = endX - movingX.current; // 横向移动距离
      const moveY = endY - movingY.current; // 纵向移动距离
      if (moveX == 0 && moveY == 0) {
      } else {
        const srcDom = (e.target as HTMLDivElement).closest('.row-item-operation')
        if (srcDom) {
          srcDom.scrollTo({ left: srcDom.scrollLeft - moveX })
        }
      }
    }
  }
  const onTouchEnd = (e: React.TouchEvent<HTMLDivElement>) => {
    e.persist()
    // e.preventDefault()
    e.stopPropagation()
    if (e.changedTouches.length > 0) {
      const touch = e.changedTouches[0];
      const endX = touch.clientX; // 触摸结束的横坐标
      const endY = touch.clientY; // 触摸结束的纵坐标
      // 如果拖动的距离很小，认为是一次单击事件
      const distance = Math.sqrt(
        (endX - originX.current) ** 2 + (endY - originY.current) ** 2
      );
      if (distance < 1) {
        // 在这里处理单击事件
      }
    }
  }
  return <div className='virtual-list-row-item' ref={virtualListItemDom}>
    <div>
      {
        renderColumns.map((column, colIndex) => {
          const itemValue = column.name
            ? resolveVariable(
              column.name,
              rowItem.data
            ) : column.value
          const showOriginTd = ['__dragme', '__expandme', 'progress', 'lion-upload', '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))  // 正式用
          if (column.type === 'operation') return null;
          return <div className={`table-vertical-row-colItem ${colIndex === 0 ? 'first-colItem' : ''}`}
          >
            <div className='colItem-label'>
              {colIndex === 0 ? <>
                <div className='colItem-checkbox'
                  style={{ display: showCheckbox ? 'block' : 'none' }}
                  onClick={() => onCheck(rowItem, true)}
                >
                  <Checkbox
                    classPrefix={ns}
                    type={multiple ? 'checkbox' : 'radio'}
                    checked={rowItem.checked}
                    disabled={!rowItem.checkable}
                  />
                </div>
                <div className='colItem-checkbox-label'>{column.label}</div>
              </> : column.label}
            </div>
            <div className='colItem-value'>{
              showOriginTd ? renderField(column)
                : <SimpleSpan key={rowItem.id + column.index} ns={ns} value={itemValue} column={column}
                  render={render} cx={cx} item={rowItem}></SimpleSpan>
            }</div>
          </div>
        })
      }
    </div>
    {columns.length > 6 && <div className='row-item-expand'>
      <span onClick={() => setExpanded(!expanded)}>{expanded ? '收起' : '更多'}</span>
    </div>}
    {renderColumns[renderColumns.length - 1].type === 'operation' && <div className='row-item-operation' style={{
    }} onScroll={(e) => e.stopPropagation()}
      onTouchStart={ontouchstart} onTouchMove={onTouchMove} onTouchEnd={onTouchEnd}
    >
      <div style={{ display: 'block', whiteSpace: 'nowrap' }}>
        {render('operations-buttons', renderColumns[renderColumns.length - 1]?.pristine?.buttons, { data: rowItem.locals })}
      </div>
    </div>}
  </div>
}
const EnhancedMyComponent = observer(SimpleTableRow);