import React from 'react';
import { FormItem, FormControlProps, FormBaseControl } from './Item';
import cx from 'classnames';
import LazyComponent from '../../components/LazyComponent';
import { tokenize } from '../../utils/tpl-builtin';
import { normalizeApi } from '../../utils/api';
import { isMobile, ucFirst } from '../../utils/helper';
import Popover from 'antd/lib/popover';
import Button from 'antd/lib/button';
import { Icon } from '../../components/icons';
import { EditOutlined } from '@ant-design/icons';
import { Drawer } from '../../components/antdCompoentsProxy';
import { tools } from '../../utils/shell/tools';
import { isNil } from 'lodash';

// import LazyDraftComponent from '../../components/LazyDraftComponent';

/**
 * RichText
 * 文档：https://baidu.gitee.io/amis/docs/components/form/input-rich-text
 */
export interface RichTextControlSchema extends FormBaseControl {
  type: 'input-rich-text';

  vendor?: 'froala' | 'tinymce' | 'wangEditor';

  receiver?: string;
  videoReceiver?: string;

  /**
   * 接收器的字段名
   */
  fileField?: string;

  /**
   * 边框模式，全边框，还是半边框，或者没边框。
   */
  borderMode?: 'full' | 'half' | 'none';

  options?: any;
}

export interface RichTextProps extends FormControlProps {
  options?: any;
  vendor?: 'froala' | 'tinymce' | 'wangEditor';
}

function loadRichText(
  // Jay
  // type: 'tinymce' | 'froala' = 'froala'
  type: 'tinymce' | 'froala' | 'wangEditor' = 'wangEditor'
): () => Promise<any> {
  return () =>
    type === 'wangEditor' ?
      import('../../components/WangEditor').then(item => item.default) :
      type === 'tinymce'
        ? import('../../components/Tinymce').then(item => item.default)
        : import('../../components/RichText').then(item => item.default);
}
interface RichTextstate {
  focused: boolean,
  popoverVisibleDefault: boolean,
  inputValue: any,
  openRich: boolean,
}
export default class RichTextControl extends React.Component<
  RichTextProps,
  RichTextstate
