import React from 'react';
import { Renderer, RendererProps } from '../factory';
import { SchemaNode, Schema, Action, PlainObject } from '../types';
import { filter, evalExpression } from '../utils/tpl';
import Checkbox from '../components/Checkbox';
import { padArr, isVisible, isDisabled, noop, hashCode, isMobile } from '../utils/helper';
import { resolveVariable, resolveVariableAndFilter } from '../utils/tpl-builtin';
import QuickEdit, { SchemaQuickEdit } from './QuickEdit';
import PopOver, { SchemaPopOver } from './PopOver';
import { TableCell } from './Table';
import Copyable, { SchemaCopyable } from './Copyable';
import omit = require('lodash/omit');
import {
  BaseSchema,
  SchemaClassName,
  SchemaCollection,
  SchemaExpression,
  SchemaObject,
  SchemaTpl,
  SchemaUrlPath
} from '../Schema';
import { ActionSchema } from './Action';
import { Card } from '../components/Card';
import { findDOMNode } from 'react-dom';
import { IItem } from '../store/list';
import { Icon } from '../components/icons';
import { isModelType } from 'mobx-state-tree';
import { Modal } from 'antd';
import { linkJump, ModleHandleClick, openImageEnlarge } from '../utils/utils';

export type CardBodyField = SchemaObject & {
  /**
   * 列标题
   */
  label: string;

  /**
   * label 类名
   */
  labelClassName?: SchemaClassName;

  /**
   * 绑定字段名
   */
  name?: string;

  /**
   * 配置查看详情功能
   */
  popOver?: SchemaPopOver;

  /**
   * 配置快速编辑功能
   */
  quickEdit?: SchemaQuickEdit;

  /**
   * 配置点击复制功能
   */
  copyable?: SchemaCopyable;
};

/**
 * Card 卡片渲染器。
 * 文档：https://baidu.gitee.io/amis/docs/components/card
 */
export interface CardSchema extends BaseSchema {
  /**
   * 指定为 card 类型
   */
  type: 'card';

  /**
   * 头部配置
   */
  header?: {
    className?: SchemaClassName;

    /**
     * 标题
     */
    title?: SchemaTpl;
    titleClassName?: SchemaClassName;

    /**
     * 副标题
     */
    subTitle?: SchemaTpl;
    subTitleClassName?: SchemaClassName;
    subTitlePlaceholder?: string;

    /**
     * 描述
     */
    description?: SchemaTpl;

    /**
     * 描述占位内容
     */
    descriptionPlaceholder?: string;

    /**
     * 描述占位类名
     */
    descriptionClassName?: SchemaClassName;

    /**
     * @deprecated 建议用 description
     */
    desc?: SchemaTpl;

    /**
     * @deprecated 建议用 descriptionPlaceholder
     */
    descPlaceholder?: SchemaTpl;

    /**
     * @deprecated 建议用 descriptionClassName
     */
    descClassName?: SchemaClassName;

    /**
     * 图片地址
     */
    avatar?: any;
    /**
     * 图片显示比例
     */
    thumbRatio?: '1:1' | '4:3' | '16:9';
    avatarText?: SchemaTpl;
    avatarTextBackground?: String[];
    avatarTextClassName?: SchemaClassName;

    /**
     * 图片包括层类名
     */
    avatarClassName?: SchemaClassName;

    /**
     * 图片类名。
     */
    imageClassName?: SchemaClassName;

    /**
     * 是否点亮
     */
    highlight?: SchemaExpression;
    highlightClassName?: SchemaClassName;

    /**
     * 链接地址
     */
    href?: SchemaTpl;

    /**
     * 是否新窗口打开
     */
    blank?: boolean;
  };

  /**
   * 内容区域
   */
  body?: Array<CardBodyField>;

  /**
   * 多媒体区域
   */
  media?: {
    className?: SchemaClassName;

    /**
     * 多媒体类型
     */
    type?: 'image' | 'video';

    /**
     * 多媒体链接地址
     */
    url?: SchemaUrlPath;

    /**
     * 多媒体区域位置
     */
    position?: 'top' | 'left' | 'right' | 'bottom';

    /**
     * 类型为video时是否自动播放
     */
    autoPlay?: boolean;

    /**
     * 类型为video时是否是直播
     */
    isLive?: boolean;

    /**
     * 类型为video时视频封面
     */
    poster?: SchemaUrlPath;
  };

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

