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, PrinterParam, sizeOptions } from "../type";
import moment from "moment";
import { fromUint8Array } from "js-base64";

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>; // 选中的行数据
    rows: Array<any>; // 选中的行数据
    selectedItems: Array<any>; // 选中的行数据
    unSelectedItems: 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
  fileDatas: FileData[]
}

interface FilePrintFormValues {
  printer: string
  direction: number
  count: number
  pageSize: string
  pageWidth: number
  pageHeight: number
}

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

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

  constructor(props: FilePrintProps) {
    super(props)
    this.state = {
      previewLoading: 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() {
    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: PrinterParam = {
        ...values,
        direction: values.direction === 0,
        preview: true,
        arrange: false,
        colSpacing: 0,
        rowSpacing: 0,
        marginTop: 0,
        marginLeft: 0
      }

      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: PrinterParam = {
      ...values,
      direction: values.direction === 0,
      preview: false,
      arrange: false,
      colSpacing: 0,
      rowSpacing: 0,
      marginTop: 0,
      marginLeft: 0
    }
    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 } = this.state
    return (
      <>
        <div className={cx('Modal-header')}>
          <div className={cx('Modal-title')}>
            {'文件打印'}
            <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} />
              <iframe id='label-preview' width='100%' height='100%'></iframe>
            </div>
            <Form ref={this.formRef} colon={false} labelCol={{ span: 5, offset: 1 }} wrapperCol={{ span: 16, offset: 1 }}>
              <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>

              <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>

              <Row gutter={24}>
                <Col span={6} style={{ position: 'relative', top: 2, padding: 0, textAlign: 'right' }}>
                  宽*高(mm)
                </Col>

                <Col span={8} style={{ paddingLeft: 15 }}>
                  <Form.Item style={{ width: 140 }} name="pageWidth" 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={8} style={{ marginLeft: 12 }}>
                  <Form.Item style={{ width: 140 }} name="pageHeight" 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>

              <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>

              <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>
            </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) => onHide(e)}>取消</Button>
        </div >
      </>
    )
  }
}