> {
  static defaultProps: Partial<RichTextProps> = {
    imageEditable: true,
    receiver: '/api/upload/image',
    videoReceiver: '/api/upload/video',
    fileField: 'file',
    placeholder: '请输入',
    options: {
      toolbarButtons: [
        'undo',
        'redo',
        'paragraphFormat',
        'textColor',
        'backgroundColor',
        'bold',
        'underline',
        'strikeThrough',
        'formatOL',
        'formatUL',
        'align',
        'quote',
        'insertLink',
        'insertImage',
        'insertEmotion',
        'insertTable',
        'html'
      ]
    }
  };

  state: RichTextstate = {
    focused: false,
    popoverVisibleDefault: false,
    inputValue: null,
    openRich: false,
  };
  popover: any
  config: any = null;
  constructor(props: RichTextProps) {
    super(props);

    const finnalVendor =
      props.vendor || (props.env.richTextToken ? 'froala' : 'tinymce');
    this.handleFocus = this.handleFocus.bind(this);
    this.handleBlur = this.handleBlur.bind(this);
    this.handleChange = this.handleChange.bind(this);

    if (finnalVendor === 'froala') {
      this.config = {
        imageAllowedTypes: ['jpeg', 'jpg', 'png', 'gif'],
        imageDefaultAlign: 'left',
        imageEditButtons: props.imageEditable
          ? [
            'imageReplace',
            'imageAlign',
            'imageRemove',
            '|',
            'imageLink',
            'linkOpen',
            'linkEdit',
            'linkRemove',
            '-',
            'imageDisplay',
            'imageStyle',
            'imageAlt',
            'imageSize'
          ]
          : [],
        key: props.env.richTextToken,
        attribution: false,
        ...props.options,
        editorClass: props.editorClass,
        placeholderText: props.translate(props.placeholder),
        imageUploadURL: tokenize(props.receiver, props.data),
        imageUploadParams: {
          from: 'rich-text'
        },
        videoUploadURL: tokenize(props.videoReceiver, props.data),
        videoUploadParams: {
          from: 'rich-text'
        },
        events: {
          ...(props.options && props.options.events),
          focus: this.handleFocus,
          blur: this.handleBlur
        },
        language:
          !this.props.locale || this.props.locale === 'zh-CN' ? 'zh_cn' : ''
      };

      if (props.buttons) {
        this.config.toolbarButtons = props.buttons;
      }
    } else {
      const fetcher = props.env.fetcher;
      this.config = {
        ...props.options,
        images_upload_handler: async (
          blobInfo: any,
          ok: (locaiton: string) => void,
          fail: (reason: string) => void
        ) => {
          const formData = new FormData();
          formData.append(
            props.fileField,
            blobInfo.blob(),
            blobInfo.filename()
          );
          try {
            const receiver = {
              adaptor: (payload: object) => {
                return {
                  ...payload,
                  data: payload
                };
              },
              ...normalizeApi(props.receiver, 'post')
            };
            const response = await fetcher(receiver, formData, {
              method: 'post'
            });
            if (response.ok) {
              const location =
                response.data?.link ||
                response.data?.url ||
                response.data?.value ||
                response.data?.data?.link ||
                response.data?.data?.url ||
                response.data?.data?.value;
              if (location) {
                ok(location);
              } else {
                console.warn('must have return value');
              }
            }
          } catch (e) {
            fail(e);
          }
        }
      };
    }
  }

  handleFocus() {
    this.setState({
      focused: true
    });
  }

  handleBlur() {
    this.setState({
      focused: false
    });
  }

  handleChange(
    value: any,
    submitOnChange?: boolean,
    changeImmediately?: boolean
  ) {
    const { onChange, disabled } = this.props;

    if (disabled) {
      return;
    }

    onChange?.(value, submitOnChange, changeImmediately);
  }

  removeHtmlTags = (html: any) => {
    if (!html) return ""
    var tempDiv = document.createElement("div");
    tempDiv.innerHTML = html;
    return tempDiv.textContent || tempDiv.innerText || "";
  }

  popoverRef = async (dom: any) => {
    const { classPrefix: ns, name } = this.props
    this.popover = dom
    if (this.popover) {
      if (localStorage.getItem('textControlHtml') && typeof localStorage.getItem('textControlHtml') == 'string') {
        let textControlHtml = JSON.parse(localStorage.getItem('textControlHtml')!)
        if (Array.isArray(textControlHtml) && textControlHtml.some((item: any) => item.name == name)) {
          const style = textControlHtml.find((item: any) => item.name == name).style
          const popoverContent = this.popover.parentElement;
          popoverContent.style.width = style.width + 'px';
        }
      }
      const tplPopTop = this.popover.querySelector(`.${ns}Footer-tplPop-top`) as HTMLElement;
      const tplPopRight = this.popover.querySelector(`.${ns}Footer-tplPop-right`) as HTMLElement;
      const tplPopLeft = this.popover.querySelector(`.${ns}Footer-tplPop-left`) as HTMLElement;
      const tplPopBottom = this.popover.querySelector(`.${ns}Footer-tplPop-bottom`) as HTMLElement;

      tplPopTop.addEventListener('mousedown', this.onMousedown);
      tplPopRight.addEventListener('mousedown', this.onMousedown);
      tplPopLeft.addEventListener('mousedown', this.onMousedown);
      tplPopBottom.addEventListener('mousedown', this.onMousedown);
    }
  }
  onMousedown = (e: any) => {
    e.stopPropagation();
    e.preventDefault();
    const { name } = this.props
    if (!this.popover || !document.defaultView) return
    const popoverContent = this.popover.parentElement
    const htmlContainer = this.popover.querySelector(`.w-e-text-container`) as HTMLElement;
    const upErDown = e.target.className.includes('top') || e.target.className.includes('bottom')
    const about = e.target.className.includes('left') || e.target.className.includes('right')
    let textControlHtml: any[] = []
    if (localStorage.getItem('textControlHtml')) {
      textControlHtml = JSON.parse(localStorage.getItem('textControlHtml')!)
      if (!Array.isArray(textControlHtml)) {
        textControlHtml = []
      }
    }
    if (e.target.tagName.toLowerCase() === 'div') {
      // 记录初始鼠标位置和弹窗初始宽高
      let startX = e.clientX;
      let startY = e.clientY;

      let startWidth = parseInt(document?.defaultView.getComputedStyle(popoverContent).width, 10);
      let startHeight = parseInt(document?.defaultView.getComputedStyle(htmlContainer).height, 10);
      // 设置鼠标移动事件
      document.addEventListener('mousemove', resizeElement);
      // 设置鼠标松开事件
      document.addEventListener('mouseup', function () {
        document.removeEventListener('mousemove', resizeElement);
      });

      // 调整元素大小函数
      function resizeElement(e: any) {
        let newWidth = startWidth + e.clientX - startX;
        let newHeight = startHeight + e.clientY - startY;
        if (newWidth < 250) return
        if (newHeight < 80) return
        if (upErDown) {
          htmlContainer.style.height = newHeight + 'px';
        }
        if (about) {
          popoverContent.style.width = newWidth + 'px';
        }

        if (textControlHtml.some(item => item.name == name)) {
          const content = {
            name: name,
            style: {
              width: newWidth,
              height: newHeight,
            }
          }
          textControlHtml = [...textControlHtml.filter(item => item.name !== name), content]
        } else {
          const content = {
            name: name,
            style: {
              width: newWidth,
              height: newHeight,
            }
          }
          textControlHtml = [...textControlHtml, content]
        }

        localStorage.setItem('textControlHtml', JSON.stringify(textControlHtml))
      }
    }
  }
  render() {
    const {
      className,
      classPrefix: ns,
      value,
      disabled,
      vendor,
      env,
      locale,
      translate,
      borderMode,
      popOverContainer,
      placeholder,
      defaultOpen,
      name,
      domicile,
      rich
    } = this.props;
    const { popoverVisibleDefault, inputValue, openRich } = this.state
    const primaryField = (this.props.store as any)?.primaryField
    const primaryVlaue = domicile ? domicile?.data?.[primaryField] ?? '' : ''
    const primarylable = domicile ? domicile.label : ''
    const finnalVendor = vendor || (env.richTextToken ? 'froala' : 'wangEditor'); // Jay 默认使用 wangEditor
    const placement = !isMobile() ? 'rightTop' : 'bottomRight';

    const popDefaultOpen = (
      <Popover
        visible={popoverVisibleDefault}
        trigger={'click'}
        overlayClassName={cx(`${ns}TplPop`, `${ns}PopRichText`)}
        getPopupContainer={popOverContainer}
        onVisibleChange={(visible) => { this.setState({ popoverVisibleDefault: visible }) }}
        autoAdjustOverflow
        arrowPointAtCenter
        destroyTooltipOnHide
        placement={placement}
        content={(
          <div className={cx(`${ns}popoverRichText`)} ref={this.popoverRef}>
            <LazyComponent
              getComponent={loadRichText(finnalVendor)}
              model={value}
              onModelChange={(value: string) => this.setState({ inputValue: value })}
              onFocus={this.handleFocus}
              onBlur={this.handleBlur}
              config={this.config}
              disabled={disabled}
              name={name}
              locale={locale}
              translate={translate}
            />
            <div className={cx(`${ns}Footer-tplPop`)}>
              {/* 关闭 */}
              <Button size="small" style={{ marginRight: 10, borderRadius: 5 }} onClick={() => { this.setState({ popoverVisibleDefault: false }) }} >
                {this.props.translate('Dialog.close')}
              </Button>
              {/* 确认 */}
              <Button size="small" style={{ borderRadius: 5 }} type="primary" onClick={() => {
                this.handleChange(inputValue)
                this.setState({ popoverVisibleDefault: false })
              }} >
                {this.props.translate('confirm')}
              </Button>
            </div>
            <div className={cx(`${ns}Footer-tplPop-top`)}></div>
            <div className={cx(`${ns}Footer-tplPop-bottom`)}></div>
            <div className={cx(`${ns}Footer-tplPop-left`)}></div>
            <div className={cx(`${ns}Footer-tplPop-right`)}></div>
          </div>
        )}
        title={(
          <div className={cx(`${ns}Title-tplPop`)} >
            <div>{primarylable + ": " + (isNil(primaryVlaue) ? '' : primaryVlaue)}</div>
          </div>
        )}>
        <EditOutlined style={{ fontSize: '0.875rem', minWidth: "12px", color: '#999' }} />
      </Popover>
    )

    return (
      <div
        className={cx(`${ns}RichTextControl`, className, {
          'is-focused': !rich && this.state.focused,
          'is-disabled': disabled,
          [`${ns}RichTextControl--border${ucFirst(borderMode)}`]: borderMode,
          'is-defaultOpen': defaultOpen
        })}
        onKeyDown={(e: any) => e.stopPropagation()}
      >
        {
          isMobile() ? <>
            <div className={cx(`${ns}RichTextControl-Rich`)} onClick={() => { this.setState({ openRich: true }) }}>
              <div className={cx(`${ns}RichTextControl-RichValue`)} >
                {!!!value ? <div className={cx(`${ns}RichTextControl-placeholder`)} >
                  {placeholder ?? '请输入'}
                </div> :
                  this.removeHtmlTags(value)}
              </div>
              {
                <a className={cx(`${ns}Table-expandBtn`)} >
                  <Icon icon="right-arrow-bold" className="icon" />
                </a>
              }
            </div>
            <Drawer
              visible={openRich}
              width="100%"
              className={`textarea-drawer textarea-drawer-rich ${tools.isIOS ? 'textarea-drawer-rich-ios' : ''}`}
              closeIcon={<Icon icon='title-left' className="icon" style={{ width: '16px', height: '16px' }} />}
              onClose={() => { this.setState({ openRich: false }) }}
              destroyOnClose
              mask={false}
              getContainer={this.props.env.getModalContainer}
              zIndex={1011}
              title={(!disabled ? '修改' : "") + this.props.label}
              extra={<Button danger size='small' type="text" />}
              footer={<div className='textarea-drawer-footer'>
                <Button type="primary" onClick={() => this.setState({ openRich: false })}>
                  完成
                </Button>
              </div>}
            >
              {/* https://www.tiny.cloud/ */}
              <LazyComponent
                getComponent={loadRichText('tinymce')}
                model={value}
                onModelChange={this.handleChange}
                onFocus={this.handleFocus}
                onBlur={this.handleBlur}
                config={this.config}
                disabled={disabled}
                locale={locale}
                name={name}
                translate={translate}
              />
            </Drawer>
          </> :
            <>
              {
                !defaultOpen ? <LazyComponent
                  getComponent={loadRichText(finnalVendor)}
                  model={value}
                  onModelChange={this.handleChange}
                  onFocus={this.handleFocus}
                  onBlur={this.handleBlur}
                  config={this.config}
                  name={name}
                  disabled={disabled}
                  locale={locale}
                  translate={translate}
                />
                  :
                  <div className={cx(`${ns}RichTextControl-value`)}>
                    <div className={cx(`${ns}RichTextControl-content`)}>
                      {this.removeHtmlTags(value)}
                    </div>
                    {
                      popDefaultOpen
                    }
                  </div>
              }
            </>}

      </div>
    );
  }
}

@FormItem({
  type: 'input-rich-text',
  sizeMutable: false
})
export class RichTextControlRenderer extends RichTextControl { }
