import React from "react";
import Form from 'antd/lib/form';
import InputNumber from 'antd/lib/input-number';
import Select from 'antd/lib/select';
import Row from 'antd/lib/Row';
import Col from 'antd/lib/Col';
import Radio from 'antd/lib/Radio';
import { FormInstance } from "antd/es/form";
import { RendererEnv } from "../../../../env";
import { CloseIcon } from "../../../../components/icons";
import Button from '../../../../components/Button'
import { Spinner } from '../../../../components';
import message from 'antd/lib/message';
import AntdModal from 'antd/lib/Modal';
import { filePrint } from "../../../../utils/print";
import { pageOptions, sizeOptions } from "../types";
import moment from "moment";
import { fromUint8Array } from "js-base64";
import Empty from "antd/lib/empty";

const { Option } = Select;

interface FilePrintProps {
  classnames: (...args: any[]) => string;
  onHide: (e?: any) => void; // modal关闭回调
  env: RendererEnv
  printers: string[]
  baseUrl: string
  isSingleFilePrint?: boolean
  modalContainer?: () => HTMLElement
  popupContainer?: () => HTMLElement
  ctx: {
    items: Array<any>; // 选中的行数据
    selectedItems: Array<any>; // 选中的行数据
    ids: string; // 多个 id 值用英文逗号隔开的字符串，前提是行数据中有 id 字段，或者有指定的 primaryField 字段
    primaryField?: string; // CRUD 设置 ID 字段名
    [key: string]: any; // 第一行的所有行数据也会包含进去
  };
  [key: string]: any;
}

type FileData = { type: 'pdf' | 'img', content: string }

interface FilePrintState {
  previewLoading: boolean
  showEmpty: boolean
  fileDatas: FileData[]
}

interface FilePrintFormValues {
  printer: string
  direction: number
  count: number
  pageSize: string
  pageWidth: number
  pageHeight: number,
  marginTop: number,
  marginLeft: number,
  marginRight: number,
  marginBottom: number
}

export default class FilePrint extends React.Component<FilePrintProps, FilePrintState> {

  formRef = React.createRef<FormInstance<FilePrintFormValues>>()

  constructor(props: FilePrintProps) {
    super(props)
    this.state = {
      previewLoading: false,
      showEmpty: true,
      fileDatas: []
    }
  }

  async componentDidMount() {
    const { ctx, baseUrl, env } = this.props
    const selectedItems = ctx?.selectedItems
    // 仅支持jpg,jpeg,png,pdf
    const pdfRegExp = /(.pdf)$/i;
    const imgRegExp = /\.(jpe?g|png)$/i;
    const fileDatas: FileData[] = []
    // 文件控件的打印
    for (let i = 0; i < selectedItems.length; i++) {
      const item = selectedItems[i];
      pdfRegExp.test(item.name)
        ? fileDatas.push({
          type: 'pdf',
          content: await this.downloadPDF(baseUrl + item.addr, env.token?.())
        })
        : imgRegExp.test(item.name) && fileDatas.push({
          type: 'img',
          content: baseUrl + item.addr
        })
    }
    this.setState({ fileDatas }, () => {
      this.handleFilePreview()
    })
  }

  async handleFilePreview() {
    this.setState({ previewLoading: true, showEmpty: false })
    const values = await this.formRef.current!.validateFields()
    let { fileDatas } = this.state
    // env.fetcher , api 获取预览数据，然后保存到state，供打印函数调用
    const { translate: __ } = this.props
    if (fileDatas.length === 0) {
      message.info(`${__('CRUD.countIs0')},${__('CRUD.reSelect')}`);
      return
    }
    // 如果预览数据条数>=xxx时提示
    let confirm = true
    if (fileDatas.length >= 20) {
      confirm = await this.showModalTip(fileDatas.length)
      fileDatas = fileDatas.slice(0, 20)
    }
    if (confirm) {
      // 调用预览函数
      this.setState({ previewLoading: true })
      const params = {
        ...values,
        direction: values.direction === 0,
        preview: true
      }

      filePrint({
        ...params,
        fileDatas
      }, () => {
        this.setState({ previewLoading: false })
      })
    }
  }