  /**
   * 工具栏按钮
   */
  toolbar?: Array<ActionSchema>;

  /**
   * 次要说明
   */
  secondary?: SchemaTpl;
}
export interface CardProps
  extends RendererProps,
  Omit<CardSchema, 'className'> {
  onCheck: (item: IItem) => void;
  actionsCount: number;
  itemIndex?: number;
  dragging?: boolean;
  selectable?: boolean;
  selected?: boolean;
  checkable?: boolean;
  multiple?: boolean;
  hideCheckToggler?: boolean;
  item: IItem;
  checkOnItemClick?: boolean;
}
interface CardState {
  visible: boolean
}
@Renderer({
  type: 'card'
})
export class CardRenderer extends React.Component<CardProps, CardState> {
  static defaultProps = {
    className: '',
    // avatarClassName: '',
    avatarClassName: 'thumb avatar m-r-sm',//Aug
    headerClassName: '',
    footerClassName: '',
    secondaryClassName: '',
    avatarTextClassName: '',
    bodyClassName: '',
    actionsCount: 10,
    titleClassName: '',
    highlightClassName: '',
    subTitleClassName: '',
    descClassName: '',
    descriptionClassName: '',
    imageClassName: '',
    highlight: false,
    blank: true,
    dragging: false,
    selectable: false,
    checkable: true,
    selected: false,
    hideCheckToggler: false,
    checkOnItemClick: true
  };

  static propsList: Array<string> = [
    'avatarClassName',
    'avatarTextClassName',
    'bodyClassName',
    'actionsCount',
    'titleClassName',
    'highlightClassName',
    'subTitleClassName',
    'descClassName',
    'descriptionClassName',
    'imageClassName',
    'hideCheckToggler'
  ];

  constructor(props: CardProps) {
    super(props);

    this.handleClick = this.handleClick.bind(this);
    this.handleAction = this.handleAction.bind(this);
    this.handleCheck = this.handleCheck.bind(this);
    this.getPopOverContainer = this.getPopOverContainer.bind(this);
    this.handleQuickChange = this.handleQuickChange.bind(this);
    this.state = {
      visible: false
    }
  }

  isHaveLink() {
    const { href, itemAction, onCheck, checkOnItemClick, checkable } = this.props;
    return href || itemAction || onCheck || (checkOnItemClick && checkable);
  }



  handleClick(e: React.MouseEvent<HTMLDivElement>) {
    const {
      item,
      href,
      data,
      env,
      blank,
      itemAction,
      onAction,
      onCheck,
      selectable,
      checkOnItemClick
    } = this.props;

    if (href) {
      env.jumpTo(filter(href, data), {
        type: 'button',
        actionType: 'url',
        blank
      });
      return;
    }

    if (itemAction) {
      onAction && onAction(e, itemAction, item?.data || data);
      return;
    }
    if (checkOnItemClick && selectable) {
      onCheck?.(item);
    }
  }

  handleAction(e: React.UIEvent<any>, action: Action, ctx: object) {
    const { onAction, item } = this.props;
    this.setState({ visible: false })
    onAction && onAction(e, action, ctx || item.data);
  }

  handleCheck(e: React.MouseEvent<any>) {
    const item = this.props.item;
    this.props.onCheck && this.props.onCheck(item);
  }

  getPopOverContainer() {
    return findDOMNode(this);
  }

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

  renderToolbar() {
    const {
      selectable,
      checkable,
      selected,
      checkOnItemClick,
      multiple,
      hideCheckToggler,
      classnames: cx,
      toolbar,
      render,
      bulkActions,
      dragging,
    } = this.props;

    const toolbars: Array<JSX.Element> = [];

    if (selectable && !hideCheckToggler && bulkActions > 0) {
      toolbars.push(
        <Checkbox
          key="check"
          className={cx('Card-checkbox Card-CheckboxNoModle')}
          type={multiple ? 'checkbox' : 'radio'}
          disabled={!checkable}
          checked={selected}
          onChange={checkOnItemClick ? noop : this.handleCheck}
        />
      );
    }

    if (Array.isArray(toolbar)) {
      toolbar.forEach((action, index) =>
        toolbars.push(
          render(
            `toolbar/${index}`,
            {
              type: 'button',
              level: 'link',
              size: 'sm',
              ...(action as any)
            },
            {
              key: index
            }
          )
        )
      );
    }

    if (dragging) {
      toolbars.push(
        <div className={cx('Card-dragBtn')}>
          <Icon icon="drag-bar" className="icon" />
        </div>
      );
    }

    return toolbars.length ? (
      <div className={cx('Card-toolbar')} onClick={(e) => { e.stopPropagation() }}>{toolbars}</div>
    ) : null;
  }

