import React, { useEffect, useState } from 'react';
import BraftEditor from 'braft-editor';
import { useSetState } from 'react-use';
import { func, object, string, bool, oneOf, number, array } from 'prop-types';
import { ContentUtils } from 'braft-utils';
import classNames from '../../utils/classnames';
import FormCell from '../form/formcell';
import { getCloudInstance, getTempFileURL } from '../../utils/tcb';
import {
  message,
  Button,
  Input,
  Modal,
  Progress,
  Upload,
  Text,
} from 'tea-component';
import { v4 as uuidv4 } from 'uuid';
import {defaultBase64} from './const';

import './index.css';
import 'braft-editor/dist/index.css';

// 默认图片类型
const IMAGE_TYPES = [
  'image/jpeg',
  'image/png',
  'image/gif',
  'image/bmp',
  'image/tiff',
  'image/svg+xml',
];


export default function RichText({
  // 系统属性
  id,
  style,
  className,
  events,
  // 组件属性
  label,
  labelVisible,
  value: initialValue,
  readOnly,
  layout,
  requiredFlag,
  onChange,
  maxSize,
  acceptTypes,
  cloudPath,
  disabled
}) {
  const [editorState, setEditorState] = useState();

  const cls = classNames({
    'weda-ui': true,
    'weda-richText': true,
    [className]: className,
  });
  const subCls = classNames({
    'weui-cell': true,
    'weui-cell_active': true,
    'weui-cell_form': true,
    'weui-cell_disabled': disabled,
  });

  const onDataChange = function (value) {
    events.change && events.change({ value: value === '<p></p>' ? '' : value });
    if (onChange) {
      if (value === '<p></p>') {
        onChange('');
      } else {
        onChange(value);
      }
    }
  };

  useEffect(() => {
    const state = BraftEditor.createEditorState(initialValue);
    setEditorState(state);
  }, []);

  const extendControls = [
    {
      key: 'richtext-uploader',
      type: 'component',
      component: (
        <CustomUploader
          acceptTypes={acceptTypes}
          maxSize={maxSize}
          cloudPath={cloudPath}
          onChange={(url) => {
            const state = ContentUtils.insertMedias(editorState, [
              { type: 'IMAGE', url },
            ]);
            setEditorState(state);
          }}
        />
      ),
    },
  ];

  // 修改img显示逻辑
  const blockRenderFn = (contentBlock, { editor, editorState }) => {
    if (contentBlock.getType() === 'atomic') {
      const entity = editorState
        .getCurrentContent()
        .getEntity(contentBlock.getEntityAt(0));
      if (entity.getType() === 'IMAGE') {
        return {
          component: RichTextImg, // 替换img的组件
          editable: false, // editable并不代表组件内容实际可编辑，建议设置为false
          props: { editor, editorState }, // 传入的内容可以在组件中通过this.props.blockProps获取到
        };
      }
    }
  };

  return (
    <FormCell
      className={cls}
      label={labelVisible ? label : null}
      layout={layout}
      multiCell={false}
      requiredFlag={requiredFlag}
    >
      
      <div className={subCls}>
        <div
          style={{
            border: '1px solid #d1d1d1',
            backgroundColor: '#fff',
            ...style,
          }}
        >
          <BraftEditor
            key={id}
            value={editorState}
            readOnly={readOnly}
            blockRendererFn={blockRenderFn}
            onBlur={(s) => {
              setEditorState(s);
              onDataChange(s.toHTML());
              if (s.toHTML().length > 32768) {
                message.warning({
                  content: '富文本长度过长，可能导致保存失败',
                });
              }
            }}
            excludeControls={['media', 'fullscreen']}
            extendControls={extendControls}
            handleKeyCommand={(command, editState) => {
              const newState = ContentUtils.handleKeyCommand(
                editState,
                command
              );
              if (newState) {
                setEditorState(newState);
                return true;
              }
              return false;
            }}
          />
        </div>
      </div>
    </FormCell>
  );
}

