/**
 * @file 表格的方式显示只读信息，比如产品详情
 */

import React from 'react';
import { Renderer, RendererProps } from '../factory';
import { BaseSchema, SchemaExpression, SchemaObject, SchemaTpl } from '../Schema';
import { resolveVariableAndFilter } from '../utils/tpl-builtin';
import { visibilityFilter, isMobile } from '../utils/helper';
import throttle from 'lodash/throttle'; // Aug
import { filter } from '../utils/tpl';

export type PropertyItemProps = {
  /**
   * 属性名
   */
  label?: SchemaTpl;

  /**
   * 属性值
   */
  content?: SchemaTpl;

  /**
   * 配置是否显示，如果不显示，后续的节点会补上来
   */
  visibleOn?: SchemaExpression;

  /**
   * 配置是否显示，如果不显示，后续的节点会补上来
   */
  hiddenOn?: SchemaExpression;

  /**
   * 跨几列
   */
  span?: number;

  /**
   * 配置过长是否需要隐藏
   */
  ellipsis?: boolean;

  /**
   * 配置图片压缩的宽度
   */
  pressWidth?: number;
  mode?: 'table' | 'simple';
  inheritWidth?: boolean;//property下的宽度需要继承，否则表格宽度异常
  classNameExpr?: string;
};

export type PropertyItem = PropertyItemProps & SchemaObject;

/**
 * Property 属性列表
 * 文档：https://baidu.gitee.io/amis/docs/components/property
 */
export interface PropertySchema extends BaseSchema {
  /**
   * 指定为 property 展示类型
   */
  type: 'property';

  /**
   * 标题
   */
  title?: string;

  /**
   * 一共几列
   */
  column?: number;

  /**
   * 显示模式
   */
  mode?: 'table' | 'simple';

  /**
   * 每个 property 的设置
   */
  items: Array<PropertyItem>;

  /**
   * 自定义样式
   */
  style?: {
    [propName: string]: any;
  };

  /**
   * 标题样式
   */
  titleStyle?: {
    [propName: string]: any;
  };

  /**
   * 自定义样式
   */
  labelStyle?: {
    [propName: string]: any;
  };

  separator?: string;

  /**
   * 自定义样式
   */
  contentStyle?: {
    [propName: string]: any;
  };
}

export interface PropertyProps
  extends RendererProps,
  Omit<PropertySchema, 'type' | 'className'> { }

interface PropertyContent {
  label: any;
  content: any;
  span: number;
  ellipsis?: boolean; //Aug
  mode?: 'table' | 'simple';
  remark?: string;
  inheritWidth?: boolean;//property下的宽度需要继承，否则表格宽度异常
  classNameExpr?: string
}

export default class Property extends React.Component<PropertyProps, any> {
  contentRef: React.RefObject<HTMLDivElement>; //Aug
  constructor(props: PropertyProps) {
    super(props);

    //Aug
    this.contentRef = React.createRef<HTMLDivElement>();
    this.state = {
      wrapperWidth: 0
    }
    this.updateWrapperWidth = throttle(this.updateWrapperWidth.bind(this), 500);
  }

  //Aug
  componentDidMount() {
    this.updateWrapperWidth()
    window.addEventListener('resize', this.updateWrapperWidth)
  }
  //Aug
  componentDidUpdate() {
    this.updateWrapperWidth()
  }
  componentWillUnmount() {
    window.removeEventListener('resize', this.updateWrapperWidth)
    if (!(this.props.items?.[0] as any)?.inheritWidth) {
      sessionStorage.removeItem('computedWidth')
      sessionStorage.removeItem('computedWidth2')
      sessionStorage.removeItem('computedWidth3')
    }
  }
  //Aug
  updateWrapperWidth() {
    const wrapperWidth = this.contentRef.current?.offsetWidth
    if (!wrapperWidth) return
    if (Math.abs(wrapperWidth - this.state.wrapperWidth) < 10) return
    this.setState({ wrapperWidth })
  }