  renderActions() {
    const {
      actions,
      render,
      dragging,
      actionsCount,
      data,
      classnames: cx
    } = this.props;

    if (Array.isArray(actions)) {
      const group = padArr(
        actions.filter(item => isVisible(item, data)),
        actionsCount
      );

      return group.map((actions, groupIndex) => (
        <div key={groupIndex} className={cx('Card-actions')}>
          {actions.map((action, index) => {
            const size = action.size || 'sm';
            return render(
              `action/${index}`,
              {
                // level: 'link',
                type: 'button',
                ...action,
                size
              },
              {
                // isMenuItem: true,
                key: index,
                index,
                disabled: dragging || isDisabled(action, data),
                className: cx(
                  'Card-action',
                  action.className || `${size ? `Card-action--${size}` : ''}`
                ),
                // componentClass: 'a',
                onAction: this.handleAction
              }
            );
          })}
        </div>
      ));
    }
    return;
  }

  renderChild(
    node: SchemaNode,
    region: string = 'body',
    key: any = 0
  ): React.ReactNode {
    //fieldNum 默认一行几个
    const { render } = this.props;

    if (typeof node === 'string' || typeof node === 'number') {
      return render(region, node, { key }) as JSX.Element;
    }

    const childNode: Schema = node as Schema;

    if (childNode.type === 'hbox' || childNode.type === 'grid') {
      return render(region, node, {
        key,
        itemRender: this.itemRender
      }) as JSX.Element;
    }

    return this.renderFeild(region, childNode, key, this.props);
  }

  itemRender(field: any, index: number, props: any) {
    return this.renderFeild(`column/${index}`, field, index, props);
  }

  renderFeild(region: string, field: any, key: any, props: any) {
    const { render, classnames: cx, itemIndex, dataColumns, tableLayout, fieldNum = 3 } = props;
    const data = this.props.data;
    if (!isVisible(field, data)) {
      return;
    }

    const $$id = field.$$id ? `${field.$$id}-field` : '';
    const itemData = dataColumns.filter((item: any) => ['mapping', 'progress', 'link', 'lion-upload', 'color'].some(Item => item.type == Item)).find((item: any) => item.name == field.name)
    const canJump = field.linkId ? linkJump(field.linkId ?? '', data, field.jumpDisabledOn) : false;
    return (
      <div className={cx('Card-field')} key={key} style={{ width: `${100 / fieldNum}%` }}>
        {field && field.label ? (<>
          <label className={cx('Card-fieldLabel', field.labelClassName)}>
            <span>
              {field.label}
            </span>:
          </label>
        </>
        ) : null}
        <div className={cx('Card-fieldValue', field.linkUrl && canJump ? 'is-linkUrl' : '')}
          style={{ flex: 1 }} title={field.name ? resolveVariable(field.name, data) : undefined}
          onClick={(e) => {
            if (canJump) {
              e.stopPropagation()
              ModleHandleClick({ ...this.props, ...field, value: data[field.name] }, e.target)
            }
          }}
        >
          {
            itemData ? render(region, itemData, {
              className: cx('Card-fieldValue', field.className, field.linkUrl && canJump ? 'is-linkUrl' : ''),
              rowIndex: itemIndex,
              colIndex: key,
              value: field.name ? resolveVariable(field.name, data) : undefined,
              label: undefined,
              mode: tableLayout ?? 'normal',
              popOverContainer: this.getPopOverContainer,
              onAction: this.handleAction,
              onQuickChange: this.handleQuickChange
            }) :
              render(
                region,
                {
                  ...field,
                  field: field,
                  $$id,
                  type: 'card-item-field'
                },
                {
                  className: cx('Card-fieldValue', field.className),
                  rowIndex: itemIndex,
                  colIndex: key,
                  value: field.name ? resolveVariable(field.name, data) : undefined,
                  popOverContainer: this.getPopOverContainer,
                  onAction: this.handleAction,
                  onQuickChange: this.handleQuickChange
                }
              ) as JSX.Element
          }
        </div>
      </div>
    );
  }