  // 文件仅打印
  async handleFilePrint() {
    const values = await this.formRef.current!.validateFields()
    const { translate: __ } = this.props
    const { fileDatas } = this.state
    if (fileDatas.length === 0) {
      message.info(`${__('CRUD.countIs0')},${__('CRUD.reSelect')}`);
      return
    }
    const params = {
      ...values,
      direction: values.direction === 0,
      preview: false,
    }
    filePrint({
      ...params,
      fileDatas
    }, () => {
      this.savePrintInfo()
    })
  }

  savePrintInfo() {
    // 获取保存请求的地址
    const { env: { fetcher }, ctx, callbackApi } = this.props
    if (!callbackApi) return
    const PRINT_TIME = moment(new Date()).format('YYYY-MM-DD HH:mm:ss')
    callbackApi.data = {
      callbackList: {
        ...callbackApi.data,
        PRINT_TIME
      }
    }
    fetcher(callbackApi, { ids: ctx?.ids })
  }

  private showModalTip(countOfPage: number) {
    return new Promise<boolean>((resolve) => {
      AntdModal.confirm({
        content:
          <>
            <span>预览共需渲染 <strong>{countOfPage}</strong> 页。</span>
            <span>大于等于20页时，仅渲染前20页，请确认是否预览？</span>
          </>
        ,
        okText: '确认',
        cancelText: '取消',
        onOk: () => resolve(true),
        onCancel: () => resolve(false),
        zIndex: 2000
      })
    })
  }

  private async downloadPDF(url: string, token: string) {
    return new Promise<string>((resolve) => {
      try {
        // if (!/^https?:/i.test(url)) resolve('http');
        var xhr = new XMLHttpRequest();
        xhr.open('GET', url, false); // false同步方式，需要设置同步，因为按照表格顺序发送请求
        let arrybuffer = false
        if (xhr.overrideMimeType) {
          try {
            xhr.responseType = 'arraybuffer';
            arrybuffer = true;
          } catch (err) {
            xhr.overrideMimeType('text/plain; charset=x-user-defined');
          }
        }
        xhr.setRequestHeader('token', token)
        xhr.send(null);
        var data = xhr.response;
        let dataArray: Uint8Array
        if (arrybuffer) {
          dataArray = new Uint8Array(data);
        } else {
          dataArray = new Uint8Array(data.length);
          for (var i = 0; i < dataArray.length; i++) {
            dataArray[i] = data.charCodeAt(i);
          }
        }
        resolve(fromUint8Array(dataArray))
      } catch (error) {
        resolve(error)
      }
    })
  }

