import React from 'react';
import { Renderer, RendererProps } from '../factory';
import { SchemaNode, Action } from '../types';
import { getScrollParent, autobind, isMobile } from '../utils/helper';
import { resizeSensor } from '../utils/resize-sensor';
import {
  BaseSchema,
  SchemaClassName,
  SchemaCollection,
  SchemaTpl
} from '../Schema';
import { ActionSchema } from './Action';
import { FormSchemaHorizontal } from './Form/index';
// Jay
import { Spinner } from '../components';
import { EllipsisOutlined } from '@ant-design/icons';
import { getHashCode, ModleHandleClick } from '../utils/utils';

/**
 * Panel渲染器。
 * 文档：https://baidu.gitee.io/amis/docs/components/panel
 */
export interface PanelSchema extends BaseSchema {
  /**
   * 指定为Panel渲染器。
   */
  type: 'panel';

  /**
   * 按钮集合
   */
  actions?: Array<ActionSchema>;

  /**
   * 按钮集合外层类名
   */
  actionsClassName?: SchemaClassName;

  /**
   * 内容区域
   */
  body?: SchemaCollection;

  /**
   * 配置 Body 容器 className
   */
  bodyClassName?: SchemaClassName;

  /**
   * 底部内容区域
   */
  footer?: SchemaCollection;

  /**
   * 配置 footer 容器 className
   */
  footerClassName?: SchemaClassName;

  /**
   * footer 和 actions 外层 div 类名。
   */
  footerWrapClassName?: SchemaClassName;

  /**
   * 头部内容, 和 title 二选一。
   */
  header?: SchemaCollection;

  /**
   * 配置 header 容器 className
   */
  headerClassName?: SchemaClassName;

  /**
   * Panel 标题
   */
  title?: SchemaTpl;

  /**
   * 固定底部, 想要把按钮固定在底部的时候配置。
   */
  affixFooter?: boolean | 'always';

  /**
   * 配置子表单项默认的展示方式。
   */
  subFormMode?: 'normal' | 'inline' | 'horizontal';
  /**
   * 如果是水平排版，这个属性可以细化水平排版的左右宽度占比。
   */
  subFormHorizontal?: FormSchemaHorizontal;
  /**
   * 在组合页模式下生效,点查看更多跳转的页面
   */
  linkUrl?: string
}

export interface PanelProps
  extends RendererProps,
  Omit<
    PanelSchema,
    'type' | 'className' | 'panelClassName' | 'bodyClassName'
  > {
  isDetail?: boolean;//来自form的详情模式
  flowProcess?: boolean//来自form
}

// Jay
export interface PanelState {
  loading: boolean;
}

export default class Panel extends React.Component<PanelProps, PanelState> { // Jay
  static propsList: Array<string> = [
    'header',
    'actions',
    'children',
    'headerClassName',
    'footerClassName',
    'footerWrapClassName',
    'actionsClassName',
    'bodyClassName'
  ];
  static defaultProps = {
    // className: 'Panel--default',
    // headerClassName: 'Panel-heading',
    // footerClassName: 'Panel-footer bg-light lter Wrapper',
    // actionsClassName: 'Panel-footer',
    // bodyClassName: 'Panel-body'
  };

  parentNode?: any;
  unSensor: Function;
  affixDom: React.RefObject<HTMLDivElement> = React.createRef();
  footerDom: React.RefObject<HTMLDivElement> = React.createRef();
  timer: ReturnType<typeof setTimeout>;
  dom: React.RefObject<HTMLDivElement> = React.createRef();
  // Jay
  constructor(props: PanelProps) {
    super(props)
    this.setPanelLoading = this.setPanelLoading.bind(this)
    this.handleLink = this.handleLink.bind(this)
    this.state = {
      loading: false
    }
  }
  setPanelLoading(loading: boolean) {
    this.setState({
      loading
    })
  }

  componentDidMount() {
    const dom = this.dom?.current
    let parent: HTMLElement | Window | null = dom ? getScrollParent(dom) : null;
    if (!parent || parent === document.body) {
      parent = window;
    }
    this.parentNode = parent;
    parent.addEventListener('scroll', this.affixDetect);
    this.unSensor = resizeSensor(dom as HTMLElement, this.affixDetect);
    this.affixDetect();
  }

  componentWillUnmount() {
    const parent = this.parentNode;
    this.parentNode = null
    parent && parent.removeEventListener('scroll', this.affixDetect);
    this.unSensor && this.unSensor();
    clearTimeout(this.timer);
  }

  @autobind
  affixDetect() {
    if (
      !this.props.affixFooter ||
      !this.affixDom.current ||
      !this.footerDom.current
    ) {
      return;
    }

    const affixDom = this.affixDom.current;
    const footerDom = this.footerDom.current;
    const offsetBottom =
      this.props.affixOffsetBottom ?? this.props.env.affixOffsetBottom ?? 0;
    let affixed = false;

    if (footerDom.offsetWidth) {
      affixDom.style.cssText = `bottom: ${offsetBottom}px;width: ${footerDom.offsetWidth}px`;
    } else {
      this.timer = setTimeout(this.affixDetect, 250);
      return;
    }

    if (this.props.affixFooter === 'always') {
      affixed = true;
      footerDom.classList.add('invisible2');
    } else {
      const clip = footerDom.getBoundingClientRect();
      const clientHeight = window.innerHeight;
      // affixed = clip.top + clip.height / 2 > clientHeight;
      affixed = clip.bottom > clientHeight - offsetBottom;
    }

    affixed ? affixDom.classList.add('in') : affixDom.classList.remove('in');
  }
  
