import React from 'react';
import { Renderer } from '../../../factory';
import List, { ListItem, ListProps, ListItemProps } from '../../../renderers/List';
import { ListStore, IItem } from '../../../store/list';
import { SchemaNode, Schema, Action } from '../../../types';
import { findDOMNode } from 'react-dom';
import offset from '../../../utils/offset';
import { getStyleNumber } from '../../../utils/dom';
import Button from '../../../components/Button';
import Checkbox from '../../../components/Checkbox';
import './index.css'

interface LionListProps {
  onPullUpRequest?: (values: object) => void;
}
import { isMobile, noop } from '../../../utils/helper'
import Tooltip from 'antd/lib/Tooltip';
import { filter } from '../../../utils/tpl';
import { isPureVariable } from '../../../utils/tpl-builtin'

const errImg = 'data:image/png;base64,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'
export class LionList extends List {
  static defaultProps = {
    hideCheckToggler: isMobile()
  }
  constructor(props: ListProps & LionListProps) {
    super(props);

    // 移动端默认隐藏勾选框
    if (this.getMobileUI() && props.hideCheckToggler === void 0) {
      props.store.update({ hideCheckToggler: true });
    }

  }

  xhrTimer: any;

  pullUpRefresh = (e: any) => {
    const target = e.target;
    let scrollHeight = target?.scrollHeight;
    let scrollTop = target?.scrollTop;
    let clientHeight = target?.clientHeight;
    if (Math.ceil(scrollTop + clientHeight) >= scrollHeight && !this.xhrTimer) {
      this.xhrTimer = setTimeout(async () => {
        clearTimeout(this.xhrTimer);
        this.xhrTimer = null;
        const res = this.props.onPullUpRequest && await this.props.onPullUpRequest({});
      }, 100)
    }
  }

  componentDidMount() {
    this.calcAutoFillHeight()
  }

  calcAutoFillHeight() {
    const { autoFillHeight = true, footerToolbar, classPrefix: ns } = this.props;
    if (!autoFillHeight) {
      return;
    }
    const dom = findDOMNode(this) as HTMLElement;
    const top = offset(dom).top;

    const viewportHeight = window.innerHeight;

    let allParentPaddingButtom = 0;
    let parentNode = dom.parentElement;
    while (parentNode) {
      const paddingButtom = getStyleNumber(parentNode, 'padding-bottom');
      const borderBottom = getStyleNumber(parentNode, 'border-bottom-width');
      allParentPaddingButtom =
        allParentPaddingButtom + paddingButtom + borderBottom;
      parentNode = parentNode.parentElement;

    }
    const n = viewportHeight - top - allParentPaddingButtom
    dom.style.height = n + 'px'
  }

  getMobileUI() {
    return isMobile() && this.props.useMobileUI
  }

  renderHeader() {
    const {
      header,
      headerClassName,
      headerToolbarRender,
      render,
      showHeader,
      store,
      classnames: cx
    } = this.props;

    if (showHeader === false) {
      return null;
    }

    const child = headerToolbarRender
      ? headerToolbarRender(
        {
          ...this.props,
          selectedItems: store.selectedItems.map(item => item.data),
          items: store.items.map(item => item.data),
          unSelectedItems: store.unSelectedItems.map(item => item.data)
        },
        this.renderToolbar
      )
      : null;
    const actions = this.renderActions('header');
    const toolbarNode =
      actions || child ? (
        <div
          className={cx('List-toolbar', headerClassName)}
          key="header-toolbar"
        >
          {actions}
          {child}
        </div>
      ) : null;
    const headerNode =
      header && (!Array.isArray(header) || header.length) ? (
        <div className={cx('List-header', headerClassName)} key="header">
          {render('header', header)}
        </div>
      ) : null;
    return headerNode && toolbarNode
      ? [headerNode, toolbarNode]
      : headerNode || toolbarNode || null;
  }