  render() {
    const { classnames: cx, translate: __, popupContainer, printers, onHide } = this.props
    const { previewLoading, showEmpty } = this.state
    return (
      <>
        <div className={cx('Modal-header')}>
          <div className={cx('Modal-title')}>
            {__('CRUD.filePrint')}
            <a
              data-tooltip={__('Dialog.close')}
              onClick={(e) => onHide(e)}
              className={cx('Modal-close')}
            >
              <CloseIcon />
            </a>
          </div>
        </div>
        <div className={cx('Modal-body')}>
          <div className='print-form-container'>
            <div className='preview-container'>
              <Spinner size="md" overlay show={previewLoading} />
              {showEmpty && <Empty description='暂无预览效果' className='preview-empty' />}
              <iframe id='file-preview' width='100%' height='100%'></iframe>
            </div>
            <Form style={{ width: 350 }} ref={this.formRef} colon={false} layout='vertical'>
              <div className="print-setting">
                <div className="print-setting-label">打印设备</div>
                <div className="print-setting-content">
                  <Row gutter={10}>
                    <Col span={12}>
                      <Form.Item name="printer" label={__('CRUD.printer')} initialValue={printers?.[0] || ''} rules={[{ required: true, message: `${__('CRUD.selectPrinter')}` }]}>
                        <Select showSearch
                          getPopupContainer={popupContainer}
                          dropdownClassName='label-print-selector' >
                          {printers?.map(item => <Option key={item} value={item}>{item}</Option>)}
                        </Select>
                      </Form.Item>
                    </Col>
                    <Col span={12}>
                      <Form.Item name="pageSize" label={__('CRUD.pageSize')} initialValue={pageOptions[0].value} rules={[{ required: true, message: `${__('CRUD.selectPage')}` }]}>
                        <Select showSearch
                          getPopupContainer={popupContainer}
                          dropdownClassName='label-print-selector'
                          onChange={(value: string) => {
                            const [pageWidth, pageHeight] = sizeOptions[value]
                            this.formRef.current?.setFieldsValue({
                              pageWidth: pageWidth,
                              pageHeight: pageHeight
                            })
                          }}
                        >
                          {pageOptions?.map(item => <Option key={item.value} value={item.value}>{item.label}</Option>)}
                        </Select>
                      </Form.Item>
                    </Col>
                  </Row>
                  <Row gutter={10}>
                    <Col span={12}>
                      <Form.Item name="pageWidth" label={__('width')} initialValue={sizeOptions[pageOptions[0].value][0]} rules={[{
                        validator: async (rule, value) => {
                          if (value < 0 || value > 1000) {
                            throw new Error(`${__('CRUD.fillIn')}1-1000`);
                          }
                        }
                      }]} >
                        <InputNumber className='w-full' min={0} max={1000} />
                      </Form.Item>
                    </Col>
                    <Col span={12}>
                      <Form.Item name="pageHeight" label={__('height')} initialValue={sizeOptions[pageOptions[0].value][1]} rules={[{
                        validator: async (rule, value) => {
                          if (value < 0 || value > 1000) {
                            throw new Error(`${__('CRUD.fillIn')}1-1000`);
                          }
                        }
                      }]}>
                        <InputNumber className='w-full' min={0} max={1000} />
                      </Form.Item>
                    </Col>
                  </Row>
                </div>
                <div className="print-setting-label">纸张设置</div>
                <div className="print-setting-content">
                  <Row gutter={10}>
                    <Col span={12}>
                      <Form.Item label={__('up')} name="marginTop" initialValue={0} >
                        <InputNumber className="w-full" min={0} />
                      </Form.Item>
                    </Col>
                    <Col span={12}>
                      <Form.Item label={__('below')} name="marginBottom" initialValue={0} >
                        <InputNumber className="w-full" min={0} />
                      </Form.Item>
                    </Col>
                  </Row>
                  <Row gutter={10}>
                    <Col span={12}>
                      <Form.Item label={__('left')} name="marginLeft" initialValue={0} >
                        <InputNumber className="w-full" min={0} />
                      </Form.Item>
                    </Col>
                    <Col span={12}>
                      <Form.Item label={__('right')} name="marginRight" initialValue={0} >
                        <InputNumber className="w-full" min={0} />
                      </Form.Item>
                    </Col>
                  </Row>
                  <Row>
                    <Col span={24}>
                      <Form.Item name="direction" label={__('direction')}
                        initialValue={0}
                        rules={[{ required: true, }]}>
                        <Radio.Group>
                          <Radio value={0} style={{ marginRight: 32 }}>{__('vertical')}</Radio>
                          <Radio value={1}>{__('horizontal')}</Radio>
                        </Radio.Group>
                      </Form.Item>
                    </Col>
                  </Row>
                </div>
                <div className="print-setting-label">打印内容</div>
                <div className="print-setting-content">
                  <Row>
                    <Col span={12}>
                      <Form.Item name="count" label={__('CRUD.copies')} initialValue={1} rules={[{
                        validator: async (rule, value) => {
                          if (value < 1 || value > 10000) {
                            throw new Error(`${__('CRUD.fillIn')}1-10000`);
                          }
                        }
                      }]}>
                        <InputNumber className='input-count' min={1} max={10000} formatter={value => value ? Number(value).toFixed(0) : ''} />
                      </Form.Item>
                    </Col>
                  </Row>
                </div>
              </div>
            </Form>
          </div>
        </div>
        <div className={cx('Modal-footer')} >
          <Button level="primary" onClick={this.handleFilePreview.bind(this)} >{__('preview')}</Button>
          <Button level="primary" onClick={this.handleFilePrint.bind(this)} >{__('print')}</Button>
          <Button onClick={(e: any) => onHide(e)}>取消</Button>
        </div >
      </>
    )
  }
}