  // renderStatistics() {
  //   const { header, classnames: cx, render, data } = this.props;
  //   if (header) {
  //     return (
  //       <div className={cx('Panel-statistics', isMobile() ? 'Table-statistic-mobile' : '')}>
  //         {render('aggregate', header, { items: [data], query: data })}
  //       </div>
  //     )
  //   }
  //   return null
  // }
  
  renderBody(): JSX.Element | null {
    const {
      type,
      className,
      data,
      header,
      body,
      render,
      bodyClassName,
      headerClassName,
      actionsClassName,
      footerClassName,
      children,
      title,
      actions,
      footer,
      classPrefix: ns,
      formMode,
      formHorizontal,
      subFormMode,
      subFormHorizontal,
      ...rest
    } = this.props;

    const subProps = {
      data,
      ...rest,
      formMode: subFormMode || formMode,
      formHorizontal: subFormHorizontal || formHorizontal,
      setPanelLoading: this.setPanelLoading // Jay
    };

    return children
      ? typeof children === 'function'
        ? children(this.props)
        : children
      : body
        ? render('body', body, subProps)
        : null;
  }

  renderActions() {
    const { actions, render, btnMapdisable, isDialogMode, wrapWithPanel } = this.props;
    if (Array.isArray(actions) && actions.length && !(isDialogMode && wrapWithPanel)) {
      return actions.map((action, key) => render('action', action, {
        type: action.type || 'button',
        key: key,
        disabled: (action as any).api && btnMapdisable
      })
      );
    }

    return null;
  }

  handleLink() {
    const { classnames, title, env, linkUrl } = this.props
    ModleHandleClick({ classnames, env, linkUrl, linkType: 1, linkTitle: title, linkId: getHashCode(title), value: true })
  }

  render() {
    const {
      type,
      className,
      data,
      header,
      body,
      render,
      bodyClassName,
      headerClassName,
      actionsClassName,
      footerClassName,
      footerWrapClassName,
      children,
      title,
      footer,
      affixFooter,
      classPrefix: ns,
      classnames: cx,
      translate: __,
      isDetail,
      flowProcess,
      linkUrl,
      inModal,
      ...rest
    } = this.props;

    const inCombination: boolean = className?.includes('Panel-Combination') ?? false
    const subProps = {
      data,
      ...rest
    };

    const footerDoms = [];
    const actions = this.renderActions();
    actions &&
      footerDoms.push(
        <div
          key="actions"
          className={cx(`Panel-btnToolbar`, actionsClassName || `Panel-footer`)}
        >
          {actions}
        </div>
      );

    footer &&
      footerDoms.push(
        <div key="footer" className={cx(footerClassName || `Panel-footer`)}>
          {render('footer', footer, subProps)}
        </div>
      );

    // console.log(header, footerDoms)
    let footerDom = (footerDoms.length || (Array.isArray(header) ? header.length : header)) ? (
      <div
        className={cx('Panel-footerWrap', footerWrapClassName)}
        ref={this.footerDom}
      >
        {footerDoms.length > 0 && footerDoms}
      </div>
    ) : null;

    return (
      <div ref={this.dom} className={cx(`Panel`, className || `Panel--default`, inModal && 'in-modal', isDetail && !flowProcess && 'detail-form-panel', footerDoms.length && 'with-fix-footer')} style={{ height: className?.includes('h-') ? 'none' : '100%' }}>
        {title ? (
          <div className={cx(headerClassName || `Panel-heading`, inCombination ? 'Panel-heading--combination' : '')}>
            <h3 className={cx(`Panel-title`, inCombination ? 'Panel-title--combination' : '')}>
              {render('title', title, subProps)}
            </h3>
            {(inCombination && !!linkUrl) &&
              (isMobile() ?
                <EllipsisOutlined onClick={(e) => { e.stopPropagation(); this.handleLink() }} style={{ fontSize: 24 }} /> :
                <h3 onClick={(e) => { e.stopPropagation(); this.handleLink() }} style={{ color: '#1890ff', cursor: 'pointer', fontSize: 14 }}>{__('ViewMore')}</h3>)}
          </div>
        ) : null
        }

        <div className={bodyClassName || `${ns}Panel-body`}>
          {this.renderBody()}
        </div>

        {footerDom}

        {
          affixFooter && footerDoms.length ? (
            <div
              ref={this.affixDom}
              className={cx(
                'Panel-fixedBottom Panel-footerWrap',
                footerWrapClassName
              )}
            >
              {footerDoms}
            </div>
          ) : null
        }

        {/* Jay 增加 Spinner */}
        <Spinner size="md" overlay key="info" style={{ top: '45%', left: '45%' }} show={this.state.loading} />
      </div >
    );
  }
}

@Renderer({
  type: 'panel'
})
export class PanelRenderer extends Panel { }