  /**
   * 算好每行的分布情况，方便后续渲染
   */
  prepareRows() {
    const { items, source, data, useMobileUI } = this.props;
    // Aug 移动端适配 始终一行
    let { column = 3 } = this.props;
    if (useMobileUI && isMobile()) {
      column = 1
    }
    const propertyItems =
      (items
        ? items
        : (resolveVariableAndFilter(
          source,
          data,
          '| raw'
        ) as Array<PropertyItem>)) || [];

    const rows: PropertyContent[][] = [];

    let row: PropertyContent[] = [];
    let columnLeft = column;
    let index = 0;
    const filteredItems = visibilityFilter(propertyItems, data);

    for (const item of filteredItems) {
      index = index + 1;
      const span = Math.min(item.span || 1, column);
      columnLeft = columnLeft - span;
      const rowItem = {
        label: item.label,
        content: item.content,
        span: span,
        mode: item.mode,
        remark: item.remark,
        inheritWidth: item?.inheritWidth,
        classNameExpr: item?.classNameExpr
      };

      // 如果还能放得下就放这一行
      if (columnLeft >= 0) {
        row.push(rowItem);
      } else {
        rows.push(row);
        columnLeft = column - span;
        row = [rowItem];
      }

      // 最后一行将最后的数据 push
      if (index === filteredItems.length) {
        rows.push(row);
      }
      // if (index === filteredItems.length) {
      //   const columnLength = row?.flatMap?.(item => item.span).reduce((prev: number, curr: number) => prev + curr, 0)
      //   if (columnLength < column) {
      //     const rowItem = {
      //       label: '',
      //       content: '',
      //       span: column - columnLength,
      //       mode: undefined,
      //       remark: '',
      //       inheritWidth: undefined
      //     };
      //     row.push(rowItem);
      //   }
      //   rows.push(row);
      // }
    }
    return rows;
  }