  renderBody(num?: number) {
    const { body } = this.props;

    if (!body) {
      return null;
    }

    if (Array.isArray(body)) {
      return body.map((child, index) => {
        if (num && num !== 0 && index >= num) {
          return
        }
        return this.renderChild(child, `body/${index}`, index)
      });
    }

    return this.renderChild(body, 'body');
  }

  rederTitle() {
    const { render, data, header } = this.props;
    if (header) {
      const { title: titleTpl } = header || {};
      const title = filter(titleTpl, data);
      return title ? this.handelRenderDom(titleTpl, render('title', titleTpl!)) : titleTpl ? "--" : undefined;
    }
    return;
  }
  renderIcon = () => {
    const {
      classnames: cx,
      data,
      header
    } = this.props;
    if (header) {
      const { highlightClassName, highlight: highlightTpl } = header;
      const highlight = !!evalExpression(highlightTpl!, data as object);
      if (highlight) {
        return <div> <i className={cx('Card-highlight', highlightClassName)} /></div>
      }
    }
    return
  }

  renderSubTitle() {
    const { render, data, header } = this.props;
    if (header) {
      const { subTitle: subTitleTpl } = header || {};

      const subTitle = filter(subTitleTpl, data);
      return subTitle ? this.handelRenderDom(subTitleTpl, render('sub-title', subTitleTpl!)) : subTitleTpl ? '--' : undefined;
    }
    return;
  }

  renderSubTitlePlaceholder() {
    const { render, header, classnames: cx } = this.props;
    if (header) {
      const { subTitlePlaceholder } = header || {};

      return subTitlePlaceholder
        ? render('sub-title', subTitlePlaceholder, {
          className: cx('Card-placeholder')
        })
        : undefined;
    }
    return;
  }

  renderDesc() {
    const { render, data, header } = this.props;

    if (header) {
      const { desc: descTpl, description: descriptionTpl } = header || {};
      const desc = filter(descriptionTpl! || descTpl!, data);
      return desc
        ? this.handelRenderDom(descriptionTpl! || descTpl!, render('desc', descriptionTpl! || descTpl!, {
          className: !desc ? 'text-muted' : null
        }))

        : descriptionTpl! || descTpl! ? '--' : undefined;
    }
    return;
  }

  renderDescPlaceholder() {
    const { render, header } = this.props;

    if (header) {
      const descPlaceholder =
        header.descriptionPlaceholder || header.descPlaceholder;
      return descPlaceholder
        ? render('desc', descPlaceholder, {
          className: !descPlaceholder ? 'text-muted' : null
        })
        : undefined;
    }
    return;
  }