  renderFooter() {
    const {
      footer,
      footerClassName,
      footerToolbar,
      headerToolbar,
      footerToolbarRender,
      render,
      showFooter,
      store,
      classnames: cx
    } = this.props;

    if (showFooter === false) {
      return null;
    }

    let _footer = footerToolbar || []
    if (this.getMobileUI()) {
      // 勾选批量状态时
      if (!store.hideCheckToggler) {
        _footer = ["bulkActions"]
      } else {
        if (headerToolbar) {
          // 移动端将所有操作统一放在在底部
          _footer = _footer.concat(headerToolbar)
        }
        // 非勾选状态补渲染不批量操作
        _footer = _footer.filter((item: any) => {
          const type = (item as Schema).type || item
          return !['bulk-actions', 'bulkActions'].includes(type)
        })
      }
    }

    const child = footerToolbarRender
      ? footerToolbarRender(
        {
          ...this.props,
          selectedItems: store.selectedItems.map(item => item.data),
          items: store.items.map(item => item.data),
          unSelectedItems: store.unSelectedItems.map(item => item.data)
        },
        this.renderToolbar,
        // PC端始终显示foottoolbar, 移动端勾选状态显示 批量
        _footer
      )
      : null;
    const actions = this.renderActions('footer');

    const toolbarNode =
      actions || child ? (
        <div
          className={cx('List-toolbar', 'List-footer', footerClassName)}
          key="footer-toolbar"
        >
          {actions}
          {child}
        </div>
      ) : null;
    const footerNode =
      footer && (!Array.isArray(footer) || footer.length) ? (
        <div className={cx('List-footer', footerClassName)} key="footer">
          {render('footer', footer)}
        </div>
      ) : null;
    return footerNode && toolbarNode
      ? [toolbarNode, footerNode]
      : footerNode || toolbarNode || null;
  }

  renderCheckAll() {
    const { store, multiple, selectable, classnames: cx, classPrefix: ns, translate: __ } = this.props;

    if (
      !store.selectable ||
      !multiple ||
      !selectable ||
      store.dragging ||
      !store.items.length
    ) {
      return null;
    }


    return (
      this.getMobileUI() ? <div key="checkall" className={cx('Mobile-checkall')} >
        <Checkbox
          classPrefix={ns}
          type={multiple ? 'checkbox' : 'radio'}
          checked={store.allChecked}
          onChange={this.handleCheckAll}
          inline
        />
        <span>{__('Select.checkAll')}</span>
      </div> :
        <Button
          key="checkall"
          // tooltip="切换全选"
          onClick={() => this.handleCheckAll()}
          size="sm"
          level={store.allChecked ? 'info' : 'default'}
        >
          {__('Select.checkAll')}
        </Button>

    );
  }

  renderActions(region: string) {
    let {
      actions,
      render,
      store,
      classnames: cx,
    } = this.props;

    let btn;
    actions = Array.isArray(actions) ? actions.concat() : [];

    if (
      !~this.renderedToolbars.indexOf('check-all') &&
      !store.hideCheckToggler &&
      this.getMobileUI() &&
      (btn = this.renderCheckAll())
    ) {
      actions.unshift({
        type: 'button',
        children: btn
      });
    }

    return Array.isArray(actions) && actions.length ? (
      <div className={cx('List-actions')}>
        {actions.map((action, key) =>
          render(
            `action/${key}`,
            {
              type: 'button',
              ...action
            },
            {
              onAction: this.handleAction,
              key,
              btnDisabled: store.dragging
            }
          )
        )}
      </div>
    ) : null;
  }

  renderHeaderContent() {
    const {
      classnames: cx,
      translate: __,
      filterRender,
      store,
    } = this.props;

    if (this.getMobileUI()) {
      {/* 搜索 */ }
      const filterNode = filterRender && filterRender()
      {/* 批量 */ }
      const checkAll = !~this.renderedToolbars.indexOf('check-all') && this.renderCheckAll() ?
        <span
          className={cx('Mobile-batch-manage', { 'is-active': !store.hideCheckToggler })}
          onClick={e => {
            e.preventDefault()
            store.toggableHideCheck()
          }} >
          {store.hideCheckToggler ? <i className='fa fa-tasks batch-manage-icon'></i> : __('Wizard.finish')}
        </span> : null
      return filterNode || checkAll ? (
        <div className={cx('Mobile-header-toolbar-wrapper')}>
          {filterNode}
          {checkAll}
        </div>
      ) : null

    }

    const heading = this.renderHeading();
    const header = this.renderHeader();
    return <>{header}{heading}</>

  }