export const CustomUploader = (props) => {
  const { onChange = () => {}, acceptTypes, maxSize, cloudPath } = props;
  const [
    { fileList, percent, visible, uploading, inputUrl, previewImg },
    setState,
  ] = useSetState({
    fileList: [],
    percent: 0,
    visible: false,
    uploading: false,
    inputUrl: '',
    previewImg: defaultBase64,
  });

  // 获取base64
  const getBase64 = (file) => {
    const reader = new FileReader();
    reader.onloadend = () => {
      setState({ previewImg: reader.result });
    };
    reader.readAsDataURL(file);
  };

  // 计算上传进度
  const onProgress = (progressEvent) => {
    let percentCompleted = 0;
    try {
      percentCompleted = Math.round(
        (progressEvent.loaded * 100) / progressEvent.total
      );
      percentCompleted < 100 ? percentCompleted : 100;
    } catch (e) {
      message.error({
        content: '上传图片失败',
      });
    }
    setState({ uploading: true, percent: percentCompleted });
  };
  return (
    <>
      <button
        role="richtext"
        type="button"
        data-title="媒体上传"
        className="control-item button"
        onClick={() => setState({ visible: true })}
      >
        <svg
          viewBox="64 64 896 896"
          focusable="false"
          data-icon="file-image"
          width="1em"
          height="1em"
          fill="currentColor"
          aria-hidden="true"
        >
          <path
            d="M534 352V136H232v752h560V394H576a42 42 0 01-42-42zm-134 50c22.1 0 40 17.9 40 40s-17.9 40-40 40-40-17.9-40-40 17.9-40 40-40zm296 294H328.1c-6.7 0-10.4-7.7-6.3-12.9l99.8-127.2a8 8 0 0112.6 0l41.1 52.4 77.8-99.2a8.1 8.1 0 0112.7 0l136.5 174c4.1 5.2.4 12.9-6.3 12.9z"
            fill="#e6f7ff"
          ></path>
          <path
            d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM602 137.8L790.2 326H602V137.8zM792 888H232V136h302v216a42 42 0 0042 42h216v494z"
            fill="#006eff"
          ></path>
          <path
            d="M553.1 509.1l-77.8 99.2-41.1-52.4a8 8 0 00-12.6 0l-99.8 127.2a7.98 7.98 0 006.3 12.9H696c6.7 0 10.4-7.7 6.3-12.9l-136.5-174a8.1 8.1 0 00-12.7 0zM360 442a40 40 0 1080 0 40 40 0 10-80 0z"
            fill="#006eff"
          ></path>
        </svg>
      </button>
      <Modal
        onClose={() => {
          setState({ visible: false });
        }}
        visible={visible}
        maskClosable={true}
      >
        <p>输入链接插入图片</p>
        <div className="richText-upload-link">
          <Input
            value={inputUrl}
            placeholder="输入图片地址"
            onChange={(value) => setState({ inputUrl: value })}
          />
          &nbsp;
          <Button
            type="primary"
            onClick={() => {
              onChange(inputUrl);
              setState({ visible: false });
            }}
          >
            确认
          </Button>
        </div>
        <p style={{ marginBottom: '16px' }}>或拖拽上传插入图片</p>
        <Upload
          accept={acceptTypes.join()}
          maxSize={1024 * 1024}
          beforeUpload={(file) => {
            getBase64(file);
            let typeRegex = new RegExp(
              `^((${acceptTypes.join(')|(').replace('+', '\\+')}))$`
            );
            if (acceptTypes.join().includes('*')) {
              typeRegex = new RegExp(`^image/.+$`);
            }
            if (!typeRegex.test(file.type)) {
              message.error({
                content: '文件格式不支持',
              });
              return false;
            }
            if (file.size > maxSize * 1024 * 1024) {
              message.error({
                content: `文件大小超过上限${maxSize}M`,
              });
              return false;
            }
            setState({
              uploading: true,
              percent: 0,
              fileList: [
                {
                  name: file.name,
                },
              ],
            });
            getCloudInstance().then(async (tcb) => {
              try {
                const fileType = file.name.split('.').pop().toLowerCase();
                const path = `${cloudPath}/uploader-${uuidv4()}.${fileType}`;
                const { fileID } = await tcb.uploadFile({
                  cloudPath: path,
                  filePath: file,
                  onUploadProgress: onProgress,
                });
                onChange(fileID);
                setState({
                  visible: false,
                  fileList: [],
                });
              } catch (e) {
                setState({
                  fileList: [],
                });
                message.error({
                  content: '上传图片失败',
                });
              } finally {
                setState({ uploading: false, percent: 100 });
              }
            });
            return false;
          }}
        >
          {({ open, isDragging }) => (
            <Upload.Dragger
              filename={fileList[0] && fileList[0].name}
              percent={percent}
              image={previewImg}
              className="richtext_upload_dragger"
            >
              {isDragging ? (
                '释放鼠标'
              ) : (
                <>
                  <a onClick={open}>点击上传</a>
                  <Text theme="weak">/拖拽到此区域</Text>
                </>
              )}
            </Upload.Dragger>
          )}
        </Upload>
        {uploading && (
          <Progress style={{ marginTop: '10px' }} percent={percent} />
        )}
      </Modal>
    </>
  );
};