  renderAvatar() {
    const { data, header } = this.props;
    if (header) {
      const { avatar: avatarTpl } = header || {};
      const avatar = data?.[avatarTpl?.replace(/\$\{([^}]+)\}/g, '$1')]

      return avatar ? avatar : undefined;
    }
    return;
  }

  renderAvatarText() {
    const { render, data, header } = this.props;
    if (header) {
      const { avatarText: avatarTextTpl } = header || {};

      const avatarText = filter(avatarTextTpl, data);
      const itemTags = avatarText?.split?.(',')

      return avatarText ?
        itemTags ? <div className='top-item tags'>{
          itemTags.map((item: string) => <div className='tag-item' title={item}>
            {this.handelRenderDom(avatarTextTpl, render('avatarText', avatarTextTpl!), item)}
          </div>)
        }
        </div> :
          this.handelRenderDom(avatarTextTpl, render('avatarText', avatarTextTpl!)) :
        undefined;
    }
    return;
  }

  renderSecondary() {
    const { render, data, secondary: secondaryTextTpl } = this.props;

    const secondary = filter(secondaryTextTpl, data);
    return secondary ? this.handelRenderDom(secondaryTextTpl, render('secondary', secondaryTextTpl!)) : secondaryTextTpl ? '--' : undefined;
  }

  renderAvatarTextStyle() {
    const { header, data } = this.props;
    if (header) {
      const { avatarText: avatarTextTpl, avatarTextBackground } = header;
      const avatarText = filter(avatarTextTpl, data);
      const avatarTextStyle: PlainObject = {};
      if (avatarText && avatarTextBackground && avatarTextBackground.length) {
        avatarTextStyle['background'] =
          avatarTextBackground[
          Math.abs(hashCode(avatarText)) % avatarTextBackground.length
          ];
      }
      return avatarTextStyle;
    }
    return;
  }

  renderMedia() {
    const { media, classnames: cx, render, region, data } = this.props;
    if (media) {
      const { type, url, className, autoPlay, isLive, poster } = media;
      const mediaUrl = resolveVariableAndFilter(url, data, '| raw');

      if (type === 'image' && mediaUrl) {
        return (
          <img
            className={cx('Card-multiMedia-img', className)}
            src={mediaUrl}
          />
        );
      } else if (type === 'video' && mediaUrl) {
        return (
          <div className={cx('Card-multiMedia-video', className)}>
            {
              render(region, {
                type: type,
                autoPlay: autoPlay,
                poster: poster,
                src: mediaUrl,
                isLive: isLive
              }) as JSX.Element
            }
          </div>
        );
      }
    }
    return;
  }

  handelRenderDom = (body: string | undefined, content: any, value?: string) => {
    const name = body?.replace(/\$\{([^}]+)\}/g, '$1') ?? ''
    const { dataColumns, render } = this.props
    const itemData = dataColumns.find((items: any) => ['mapping', 'link'].some(item => items.type == item) && items.name == name)
    if (itemData) {
      if (value) {
        return render(name, itemData, { value: value })
      }
      return render(name, itemData)
    }

    return content
  }
  render() {
    const {
      header,
      className,
      avatarClassName,
      avatarTextClassName,
      descClassName,
      descriptionClassName,
      titleClassName,
      subTitleClassName,
      bodyClassName,
      imageClassName,
      headerClassName,
      secondaryClassName,
      footerClassName,
      mediaClassName,
      media,
      onImageEnlarge,
      env,
      classPrefix: ns,
      ...rest
    } = this.props;
    const { visible } = this.state
    const headerCn = header?.className || headerClassName;
    const titleCn = header?.titleClassName || titleClassName;
    const subTitleCn = header?.subTitleClassName || subTitleClassName;
    const descCn = header?.descClassName || descClassName;
    const descriptionCn =
      header?.descriptionClassName || descriptionClassName || descCn;
    const avatarTextCn = header?.avatarTextClassName || avatarTextClassName;
    const avatarCn = header?.avatarClassName || avatarClassName;
    const imageCn = header?.imageClassName || imageClassName;
    const mediaPosition = media?.position;
    const baseUrl = env?.axiosInstance?.defaults?.baseURL || env?.ajaxApi || '';
    const imgUrl = (this.renderAvatar()?.info?.[0]?.addr as string)?.startsWith?.("http") ? this.renderAvatar()?.info?.[0]?.addr : ((baseUrl ? baseUrl : '') + this.renderAvatar()?.info?.[0]?.addr)
    return (<>
      <Card
        {...rest}
        env={env}
        icon={this.renderIcon()}
        title={this.rederTitle()}
        subTitle={this.renderSubTitle()}
        subTitlePlaceholder={this.renderSubTitlePlaceholder()}
        description={this.renderDesc()}
        descriptionPlaceholder={this.renderDescPlaceholder()}
        children={this.renderBody()}
        actions={this.renderActions()}
        avatar={this.renderAvatar()}
        avatarText={this.renderAvatarText()}
        secondary={this.renderSecondary()}
        toolbar={this.renderToolbar()}
        avatarClassName={avatarCn}
        avatarTextStyle={this.renderAvatarTextStyle()}
        avatarTextClassName={avatarTextCn}
        className={className}
        titleClassName={titleCn}
        media={this.renderMedia()}
        subTitleClassName={subTitleCn}
        mediaPosition={mediaPosition}
        descriptionClassName={descriptionCn}
        imageClassName={imageCn}
        headerClassName={headerCn}
        footerClassName={footerClassName}
        secondaryClassName={secondaryClassName}
        bodyClassName={bodyClassName}
        onImageEnlarge={onImageEnlarge}
        handleModleClick={(visible) => { this.setState({ visible }) }}
        onClick={this.isHaveLink() ? this.handleClick : undefined}
        titleField={header?.title}
        thumbRatio={header?.thumbRatio}
        subTitleField={header?.subTitle}
      ></Card>

      {isMobile() && <Modal
        zIndex={9}
        className={`${ns}Modal-mobile ${ns}Card-modal`}
        bodyStyle={{ overflowY: 'auto', padding: 0 }}
        closable={false}
        visible={visible}
        getContainer={this.props.env.getModalContainer}
        footer={false}
        centered
        onCancel={(e) => {
          e.stopPropagation();
          this.setState({ visible: false });
        }}
      >
        <div className={`${ns}Card-modal-content`}>
          <div className={`${ns}Card-modal-head`}>

            {this.renderAvatar() && <div className={`${ns}Card-modal-head-avtarimg`}>
              {this.renderAvatar()?.info?.[0]?.addr ?
                <span className={`${ns}Card-modal-head-avtarimg-avtar avatarClassName`} onClick={(e) => {
                  e.stopPropagation()
                  openImageEnlarge([this.renderAvatar()?.info?.[0]], baseUrl, onImageEnlarge, env)
                }}>
                  <img className={`${ns}Card-img  imageClassName`} src={imgUrl} />
                </span> :
                <div onClick={(e) => e.stopPropagation()} className={`${ns}Card-modal-head-avtarimg-avtarsvg`}>
                  <Icon icon='no-resources' />
                  No image
                </div>}
            </div>}

            <div className={`${ns}Card-modal-head-content`}>
              {this.renderAvatarText() ? (
                <div className={`${ns}Card-title-text`}>{this.renderAvatarText()}</div>
              ) : null}
              <div className={`${ns}Card-title-body`}>
                {this.rederTitle() ? (
                  <div className={`${ns}Card-title titleClassName`}>{this.rederTitle()}</div>
                ) : null}
              </div>

              {this.renderSubTitle() || this.renderSubTitlePlaceholder() ? (
                <div className={`${ns}Card-subTitle subTitleClassName`}>
                  {this.renderSubTitle()
                    ? this.renderSubTitle()
                    : this.renderSubTitlePlaceholder()
                      ? this.renderSubTitlePlaceholder()
                      : null}
                </div>
              ) : null
              }
            </div>
          </div >
          <div className={`${ns}Card-modal-body`}>
            {this.renderBody()}
            {this.renderDesc() || this.renderDescPlaceholder() ? (
              <div className={`${ns}Card-desc ${descriptionClassName}`}>
                {this.renderDesc()
                  ? this.renderDesc()
                  : this.renderDescPlaceholder()
                    ? this.renderDescPlaceholder()
                    : null}
              </div>
            ) : null}
          </div>
          <div className={`${ns}Card-modal-footer`}>
            {this.renderActions()}
          </div >
        </div >
      </Modal >}
    </>

    );
  }
}