  render() {
    const {
      className,
      itemClassName,
      store,
      render,
      multiple,
      listItem,
      onAction,
      checkOnItemClick,
      itemAction,
      classnames: cx,
      size,
      translate: __,

    } = this.props;

    this.renderedToolbars = [];

    const header = this.renderHeaderContent()
    const footer = this.renderFooter()

    return (
      <div
        className={cx('List', 'LionList', className, {
          [`List--${size}`]: size,
          'List--unsaved': !!store.modified || !!store.moved,
          'is-mobile': this.getMobileUI(),

        })}
        ref={this.bodyRef}
      >
        {header}

        <div className={cx('List-content', {
          'hasHeader': header,
          'hasFooter': footer,
        })}>
          {store.items.length ? (
            <div className={cx('List-items')}>
              {store.items.map((item, index) =>
                render(
                  `${index}`,
                  {
                    type: 'lion-list-item',
                    ...listItem
                  },
                  {
                    key: item.index,
                    className: cx(itemClassName, {
                      'is-checked': item.checked,
                      'is-modified': item.modified,
                      'is-moved': item.moved
                    }),
                    selectable: store.selectable,
                    checkable: item.checkable,
                    multiple,
                    item,
                    itemIndex: item.index,
                    hideCheckToggler: store.hideCheckToggler,
                    checkOnItemClick,
                    itemAction,
                    selected: item.checked,
                    onCheck: this.handleCheck,
                    dragging: store.dragging,
                    onAction,
                    data: item.locals,
                    onQuickChange: store.dragging ? null : this.handleQuickChange,
                    popOverContainer: this.getPopOverContainer
                  }
                )
              )}
            </div>
          ) : null}
        </div>
        {footer}
      </div>
    );
  }
}


@Renderer({
  type: 'lion-list',
  storeType: ListStore.name
})
export class LionListRenderer extends LionList {
  dragging: boolean;
  selectable: boolean;
  selected: boolean;
  title?: string;
  subTitle?: string;
  desc?: string;
  avatar?: string;
  avatarClassName?: string;
  body?: SchemaNode;
  actions?: Array<Action>;
  onCheck: (item: IItem) => void;
}


@Renderer({
  test: /(^|\/)(?:lion-list|lion-list-group)\/(?:.*\/)?lion-list-item$/,
  name: 'lion-list-item'
})
export class ListItemRenderer extends ListItem {
  static propsList = ['multiple', ...ListItem.propsList];
  constructor(props: ListItemProps) {
    super(props);
  }

  getValue(name: any, data: any, ...rest: Array<any>) {
    return isPureVariable(name) ? filter(name, data, ...rest) : data[name]
  }

  render() {
    const {
      className,
      data,
      avatar,
      title,
      titleClassName,
      subTitle,
      desc,
      avatarClassName,
      checkOnItemClick,
      render,
      checkable,
      classnames: cx,
      actionsPosition,
      itemAction,
      $schema,
      env,
      // Jay
      footable,
      footBody,
    } = this.props;

    let avaterImg = this.getValue(avatar, data, '| raw')
    if (avaterImg) {
      const baseUrl = env?.axiosInstance?.defaults?.baseURL || env?.ajaxApi || '';
      avaterImg = baseUrl + avaterImg
    }
    return (
      // Jay
      <div className={cx('ListItem-wapper')}>
        <div
          className={cx(
            `ListItem ListItem--actions-at-${actionsPosition || 'right'}`,
            {
              'ListItem--hasItemAction': itemAction
            },
            className,
            // Jay
            typeof (footable) === 'object' && footable.expand === 'all' && 'expand'
          )}
          // Jay
          onTouchStart={() => {
            footable && (this.touchStartTime = +new Date())
          }}
          // 这里不能用onTouchEnd，否则会有一些bug
          onClick={(e) => {
            if (footable && (+ new Date() - this.touchStartTime < 300)) {
              if (/expand/.test(e.currentTarget.className)) {
                e.currentTarget.classList.remove('expand')
              } else {
                e.currentTarget.classList.add('expand')
              }
            }
            ((checkOnItemClick && checkable) || itemAction)
              && this.handleClick(e)
          }}
        >
          {this.renderLeft()}
          {$schema.avatar ? (
            <span className={cx('ListItem-avatar', avatarClassName)}>
              <img src={avaterImg || errImg} alt="..." />
            </span>
          ) : null}
          <div className={cx('ListItem-content')}>
            {title ? (
              <p className={cx('ListItem-title', titleClassName)}>{this.getValue(title, data)}</p>
            ) : null}
            {subTitle ? (
              <div>
                <small className={cx('ListItem-subtitle')}>{this.getValue(subTitle, data)}</small>
              </div>
            ) : null}
            {desc ? <small className={cx('ListItem-subtitle')}>{this.getValue(desc, data)}</small> : null}
            {this.renderBody()}
          </div>
          {this.renderRight()}
        </div>
        {footable && footBody?.length &&
          <div className={cx('ListItem-footable', 'flex-wrap')}>
            {
              footBody?.map((column, index) =>
                <div key={index} className={'footItem flex items-center'}>
                  <span className="label">{column.label} :</span>
                  <span className="value">
                    {column.type ? render(`field`, column, { key: index, data }) : (data[column.name] || '-')}
                  </span>
                </div>)
            }
          </div>
        }
      </div>
    );
  }
}