export const RichTextImg = ({ contentState, block }) => {
  const blockData = contentState.getEntity(block.getEntityAt(0)).getData();
  const { url } = blockData || {};
  const [src, setSrc] = React.useState('');
  const [width, setWidth] = React.useState('unset');

  useEffect(() => {
    const getSrc = async () => {
      try {
        if (url.includes('cloud://')) {
          let _src = await getTempFileURL(url);
          setSrc(_src || url);
        } else {
          setSrc(url);
        }
      } catch (e) {
        message.error({
          content: `显示图片失败：${e.message || '未知原因'}`,
        });
      }
    };
    getSrc();
  }, [url]);

  return (
    src && (
      <>
        <div className="bf-media">
          <div draggable="true" className="bf-image" style={{ float: 'left' }}>
            <div style={{ position: 'relative', display: 'inline-block' }}>
              <img
                src={src}
                key={url + Math.random()}
                style={{ maxWidth: '100%', width }}
                onError={() => {
                  setSrc(defaultBase64);
                  setWidth('80px');
                }}
              />
              <div className="bf-pre-csize"></div>
            </div>
          </div>
          <div
            style={{
              clear: 'both',
              height: '0px',
              lineHeight: 0,
              float: 'none',
            }}
          ></div>
        </div>
      </>
    )
  );
};

RichText.propTypes = {
  // 系统属性
  id: string,
  style: object,
  value: string,
  className: string,
  events: object,
  // 组件属性
  label: string,
  labelVisible: bool,
  name: string,
  readOnly: bool,
  layout: oneOf(['horizontal', 'vertical']),
  requiredFlag: bool,
  onChange: func,
  maxSize: number,
  acceptTypes: array,
  cloudPath: string,
  disabled: bool
};

RichText.defaultProps = {
  // 系统属性
  events: {},
  style: { width: '100%' },
  // 组件属性
  label: '标题',
  labelVisible: true,
  name: 'formRichText',
  value: '',
  readOnly: false,
  layout: 'vertical',
  requiredFlag: false,
  maxSize: 10,
  acceptTypes: IMAGE_TYPES,
  cloudPath: 'weda-richtext-upload',
};

CustomUploader.propTypes = {
  onChange: func,
  maxSize: number,
  acceptTypes: array,
  cloudPath: string,
};

CustomUploader.defaultProps = {
  maxSize: 10,
  acceptTypes: IMAGE_TYPES,
  cloudPath: 'weda-richtext-upload',
};

RichTextImg.propTypes = {
  contentState: object,
  block: object,
};

RichTextImg.defaultProps = {};