@Renderer({
  type: 'card-item-field'
})
@QuickEdit()
@PopOver()
@Copyable()
export class CardItemFieldRenderer extends TableCell {
  static defaultProps = {
    ...TableCell.defaultProps,
    wrapperComponent: 'div'
  };

  static propsList = [
    'quickEdit',
    'quickEditEnabledOn',
    'popOver',
    'copyable',
    'inline',
    ...TableCell.propsList
  ];

  render() {
    let {
      type,
      className,
      render,
      style,
      wrapperComponent: Component,
      labelClassName,
      value,
      data,
      children,
      width,
      innerClassName,
      label,
      tabIndex,
      onKeyUp,
      field,
      ...rest
    } = this.props;

    const schema = {
      ...field,
      className: innerClassName,
      type: (field && field.type) || 'plain'
    };

    let body = children
      ? children
      : render('field', schema, {
        ...omit(rest, Object.keys(schema)),
        value,
        data
      });

    if (width) {
      style = style || {};
      style.width = style.width || width;
      body = (
        <div style={{ width: !/%/.test(String(width)) ? width : '' }}>{body}</div>
      );
    }

    if (!Component) {
      return body as JSX.Element;
    }

    return (
      <Component
        style={style}
        className={className}
        tabIndex={tabIndex}
        onKeyUp={onKeyUp}
      >
        {body}
      </Component>
    );
  }
}
