import { message } from 'antd';
import React, { useEffect, useState } from 'react';
import { Renderer, RendererProps } from '../factory';
import { BaseSchema } from '../Schema';
import { ImgInfo, Shell } from '../utils/shell';
import Drawer from 'antd/lib/drawer';
import Button from 'antd/lib/Button';
import LionUpload from './Lion/components/Upload';
import CloseCircleOutlined from '@ant-design/icons/lib/icons/CloseCircleOutlined';
import Modal from 'antd/lib/modal/Modal';
export interface OfflineImageSchema extends BaseSchema {
  // 定义类型
  type: 'offline-image';
  multiple?: boolean;//多图
  maxLength?: number;//图片最大数量
  readonly?: boolean;
  label?: string;
}
interface InfoItem {
  addr: string,
  chunkDownload?: false,
  name: string,
  preview?: string,
  preview_name?: string,
  size?: number,
  thumbnailAddr?: string,
  fileName?: string
}
interface FLFileInfo {
  name: string,
  addr: string,
  size?: number,
  fileName?: string
}
// 附件数据对象
interface FLFileData {
  value: string | null;
  info: Array<FLFileInfo>;
}
export interface CustomFile {
  uid: string; // 唯一值
  size?: number; // 文件大小
  name: string; // 文件名称
  url: string; // 文件地址
  status: "done" | "uploading" | "error" | "success"; // 上传状态
  file?: File; // 文件对象
  percent?: number; // 上传进度
  unique?: string; // unique值
  error?: any; // 出错
  assign?: obj
}
// 大部分组件都是直接继承 RendererProps，里面包含渲染组件所需的常用属性
export interface OfflinePageProps
  extends RendererProps,
  Omit<OfflineImageSchema, 'type' | 'className'> {
  offlineData: FLFileData,
  offline: {
    tableName: string;
    primaryKey: string;//主键名称 
    primaryValue: string;// 主键值
    fieldName: string
  },
  offlineChange: (list: string[], fieldName: string) => void,
  offlineDelete: (fieldName: string, fileIndex: number) => void;
  formItem?: boolean
};
export const getMediaUrl = (originUrl: string, thumbnail: boolean = false): string => {
  // media的url存在多种类型
  // blob,localfile,base64可以直接显示,并且没有缩略图
  // 后台资源地址需要拼接CONF.baseUrl,并且支持缩略图
  if (
    /^data:/.test(originUrl) || // base64
    /^blob:/.test(originUrl) || // blob
    /^localfile:/.test(originUrl) // 终端localfile
  ) return originUrl
  return createImageUrl(originUrl, thumbnail)
}
const createImageUrl = (imgUrl: string, thumbnail: boolean = false, isoffline: boolean = true): string => {
  if (isoffline && Shell.hasShell() && imgUrl) {
    //离线终端的临时目录  已经有了就localfile 就不需要拼接  否则要把线上的http换成localfile
    let url = '';
    if (imgUrl.indexOf("localfile:///") > -1) {
      return imgUrl
    } else {
      url = `localfile:///`
      return `${url}${imgUrl}`
    }
  }
  if (/^data:image/.test(imgUrl)) {
    return imgUrl;
  }
  return imgUrl;
}
const OfflineImage = (props: OfflinePageProps) => {
  const { offlineData, classnames: cx, multiple, maxLength = 0, formItem, label, readonly, offline,
    offlineChange, offlineDelete, limit, maxSize = 1024 } = props;
  const [imageValue, setImageValue] = useState<FLFileData>(offlineData);
  const [previewOpen, setPreviewOpen] = useState(false);
  const [previewImage, setPreviewImage] = useState('');
  const [previewTitle, setPreviewTitle] = useState('');
  useEffect(() => {
    setImageValue(offlineData)
  }, [offlineData])
  const [visible, setVisible] = useState(false);
  const ImageItem = (index: number, value?: InfoItem) => {
    if (value) {
      const url = getMediaUrl(value.name)
      return <div className={cx('Offline-image-item')}>
        <div className='img-left' style={{ width: 28, height: 28, overflow: 'hidden' }}>
          <img style={{ width: '100%' }} onClick={(e) => {
            e.stopPropagation();
            handlePreview(url, value.name || value.fileName || '');
          }} src={url} />
        </div>
        {formItem && <div className='img-right'>
          <div className='img-name'>{value.name || value.fileName}</div>
          {value.size ? <div className='img-size'>{LionUpload.formatFileSize(value.size)}</div> : null}
        </div>}
        {formItem && !readonly ? <div className='img-del'>
          <CloseCircleOutlined onClick={() => handleDelete(index)} />
        </div> : null}
      </div>
    }
    return null
  }
  //壳选择图片
  const chooseImage = () => {
    let hasShell = Shell.hasShell();
    if (hasShell && offline.primaryValue) {
      setVisible(true)
    } else {
      message.error("请先扫码再选择图片！")
    }
  }
  //0相册 1 拍照
  const getImages = (type: number) => {
    let currentNum = 0;
    if (imageValue) {
      if ("info" in imageValue) {
        currentNum = imageValue.info?.length || 0
      }
    }
    const count = maxLength - currentNum;
    // maxLength大于0证明有配置,此时才需要验证
    if (count <= 0 && maxLength) {
      message.warning({ content: `上传个数已达上限${maxLength}个` })
      return
    }
    let config = {
      maxHeight: limit?.maxHeight || 0, maxWidth: limit?.maxWidth || 0, maxSize: 1024,
      multi: multiple, type, rect: null, count, offline
    };
    let list: any[] = [];
    let fail = (res: ShellFailResult) => {
      message.error(res.msg)
    }
    let info = (res: ShellDoneResult<ImgInfo>) => {
      if (res?.code === -200) {
        message.warning(res?.msg || '拍照失败')
      } else {
        list.push(res.data.dataurl);
      }
    }
    let success = (res: ShellDoneResult<ImgInfo>) => {
      list.push(res.data.dataurl);
      onUpload(list)
    }
    Shell.getAttachment(config, info, success, fail)
  }
  //处理回调文件
  const onUpload = (md5s: string[]) => {
    let valueList: string[] = []
    const info = md5s.map(item => {
      const name = item.replace('localfile:///', '');
      valueList.push(name)
      return {
        addr: item,
        name,
        fileName: name,
        path: item
      }
    })
    if (imageValue.value) {
      const newValue = [imageValue.value, ...valueList].join(',')
      const newInfo = [...imageValue.info, ...info]
      setImageValue({
        value: newValue,
        info: newInfo
      })
    } else {
      setImageValue({
        value: valueList.join(','),
        info
      })
    }
    offlineChange(md5s, offline.fieldName)
    setVisible(false)
  }
  //离线删除本地图片
  const handleDelete = async (fileIndex: number) => {
    const { tableName, primaryKey, primaryValue, fieldName } = offline
    await Shell.deleteFile(tableName, primaryKey, primaryValue, fieldName, 'localfile:///' + imageValue.info[fileIndex].name)
    let valueList = imageValue.value!.split(',')
    let info = [...imageValue.info]
    valueList.splice(fileIndex, 1)
    info.splice(fileIndex, 1)
    setImageValue({
      value: valueList.join(','),
      info
    })
    offlineDelete(fieldName, fileIndex)
  }
  const renderBody = () => {
    const images = multiple ?
      imageValue?.value ?
        imageValue.value.split(',').map((imageName, index) => ImageItem(index, imageValue?.info?.[index])) : null
      : ImageItem(0, imageValue?.info?.[0])

    return formItem ? <div className={cx('Offline-form-item')}>
      <label>
        {label}
        {readonly || (imageValue?.info?.length === maxLength && maxLength) || (!multiple && imageValue?.info?.length === 1) ? null : <span className="fa fa-plus-circle" onClick={chooseImage}></span>}
      </label>
      <div className='offline-form-item-wrapper'>
        {images}
      </div>
    </div> : <div className='offline-image-wrapper'>
      {images}
    </div>
  }

  const handleCancel = () => setPreviewOpen(false);

  const handlePreview = async (url: string, fileName: string) => {
    setPreviewImage(url)
    setPreviewTitle(fileName)
    setPreviewOpen(true);
  };

  return (
    <>
      <div className={cx('Offline-image')}>
        {renderBody()}
      </div >
      <Drawer
        title={null}
        placement='bottom'
        closable={false}
        visible={visible}
        onClose={() => setVisible(false)}
        maskClosable
        getContainer={props.env.getModalContainer}
        // zIndex={1000}
        height={110}
        className='offline-picture-drawer'
      >
        <div className='offline-picture-item'>
          <Button onClick={() => getImages(0)} block type='primary' size='large'>相册</Button>
        </div>
        <div className='offline-picture-item'>
          <Button onClick={() => getImages(1)} block size='large'>拍摄</Button>
        </div>
      </Drawer>
      <Modal getContainer={document.body} visible={previewOpen} title={<span style={{
        paddingRight: '22px', width: '100%', display: 'inline-block', whiteSpace: 'nowrap',
        textOverflow: 'ellipsis', overflow: 'hidden'
      }}>{previewTitle}</span>} footer={null} onCancel={(e) => {
        e.stopPropagation()
        handleCancel()
      }}>
        <img alt="example" style={{ width: '100%' }} src={previewImage} />
      </Modal>
    </>
  )
}
// 将组件注册到 amis 渲染器中
export default Renderer({
  type: 'offline-image'
})(OfflineImage);