  renderRow(rows: PropertyContent[][]) {
    const {
      render,
      contentStyle,
      labelStyle,
      mode = 'table',
      classnames: cx, //Aug
      column = 3, //Aug
      env,
      popOverContainer
    } = this.props;
    const baseW = this.state.wrapperWidth / column
    return rows.map((row, key) => {
      return (
        <tr key={key}>
          {row.map((property, index) => {
            const itemMode = (property.content?.type === 'input-table-field' && property.content?.tableLayout === 'vertical') || property.content?.type == 'matrix-checkboxes' ? 'simple' : property.mode || mode
            const { ellipsis = true, remark } = property //Aug
            const isLastFillCell = (property.span == 1 && row.length != column && property.label === row[row.length - 1]?.label)
            const colSpan = isLastFillCell ? column * 2 - (index * 2 + 1) : property.span + property.span - 1
            const fillCell = property.content.type === 'lion-upload' && property.span == 1 && key == rows.length - 1

            if (property.span === 1) {
              const getWidth = sessionStorage.getItem('computedWidth')
              if (!getWidth && (baseW * property.span - 130 > 0) && !property.inheritWidth && !(property.content?.type === 'input-table-field' && property.content?.tableLayout === 'vertical')) {
                sessionStorage.setItem('computedWidth', baseW * property.span - 130 + 'px')
              }
            }
            if (property.span === 2) {
              const getWidth = sessionStorage.getItem('computedWidth2')
              if (!getWidth && (baseW * property.span - 130 > 0) && !property.inheritWidth && !(property.content?.type === 'input-table-field' && property.content?.tableLayout === 'vertical')) {
                sessionStorage.setItem('computedWidth2', baseW * property.span - 130 + 'px')
              }
            }
            if (property.span === 3) {
              const getWidth = sessionStorage.getItem('computedWidth3')
              if (!getWidth && (baseW * property.span - 130 > 0) && !property.inheritWidth && !(property.content?.type === 'input-table-field' && property.content?.tableLayout === 'vertical')) {
                sessionStorage.setItem('computedWidth3', baseW * property.span - 130 + 'px')
              }
            }
            return itemMode === 'table' ? (
              <React.Fragment key={`item-${index}`}>
                {!(property.content?.tableLayout === 'horizontal' && !isMobile()) && <th>
                  {/* Aug */}
                  <div className={cx('cell', { 'ellipsis': ellipsis })}
                    style={Object.assign({ width: 120, display: 'flex', justifyContent: 'flex-start', alignItems: 'center' }, labelStyle)}>
                    {render('label', property.label)}
                    {remark && render('label-remark', {
                      type: 'remark',
                      icon: property.content?.icon,
                      tooltip: remark,
                      style: { display: 'flex' },
                      container: popOverContainer ? popOverContainer : env.getModalContainer ? env.getModalContainer : undefined
                    })
                    }
                  </div>
                </th>}
                <td
                  style={{ height: fillCell ? '100%' : undefined}}
                  colSpan={property.content?.tableLayout === 'horizontal' && !isMobile() ? column * 2 : colSpan} // 需要再补上 th 所占的列数
                  className={property.classNameExpr ? filter(property.classNameExpr, this.props.data) : ''}
                >
                  {property.content?.tableLayout === 'horizontal' && !isMobile() ? <div className='fieldTable-block'></div> : null}
                  <div className={cx('cell', { 'ellipsis-cell': ellipsis }, isLastFillCell && 'full-cell')}
                    // 减去label 以及 th td > border的宽度
                    style={Object.assign({
                      height: fillCell ? '100%' : undefined,
                      width: isLastFillCell ? '100%' : property.inheritWidth && [1, 2, 3].includes(property.span) ? (((property.span == 1 || property.span == 2) ? property.span == 2 ? sessionStorage.getItem('computedWidth2') : sessionStorage.getItem('computedWidth') : sessionStorage.getItem('computedWidth3')) || baseW * property.span - 130) : baseW * property.span - (property.content?.tableLayout === 'horizontal' && !isMobile() ? 0 : 130)
                    },
                      contentStyle,
                      property.content?.tableLayout === 'horizontal' && !isMobile() ? { padding: 0 } : {}
                    )}>
                    {render('content', property.content, {
                      data: this.props.data,
                      key: `${property.content.name}-${property.content.type}-${index}`,
                      labelName: property.label,
                      isProperty: true,
                      fillCell
                    })}
                  </div>
                </td>
              </React.Fragment>
            ) : (
              <td
                colSpan={property.span * 2}
                style={contentStyle}
                key={`item-${index}`}
              >
                <div className='fieldTable-block'></div>
                {render('content', property.content, { labelName: property.label, isProperty: true, span: column })}
              </td>
            );
          })}
        </tr>
      );
    });
  }

  render() {
    const {
      style,
      title,
      column = 3,
      classnames: cx,
      className,
      titleStyle,
      mode = 'table'
    } = this.props;

    const rows = this.prepareRows();
    //判断是否有符合条件撑满图片
    const fillImage = rows.find((row, key) => row.find(col => col.content.type === 'lion-upload' && col.span == 1 && key == rows.length - 1));
    return (
      <div
        className={cx('Property', `Property--${mode}`, className)}
        style={{ ...style, height: !!fillImage ? '100%' : undefined }}
        ref={this.contentRef}
      >
        <table>
          {title ? (
            <thead>
              <tr>
                <th
                  colSpan={mode === 'table' ? column + column : column}
                  style={titleStyle}
                >
                  {title}
                </th>
              </tr>
            </thead>
          ) : null}
          <tbody>{this.renderRow(rows)}</tbody>
        </table>
      </div>
    );
  }
}

@Renderer({
  type: 'property'
})
export class PropertyRenderer extends Property { }
