import React from 'react';
import RN, {DeviceEventEmitter, Image, View, Text} from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
import {connect} from 'react-redux';
import {debounce} from 'throttle-debounce';
import KeyEvent from 'react-native-keyevent';
import Icon from 'react-native-vector-icons/Ionicons';
import NumberModal from '../components/NumberModal';
import Modal from '../components/Modal';
import {colors, font} from '../utils/common';
import Touch from '../components/Touch';
import ModalStyles from '../components/Modal/styles';
import Speech from '../utils/Speech';
import Toast from '../components/Toast';
import NP from '../utils/np';
import {total} from '../utils/validity';
import RedPacketModal from '../components/RedPacketModal';
import {width, height, scaleSize} from '../utils/screen';
import EnterEvent from '../utils/EnterEvent';
import Printer from '../utils/Printer';
import AutoClick from '../utils/AutoClick';
import QRCode from 'react-native-qrcode-svg';
import {login, ossLink} from '../utils/config';

window.RN = RN;
window.Toast = Toast;
window.Speech = Speech;

const mStyles = {
  ...ModalStyles,
  innerContainer: {
    ...ModalStyles.innerContainer,
    width: width > 777 ? 777 : scaleSize(900),
  },
  header: {
    ...ModalStyles.header,
    fontSize: font.title,
    width: width > 777 ? '100%' : '95%',
  },
};

const clearTime = 300; // 五分钟自动清空购物车
const paidTime = 30; // 支付完成等待时间 30s
const delay = 1500; // 扫码后延迟时间

const wait = t => new Promise(resolve => setTimeout(resolve, t));

const CounterMixins = ComposeComponent => {
  class Mixins extends ComposeComponent {
    static displayName = 'CounterMixins';

    state = {
      stype: 'guard',
      isInduction: false,
      goodsArr: [],
      preventRevert: false,
      modalS: false,
      current: 1,
      preventMsg: '',
      caseUp: false,
      voiceModal: false,
      title: '',
      dot: false,
      luckyVisible: false,
      autoplayTime: 10,
      imgArr: [],
      adType: 'image',
      visible: false,
      receipt: {},
      printer: [],
      receiptTime: 5,
      cloudFinishModal: false,
      noBuyModal: false,
      logoVisible: true,
      nobodyVoice: false,
      numberValue: '',
      human: false,
      totalNum: 0,
    };

    componentWillMount = async () => {
      const {data} = await this.props.dispatch({
        type: 'store/getAdvertising',
        service: 'counter',
      });
      if (data.code === 1 && data.data && Object.keys(data.data)) {
        this.setState({
          autoplayTime: Number(data.data.time),
          imgArr: data.data.image,
          adType: data.data.type,
        });
      }
      this.initSetting();
      await this.refreshLogo();

      const human = await AsyncStorage.getItem('HUMAN');
      const stype = await AsyncStorage.getItem('STYPE');
      const qrHost = await AsyncStorage.getItem('QRHOST');
      const isInduction = await AsyncStorage.getItem('isInduction');
      await this.setState({
        qrHost,
        stype,
        isInduction: isInduction === '1',
        human: human === '1',
      });
    };

    componentDidMount = async () => {
      window.scan = this.submitBarcode;
      window.clear = this.clearList;
      this.goodsMap = {}; // 缓存商品数据
      this.barcode = ''; // 记录条形码
      this.totalNum = 0; // 总件数
      this.weight = 0;
      this.clearListInter = setInterval(() => {
        window.count++;
        if (window.count === clearTime) {
          this.clearList();
          window.count = window.defaultCount;
        }
      }, 1000);
      DeviceEventEmitter.addListener('onSpeechStart', () => (this.busy = true));
      DeviceEventEmitter.addListener(
        'onSpeechFinish',
        () => (this.busy = false),
      );
      DeviceEventEmitter.addListener('onError', () => (this.busy = false));
      const handleScan = this.submitBarcode;
      // if you want to react to keyUp
      KeyEvent.onKeyDownListener(async e => {
        const {keyCode, pressedKey} = e;
        if (keyCode === 66) {
          // 回车事件
          await handleScan();
          this.barcode = '';
        } else if (keyCode >= 7 && keyCode <= 16) {
          this.barcode += keyCode - 7;
        } else if (keyCode >= 29 && keyCode <= 54) {
          this.barcode += pressedKey;
        } else {
          this.barcode += pressedKey;
        }
      });
      EnterEvent.on('Trigger', async () => {
        await handleScan();
        this.barcode = '';
      });
      this.printerConnect();
      this.listen();
      if (this.state.nobodyVoice) {
        this.guideVoice();
      }
    };

    initSetting = () => {
      AutoClick.isSettingsOn().then(setting => {
        if (!setting) this.setState({setting: true}); // 展示辅助按钮
      });
      AsyncStorage.getItem('hideLogo').then(hide => {
        if (hide === 'true') this.setState({logoVisible: false}); // 隐藏LOGO
      });
    };

    refreshLogo = async () => {
      let group = await AsyncStorage.getItem('KEY');
      let {data} = await this.props.dispatch({
        type: 'store/findModuleSetting',
        group,
      });
      if (data.code === 1 && data.data) {
        const state = {priceVisible: data.data.priceVisible};
        if (data.data.cardCounter) {
          // 是否支持刷卡
          state.isCard = true;
          window.cardCounter = data.data.cardCounter;
        }
        if (data.data.logo) state.logo = `${ossLink}/${data.data.logo}`;
        this.setState(state);
      }
    };

    hideLogo = async () => {
      if (!this.num) this.num = 0;
      this.num++;
      if (this.num >= 10) {
        this.num = 0;
        let {logoVisible} = this.state;
        AsyncStorage.setItem('hideLogo', String(logoVisible));
        this.setState({
          logoVisible: !logoVisible,
        });
      }
    };

    handleCard = async cardId => {
      Toast.hide();
      if (!cardId) return;
      Toast.loading('正在付款，请稍后~');
      const {ids, noBarcode} = this.getGoods();
      this.props
        .dispatch({
          type: 'goods/cardPay',
          ids,
          noBarcode,
          cardId,
        })
        .then(async ({data}) => {
          this.props.dispatch({
            type: 'goods/cardVisible',
            visible: false,
          });
          if (data.code === 1) {
            this.orderId = data.data.orderId;
            await this.successPay(true);
          } else {
            Toast.hide();
            Speech.speak(data.msg);
            this.setState({voiceModal: true, voiceTitle: data.msg});
          }
        });
      setTimeout(() => {
        this.setState({voiceModal: false});
      }, 3000);
    };

    componentWillUnmount = () => {
      clearInterval(this.clearListInter);
      clearInterval(this.payInter);
      clearTimeout(this.paidTimeout);
      KeyEvent.removeKeyUpListener();
    };

    printerConnect = async () => {
      if (Printer) {
        const isConnected = await Printer.isConnected();
        if (!isConnected) await Printer.usbConnect(); // 尝试连接打印机模块
      }
    };

    setDelay = debounce(delay, true, () => {
      this.isDelay = true;
      setTimeout(() => {
        this.isDelay = false;
      }, delay);
    });

    listen = async () => {
      while (!window.socket) {
        await wait(1000);
      }
      if (window.socket.hasListeners('counterOrder')) {
        window.socket.removeAllListeners('counterOrder');
      }
      if (window.socket.hasListeners('cmdOperate')) {
        window.socket.removeAllListeners('cmdOperate');
      }
      if (window.socket.hasListeners('adsOperate')) {
        window.socket.removeAllListeners('adsOperate');
      }
      if (window.socket.hasListeners('goodsData')) {
        window.socket.removeAllListeners('goodsData');
      }
      if (window.socket.hasListeners('goodsOperate')) {
        window.socket.removeAllListeners('goodsOperate');
      }
      if (window.socket.hasListeners('humanSwitch')) {
        window.socket.removeAllListeners('humanSwitch');
      }
      window.socket.on('cmdOperate', this.command.bind(this));
      window.socket.on('adsOperate', ({adsData}) => {
        this.setState({
          autoplayTime: Number(adsData.time),
          imgArr: adsData[adsData.type],
          adType: adsData.type,
        });
      });
      window.socket.on(
        'goodsOperate',
        ({type, number, row, barcode, price}) => {
          const index = row;
          if (type === 'add') {
            // 新增
            this.submitBarcode(barcode);
          } else if (type === 'update') {
            // 修改
            this.numIndex = index;
            this.submitGoodNum(number);
          } else if (type === 'delete') {
            // 删除
            this.removeIndex(index);
          } else if (type === 'price') {
            // 无码商品
            this.submitCodeless(price);
          } else if (type === 'clear') {
            // 清除商品
            this.clearList();
          }
        },
      );
      window.socket.on('goodsData', () => {
        const data = [];
        const {goodsArr} = this.state;
        goodsArr.map(
          ({
            barcode,
            category,
            name,
            num,
            prePrice,
            price,
            spec,
            unit,
            weight,
          }) => {
            data.push({
              name,
              barcode,
              category: category || '',
              price: price || 0,
              unit: unit || '个',
              prePrice: prePrice || 0,
              num,
              weight: weight || 0,
              spec: spec || '',
            });
          },
        );
        window.socket.emit('goodsData', JSON.stringify(data));
      });
      window.socket.on(
        'counterOrder',
        ({type, msg, sid, token, payType, orderId}) => {
          let totalPrice = this.totalPrice;
          let totalCount = this.totalCount;
          if (type === 'waiting') {
            // 客户端等待，响应购物车列表
            this.token = token;
            const {ids, noBarcode} = this.getGoods();
            window.socket.emit(
              'counterGoods',
              sid,
              JSON.stringify(ids),
              totalPrice,
              totalCount,
              payType,
              JSON.stringify(noBarcode),
            );
          } else if (type === 'fail') {
            // 下单失败
            Speech.speak(msg);
          } else if (type === 'paying') {
            if (this.isPaying) return;
            this.isPaying = true;
            clearTimeout(this.payingTimeout);
            this.payingTimeout = setTimeout(() => {
              this.isPaying = false;
            }, 2000);
            // 下单成功，等待用户支付
            let count = 0;
            this.props.dispatch({
              // 扫码付款步骤
              type: 'app/step',
              step: 2,
            });
            clearInterval(this.payInter); // 清除定时查询订单
            this.payInter = setInterval(async () => {
              count++;
              if (count >= 30) {
                // 一分钟，超时关闭付款
                this.props.dispatch({
                  // 返回商品扫码步骤
                  type: 'app/step',
                  step: 1,
                });
                clearInterval(this.payInter);
                this.setState({voiceModal: false});
              }
            }, 3000);
            this.setState({voiceModal: true, voiceTitle: msg});
            Speech.speak(msg);
          } else if (type === 'paid') {
            if (orderId) {
              this.orderId = orderId;
              let count = 0;
              this.props.dispatch({
                // 扫码付款步骤
                type: 'app/step',
                step: 2,
              });
              clearInterval(this.payInter); // 清除定时查询订单
              this.payInter = setInterval(async () => {
                if (!this.state.voiceModal) {
                  clearInterval(this.payInter);
                }
                count++;
                const order = await this.props.dispatch({
                  type: 'goods/status',
                  orderId, // 订单号,
                });
                if (order.code === 1 && order.data === 1) {
                  this.setState({voiceModal: false});
                  this.successPay();
                  clearInterval(this.payInter); // 清除定时查询订单
                  this.isPaid = true; // 支付成功，暂停检测秤的重量
                  this.paidTimeout = setTimeout(() => {
                    this.isPaid = false;
                  }, paidTime * 1000);
                  setTimeout(() => {
                    this.props.dispatch({
                      // 返回商品扫码步骤
                      type: 'app/step',
                      step: 1,
                    });
                    this.setState({voiceModal: false});
                  }, 3000);
                }
                if (count >= 20) {
                  // 一分钟，超时关闭付款
                  this.props.dispatch({
                    // 返回商品扫码步骤
                    type: 'app/step',
                    step: 1,
                  });
                  clearInterval(this.payInter);
                  setTimeout(() => {
                    this.setState({voiceModal: false});
                  }, 3000);
                }
              }, 3000);
            } else {
              this.props.dispatch({
                // 购物完成步骤
                type: 'app/step',
                step: 3,
              });
              this.clearList();
              this.setState({voiceModal: true, voiceTitle: msg});
              Speech.speak(msg);
              clearInterval(this.payInter); // 清除定时查询订单
              this.isPaid = true; // 支付成功，暂停检测重力感应器的重量
              this.paidTimeout = setTimeout(() => {
                this.isPaid = false;
              }, paidTime * 1000);
              setTimeout(() => {
                this.props.dispatch({
                  // 返回商品扫码步骤
                  type: 'app/step',
                  step: 1,
                });
                this.setState({voiceModal: false});
              }, 3000);
            }
          }
        },
      );
      window.socket.on('humanSwitch', ({human}) => {
        this.setState({human});
      });
    };

    // 运营端远程命令
    command = ({cmd}) => {
      try {
        eval(cmd);
      } catch (e) {
        console.warn(e.message);
      }
    };

    // 锁定授权设置
    lock = lock => {
      if (!window.auth) {
        return '门店未授权无法锁定';
      }
      this.props.dispatch({
        type: 'app/lock',
        lock,
      });
      if (lock) {
        return '门店设置已锁定';
      }
      return '门店设置已解锁';
    };

    successPay = async facepay => {
      Toast.hide();
      const {goodsArr, human} = this.state;
      let total = 0;
      let totalNum = 0;
      goodsArr.map(item => {
        totalNum += Number(item.num);
        if (item.price) {
          total += Number(item.price) * Number(item.num);
        } else {
          total += Number(item.prePrice) * Number(item.num);
        }
      });
      let msg = '付款' + total + '元，共' + totalNum + '件商品';
      this.props.dispatch({
        // 购物完成步骤
        type: 'app/step',
        step: 3,
      });
      // this.setState({voiceModal: true, voiceTitle: msg});
      // if (!facepay) {
      //   await Speech.speak('付款成功');
      // }
      if (this.state.stype === 'guard' && !human) {
        let group = await AsyncStorage.getItem('KEY');
        let {data} = await this.props.dispatch({
          type: 'store/getStore',
          group,
        });
        if (data.code === 1) {
          if (data.data && data.data.payLeave) {
            await Speech.speak(msg);
            setTimeout(() => {
              this.onOpen();
            }, 1000);
          } else {
            await Speech.speak('付款成功');
            this.showLeaveModal();
          }
        } else {
          this.showLeaveModal();
        }
      } else {
        msg += '，祝您生活愉快';
        await Speech.speak(msg);
        await this.storeSetting(goodsArr);
        await this.onLucky();
      }
      this.clearList();
    };

    storeSetting = async printer => {
      let group = await AsyncStorage.getItem('KEY');
      let {data} = await this.props.dispatch({
        type: 'store/getStore',
        group,
      });
      if (data.code === 1) {
        this.setState({
          receipt: (data.data && data.data.receipt) || {},
          printer,
        });
        if (data.data && data.data.receipt && data.data.receipt.enable) {
          if (data.data.receipt.confirm) {
            await this.setState({
              visible: true,
              receiptTime: data.data.receipt.tipsTime || 5,
            });
            clearInterval(this.receiptTimeInter);
            this.receiptTimeInter = setInterval(async () => {
              await this.setState({receiptTime: this.state.receiptTime - 1});
              if (this.state.receiptTime <= 0) {
                this.setState({
                  visible: false,
                  receiptTime: data.data.receipt.tipsTime || 5,
                });
                clearInterval(this.receiptTimeInter);
              }
            }, 1000);
          } else {
            this.print();
          }
        }
      }
    };

    confirm = () => {
      this.setState({visible: false});
      this.print();
    };

    print = async () => {
      let total = 0;
      let goods = [];
      this.state.printer.map(v => {
        total += (v.price > 0 ? v.price : v.prePrice) * v.num;
        goods.push(
          `${v.name},${v.num},${v.price > 0 ? v.price : v.prePrice},${(v.price >
          0
            ? v.price
            : v.prePrice) * v.num}`,
        );
      });
      goods.push(`总计, , ,${total.toFixed(2)}`);
      await Printer.printNote(goods, this.state.receipt);
      this.setState({printer: []});
    };

    showLeaveModal = () => {
      const {stype, human} = this.state;
      if (stype === 'guard' && !human) {
        Speech.speak('请点击收银界面开门离店按钮，离开门店');
        this.setState({cloudFinishModal: true});
        clearTimeout(this.leaveModalTimeout);
        this.leaveModalTimeout = setTimeout(() => {
          this.setState({cloudFinishModal: false});
        }, 25000);
      }
    };

    // 付款成功，若达到领取红包的金额则弹出领取红包的弹窗
    onLucky = async () => {
      // 支付成功，用户完成付款
      let {dispatch} = this.props;
      let {code: codeLucky, data: dataLucky} = await dispatch({
        type: 'lucky/getLucky',
        orderId: this.orderId,
      });
      if (codeLucky === 1) {
        this.setState({
          luckyVisible: true,
          amount: dataLucky.amount,
        });
        setTimeout(() => {
          this.setState({
            luckyVisible: false,
          });
          this.showLeaveModal();
        }, 10000);
      } else {
        this.showLeaveModal();
      }
    };

    speak = (msg, showModal, duration = 3000) => {
      if (!this.busy) {
        Speech.speak(msg);
      }
      if (showModal) {
        this.setState({voiceModal: true, voiceTitle: msg});
        setTimeout(() => {
          this.setState({voiceModal: false});
        }, duration);
      }
    };

    dropUp = () => {
      let {current} = this.state;
      if (current > 1) {
        this.setDelay();
        this.setState({
          current: --current,
        });
      }
    };

    dropDown = goodsLength => {
      let {current} = this.state;
      if (current < goodsLength) {
        this.setDelay();
        this.setState({
          current: ++current,
        });
      }
    };

    numRemove = (num, index) => {
      if (num > 1) {
        this.setDelay();
        let gaArr = this.state.goodsArr;
        gaArr[index].num = Number(num) - 1;
        this.setState({
          goodsArr: gaArr,
        });
        this.goodsChangeSpeak(gaArr);
      }
      this.setState({
        focus: true,
      });
    };

    modalResult = () => {
      clearTimeout(this.mrTimeout);
      this.mrTimeout = setTimeout(() => {
        this.setState({
          modalS: false,
          numberValue: '',
        });
      }, 15000);
    };

    refreshModalResult = () => {
      clearTimeout(this.mrTimeout);
      this.mrTimeout = setTimeout(() => {
        this.setState({
          modalS: false,
          numberValue: '',
        });
      }, 15000);
    };

    setNumberValue = numberValue => {
      this.setState({
        numberValue,
      });
    };

    handleBarcode = () => {
      this.handleScan = this.submitBarcode;
      this.setState({
        modalS: true,
        title: '录入条码',
        dot: false,
      });
      this.modalResult();
    };

    handleCodeless = () => {
      this.handleScan = this.submitCodeless;
      this.setState({
        modalS: true,
        title: '无码商品',
        dot: true,
      });
      this.modalResult();
    };

    numChange = index => {
      this.handleScan = this.submitGoodNum;
      this.numIndex = index;
      this.setState({
        modalS: true,
        title: '修改数量',
      });
      this.modalResult();
    };

    numAdd = (num, index) => {
      this.setDelay();
      let gaArr = this.state.goodsArr;
      if (gaArr[index].category === '特价') {
        Toast.info('特价商品每人限购一次哦', 2);
      } else {
        gaArr[index].num = Number(num) + 1;
        this.errGood = gaArr[index];
        this.errGood.index = index;
        this.setState({
          goodsArr: gaArr,
        });
        this.goodsChangeSpeak(gaArr);
      }
    };

    removeIndex = index => {
      this.setDelay();
      let goodsArr = [].concat(this.state.goodsArr);
      goodsArr.splice(index, 1);
      this.setState({
        goodsArr,
      });
      this.goodsChangeSpeak(goodsArr);
    };

    submitGoodNum = async num => {
      this.setDelay();
      let gaArr = this.state.goodsArr;
      if (gaArr[this.numIndex].category === '特价') {
        Toast.info('特价商品每人限购一次哦', 2);
      } else {
        gaArr[this.numIndex].num = Number(num);
        this.errGood = gaArr[this.numIndex];
        this.errGood.index = this.numIndex;
        this.setState({
          goodsArr: gaArr,
        });
        this.goodsChangeSpeak(gaArr);
      }
    };

    submitBarcode = async barcode => {
      if (this.props.goods.cardVisible) {
        return await this.handleCard(barcode || this.barcode);
      }
      this.errGood = null;
      if (!window.auth) {
        const msg = '系统未授权，无法查询商品';
        this.setState({voiceModal: true, voiceTitle: msg});
        Speech.speak(msg);
        clearTimeout(this.noAuthTimeout);
        this.noAuthTimeout = setTimeout(() => {
          this.setState({voiceModal: false});
        }, 3000);
        return;
      }
      barcode = barcode || this.barcode;
      if (isNaN(barcode.substring(0, 4))) {
        const msg = '请遮住条码旁边的二维码，再重新扫条码';
        this.setState({voiceModal: true, voiceTitle: msg});
        Speech.speak(msg);
        setTimeout(() => {
          this.setState({voiceModal: false});
        }, 3500);
        return;
      }
      if (await this.barcodepay(barcode)) {
        return;
      }
      window.count = window.defaultCount;
      if (barcode) {
        const goods = this.goodsMap[barcode];
        if (!goods) {
          this.timeout = Date.now();
          Toast.loading('正在查询商品', 3, () => {
            const timeDiff = Date.now() - this.timeout;
            if (timeDiff > 2500) {
              this.props.dispatch({
                type: 'agora/talkCall',
                isBug: 1,
              });
            }
          });
        }
        this.setDelay();
        let {goodsArr} = this.state;
        this.barcode = '';
        let {data} = goods
          ? {data: {code: 1, data: goods}}
          : await this.props.dispatch({
              type: 'goods/getGoods',
              barcode,
            });
        if (!data) {
          return;
        }
        if (data.code < 0) {
          this.speak(data.msg);
          return;
        }
        let stopSpecial = false;
        if (data.data.category === '特价') {
          for (let i = 0; i < goodsArr.length; i++) {
            if (goodsArr[i].name === data.data.name) {
              stopSpecial = true;
              break;
            }
          }
        }
        let price = Number(data.data.price || data.data.prePrice);
        if (data.code === 1 && price > 0 && !stopSpecial) {
          if (!data.data.num) {
            data.data.numChange = true;
          } // 称重计价不可修改数量
          this.goodsMap[barcode] = data.data;
          let dataReal = data.data;
          let t = 0;
          let totalNum = 0;
          for (let i = 0; i < goodsArr.length; i++) {
            if (goodsArr[i].barcode === barcode) {
              goodsArr[i].num += 1;
            } else {
              t++;
            }
            totalNum =
              Number(NP.round(totalNum, 2).toFixed(2)) +
              Number(NP.round(goodsArr[i].num, 2).toFixed(2));
          }
          if (t === goodsArr.length) {
            dataReal.num = data.data.num || 1;
            totalNum =
              Number(NP.round(totalNum, 2).toFixed(2)) +
              Number(NP.round(dataReal.num, 2).toFixed(2));
            goodsArr.push({...dataReal});
          }
          const current = Math.ceil(goodsArr.length / window.pageSize);
          // clearInterval(this.nobodyInter);
          await this.setState({
            current,
            goodsArr,
            modalS: false,
            nobodyInter: false,
          });
          this.goodsChangeSpeak(goodsArr);
          Toast.hide();
        } else if (data.code === 1 && price <= 0) {
          Toast.info('商品价格异常，请联系客服人员处理', 2);
        } else if (data.code === 1 && stopSpecial) {
          Toast.info('特价商品每人限购一次哦', 2);
        } else if (data.code === 2) {
          Toast.fail(data.data, 1.5);
        }
      }
    };

    submitCodeless = async price => {
      if (!total.test(price)) {
        Toast.info('商品价格的小数点只能输入两位', 2);
      } else if (Number(NP.round(price, 2).toFixed(2)) <= 0) {
        Toast.info('商品价格必须要大于0', 2);
      } else if (Number(NP.round(price, 2).toFixed(2)) > 2000000) {
        Toast.info('商品价格不能大于2000000', 2);
      } else {
        const {goodsArr} = this.state;
        const good = {
          barcode: '000000',
          name: '无码商品',
          // unit: 1,
          num: 1,
          // price: NP.round(price, 2).toFixed(2),
          prePrice: NP.round(price, 2).toFixed(2),
          numChange: false,
        };
        goodsArr.push({...good});
        const current = Math.ceil(goodsArr.length / window.pageSize);
        this.setState({
          current,
          goodsArr,
          modalS: false,
          dot: false,
        });
        Toast.hide();
        this.goodsChangeSpeak(goodsArr);
      }
    };

    goodsChangeSpeak = goodsArr => {
      let totalNum = 0;
      goodsArr.map(v => {
        totalNum =
          Number(NP.round(totalNum, 2).toFixed(2)) +
          Number(NP.round(v.num, 2).toFixed(2));
      });
      this.setState({
        totalNum,
      });
      Speech.speak('共' + totalNum + '件商品');
    };

    getGoods = () => {
      const {goodsArr} = this.state;
      const ids = {};
      const noBarcode = [];
      goodsArr.map(({barcode, num, prePrice, name}) => {
        if (barcode !== '000000') {
          //非无码商品
          if (!ids[barcode]) {
            ids[barcode] = num;
          } else {
            ids[barcode] += num;
          }
        } else {
          noBarcode.push({
            name,
            barcode,
            price: 0,
            purPrice: 0,
            prePrice,
            num,
            weight: 0,
          });
        }
      });
      return {ids, noBarcode};
    };

    // 付款码支付
    barcodepay = async (code, facepay, openid, fToken, uid) => {
      if (this.barcodeBusy) {
        return true;
      }
      const isWxpay = code.toString().match(/1[0-5]\d{16}/);
      const isAlipay =
        fToken || code.toString().match(/^(2[5-9]|30)\d{14,22}$/);
      if (!isWxpay && !isAlipay) {
        return false;
      }
      if (window.cardCounter) {
        this.speak('不支持使用付款码付款', true);
        return true;
      }
      Toast.loading('正在付款，请稍后~');
      this.barcodeBusy = true;
      let successPay = false;
      const {ids, noBarcode} = this.getGoods();
      const res = await this.props.dispatch({
        type: 'goods/barcodepay',
        ids,
        code,
        facepay,
        noBarcode,
        openid,
        fToken,
        uid,
      });
      if (res.code !== 1) {
        await this.setState({voiceModal: true, voiceTitle: res.msg});
        Speech.speak(res.msg);
      }
      if (res.code === 1) {
        // 付款成功
        this.orderId = res.data.orderId;
        if (res.data.users) {
          this.barcodeUser = res.data;
          await this.selectUserModal();
        }
        if (res.data.alipayUserId) {
          // 没有匹配到支付宝用户
          const voiceTitle =
            '为了正常出店，首次使用支付宝付款码，请用进店微信扫描屏幕二维码';
          // this.orderId = res.data.orderId;
          this.alipayUserId = res.data.alipayUserId;
          Speech.speak(voiceTitle);
          this.setState({voiceTitle});
        } else {
          if (facepay) {
            setTimeout(() => {
              this.successPay(facepay);
            }, 2000);
          } else {
            this.successPay();
          }
          successPay = true;
          await wait(3000);
          // await wait(res.data.timeout);
        }
      } else if (res.code === 2) {
        // 等待付款
        for (let i = 0; i < 20; i++) {
          await wait(3000);
          if (!this.state.voiceModal) {
            break;
          }
          const status = await this.props.dispatch({
            type: 'goods/status',
            orderId: res.data.orderId, // 订单号,
          });
          if (status.code === 1 && status.data === 1) {
            this.successPay();
            successPay = true;
            await wait(3000);
            break;
          }
        }
      } else if (res.code === 3) {
        // 付款失败
        await wait(res.data.timeout);
      } else {
        await wait(3000);
      }
      this.setState({voiceModal: false});
      this.barcodeBusy = false;
      if (successPay) {
        return 'SUCCESS';
      }
      return true;
    };

    balancePay = async openid => {
      if (this.barcodeBusy) {
        return true;
      }
      Toast.loading('正在付款，请稍后~');
      this.barcodeBusy = true;
      const {ids, noBarcode} = this.getGoods();
      const {data} = await this.props.dispatch({
        type: 'goods/balancePay',
        ids,
        noBarcode,
        openid,
      });
      if (data.code === 1) {
        // 付款成功
        this.orderId = data.data.orderId;
        if (openid) {
          this.successPay(true);
        } else {
          this.successPay();
        }
        await AutoClick.clickBackKey();
        await wait(3000);
        await this.setState({voiceModal: false});
        this.barcodeBusy = false;
        return data;
      }
      this.barcodeBusy = false;
      return data;
    };

    selectUserModal = () =>
      new Promise(async resolve => {
        this.barcodeResolve = resolve;
        const {users} = this.barcodeUser;
        const msg = '请选择您的微信账号或手机号码';
        await this.setState({users, usersModal: true, voiceTitle: msg});
        Speech.speak(msg);
        this.barcodeTimeout = setTimeout(() => {
          this.setState({usersModal: false});
          resolve();
        }, 30000);
      });

    // 选择付款码对应用户
    selectUser = userId => {
      const {alipayUserId, orderId} = this.barcodeUser;
      this.props.dispatch({
        type: 'goods/barcodeUser',
        userId,
        alipayUserId,
        orderId,
      });
      this.setState({usersModal: false});
      clearTimeout(this.barcodeTimeout);
      if (this.barcodeResolve) {
        this.barcodeResolve();
      }
    };

    clearList = () => {
      this.setDelay();
      this.goodsMap = {};
      this.setState({
        goodsArr: [],
      });
      this.guideVoice();
    };

    guideVoice = () => {
      // if (this.nobodyInter) clearInterval(this.nobodyInter);
      // const that = this;
      // this.nobodyInter = setInterval(async () => {
      //   if (this.state.nobodyVoice) {
      //     await Speech.speak('您好，选购完商品后请到收银机这边付款');
      //     await wait(5000);
      //     await Speech.speak('请先扫描商品条码，再出示付款码');
      //   } else {
      //     clearInterval(that.nobodyInter);
      //   }
      // }, 45000);
      // this.setState({
      //   nobodyVoice: true,
      // });
    };

    pushBag = index => {
      let {goods} = this.props;
      this.submitBarcode(goods.bags[index].barcode);
    };

    talkCall = () => {
      this.props.dispatch({
        type: 'agora/talkCall',
      });
    };

    onCloseLucky = () => {
      this.setState({
        luckyVisible: false,
      });
      const {stype} = this.state;
      if (stype === 'guard') {
        Speech.speak('请点击收银界面开门离店按钮，离开门店');
        this.setState({
          cloudFinishModal: true,
        });
      }
    };

    onCloseCloudFinish = () => {
      this.setState({
        cloudFinishModal: false,
      });
      this.clearList();
    };

    onOpen = async () => {
      this.setState({
        cloudFinishModal: false,
      });
      const {data} = await this.props.dispatch({
        type: 'store/open',
        orderId: this.orderId,
        isScan: !this.state.isInduction,
      });
      if (data.code === 1) {
        Speech.speak(data.msg || '门已经打开，谢谢惠顾');
      } else if (data.code === -2) {
        Speech.speak(data.msg || '开门失败，正在为您呼叫客服');
        this.talkCall();
      } else if (data.code === -1) {
        Speech.speak(data.msg || '开门失败，请扫收银机二维码认证手机号');
        this.setState({
          noBuyModal: true,
        });
        setTimeout(() => {
          this.setState({noBuyModal: false});
        }, 30000);
      } else {
        setTimeout(async () => {
          const {data: dataNext} = await this.props.dispatch({
            type: 'store/open',
            orderId: this.orderId,
            isScan: !this.state.isInduction,
          });
          if (dataNext.code === 1) {
            Speech.speak(data.msg || '门已经打开，谢谢惠顾');
          } else if (data.code === -1) {
            Speech.speak(data.msg || '开门失败，请扫收银机二维码认证手机号');
            this.setState({
              noBuyModal: true,
            });
            setTimeout(() => {
              this.setState({noBuyModal: false});
            }, 30000);
          } else {
            Speech.speak(data.msg || '开门失败，正在为您呼叫客服');
            this.talkCall();
          }
        }, 500);
      }
      this.clearList();
    };

    onReceiveLucky = async () => {
      const {data} = await this.props.dispatch({
        type: 'lucky/receiveLucky',
        orderId: this.orderId,
      });
      Toast.success(data.msg);
    };

    onNumberClose = () => {
      clearTimeout(this.mrTimeout);
      this.setState({
        modalS: false,
        dot: false,
        numberValue: '',
      });
    };

    render = () => {
      let {
        cloudFinishModal,
        voiceModal,
        voiceTitle,
        title,
        luckyVisible,
        amount,
        visible,
        receiptTime,
        noBuyModal,
        logoVisible,
        qrHost,
        nobodyVoice,
        numberValue,
      } = this.state;
      return (
        <View style={{flex: 1}}>
          <RN.Modal
            style={{margin: 0, padding: 0}}
            visible={noBuyModal}
            transparent>
            <View
              style={{
                width: '100%',
                height: '100%',
                margin: 0,
                position: 'relative',
              }}>
              <Touch
                style={{
                  width: '100%',
                  height: '100%',
                  backgroundColor: '#000',
                  opacity: 0.5,
                }}
                onPress={() => this.setState({noBuyModal: false})}>
                <View />
              </Touch>
              <View style={styles.HintPhone}>
                <Image
                  source={require('../assets/Vertical/realname.png')}
                  style={{left: 20, position: 'absolute'}}
                />
                <Image
                  source={require('../assets/Vertical/police.png')}
                  style={{right: 20, position: 'absolute'}}
                />
                <Text style={{fontSize: scaleSize(50), marginBottom: 20}}>
                  请扫码出店
                </Text>
                <QRCode
                  logoSize={width > 801 ? 50 : scaleSize(100)}
                  // logoBackgroundColor="#fc4000"
                  logo={logoVisible && require('../assets/logo2.png')}
                  size={width > 801 ? 200 : scaleSize(400)}
                  value={`${qrHost || login}/#/store-leave-g${this.storeKey}`}
                />
              </View>
            </View>
          </RN.Modal>
          <Modal visible={visible} transparent>
            {/*<View style={{width,height,backgroundColor:'rgba(0,0,0,.5)'}} />*/}
            <View
              style={{
                height: height * 0.15,
                backgroundColor: '#fff',
                justifyContent: 'center',
                alignItems: 'center',
              }}>
              <Text
                style={{
                  textAlign: 'center',
                  fontSize: font.textMDActive,
                }}>
                是否打印小票?
              </Text>
              <View
                style={{
                  flexDirection: 'row',
                  justifyContent: 'space-around',
                  marginTop: 30,
                }}>
                <Touch onPress={() => this.setState({visible: false})}>
                  <Text
                    style={{
                      width: width * 0.1,
                      height: width * 0.05,
                      borderRadius: width * 0.05,
                      textAlign: 'center',
                      textAlignVertical: 'center',
                      fontSize: font.textF,
                      margin: 20,
                      backgroundColor: '#959595',
                      color: '#fff',
                    }}>
                    取消({receiptTime}s)
                  </Text>
                </Touch>
                <Touch onPress={() => this.confirm()}>
                  <Text
                    style={{
                      width: width * 0.1,
                      height: width * 0.05,
                      borderRadius: width * 0.05,
                      textAlign: 'center',
                      textAlignVertical: 'center',
                      fontSize: font.textF,
                      margin: 20,
                      backgroundColor: colors.bg,
                      color: '#fff',
                    }}>
                    确认
                  </Text>
                </Touch>
              </View>
            </View>
          </Modal>
          <NumberModal
            title={title}
            onClose={this.onNumberClose}
            visible={this.state.modalS}
            onSubmit={this.handleScan}
            dot={this.state.dot}
            operateCb={this.refreshModalResult}
            value={numberValue}
            setValue={this.setNumberValue}
          />
          <RedPacketModal
            luckyVisible={luckyVisible}
            amount={amount}
            orderId={this.orderId}
            onReceiveLucky={this.onReceiveLucky}
            onCloseLucky={this.onCloseLucky}
          />
          <Modal
            maskClosable
            styles={mStyles}
            visible={voiceModal}
            transparent
            title={voiceTitle}
            onClose={() => this.setState({voiceModal: false})}>
            <View style={{justifyContent: 'center', alignItems: 'center'}}>
              <CloseButton onClose={() => this.setState({voiceModal: false})} />
              <Image source={require('../assets/voice.gif')} />
            </View>
          </Modal>
          <Modal visible={cloudFinishModal} transparent>
            <View style={{alignItems: 'center'}}>
              <View
                style={{
                  flexDirection: 'row',
                  justifyContent: 'center',
                  marginBottom: 10,
                }}>
                <Image
                  style={{
                    width: 100,
                    height: 100,
                    marginLeft: 0,
                    marginTop: -8,
                    resizeMode: 'contain',
                    alignSelf: 'flex-start',
                  }}
                  source={require('../assets/paied.png')}
                />
                <View
                  style={{
                    justifyContent: 'center',
                    alignItems: 'center',
                    flex: 1,
                  }}>
                  <Text style={{color: '#000000', fontSize: 32}}>云值守店</Text>
                </View>
                <Touch
                  onPress={() => this.onCloseCloudFinish()}
                  style={{
                    width: 100,
                    height: 100,
                    justifyContent: 'flex-start',
                    alignItems: 'flex-end',
                  }}>
                  <Image
                    style={{
                      width: 30,
                      height: 30,
                      marginRight: -8,
                      marginTop: -16,
                      resizeMode: 'contain',
                    }}
                    source={require('../assets/close.png')}
                  />
                </Touch>
              </View>
              <Touch
                onPress={() => this.onOpen()}
                style={{
                  width: '90%',
                  height: 80,
                  borderRadius: 5,
                  justifyContent: 'center',
                  alignItems: 'center',
                  backgroundColor: '#FC4000',
                  marginVertical: 30,
                }}>
                <Text style={{color: '#ffffff', fontSize: 28}}>开门离店</Text>
              </Touch>
            </View>
          </Modal>
          <ComposeComponent
            {...this.props}
            {...this.state}
            pushBag={this.pushBag}
            handleBarcode={this.handleBarcode}
            barcodepay={this.barcodepay}
            handleCodeless={this.handleCodeless}
            clearList={this.clearList}
            numAdd={this.numAdd}
            numRemove={this.numRemove}
            numChange={this.numChange}
            removeIndex={this.removeIndex}
            dropUp={this.dropUp}
            dropDown={this.dropDown}
            speak={this.speak}
            balancePay={this.balancePay}
          />
          <View
            style={{
              width: 100,
              height: 100,
              position: 'absolute',
              top: 0,
              left: 0,
              zIndex: 999,
              opacity: 0,
            }}>
            <Touch
              style={{
                width: '100%',
                height: '100%',
              }}
              onPress={() => {
                this.setState({nobodyVoice: !nobodyVoice});
                if (!nobodyVoice) {
                  this.guideVoice();
                }
              }}>
              <View />
            </Touch>
          </View>
        </View>
      );
    };
  }

  return connect(({goods, admin, store}) => ({
    goods,
    admin,
    store,
  }))(Mixins);
};

const CloseButton = ({onClose, style}) => {
  return (
    <Touch
      style={{position: 'absolute', top: -70, right: -5, ...style}}
      onPress={onClose}
      feedback={false}>
      <Icon size={40} name="ios-close-circle-outline" />
    </Touch>
  );
};

const styles = {
  HintPhone: {
    width: width > 801 ? '50%' : '80%',
    height: width > 801 ? '25%' : '40%',
    backgroundColor: '#ffffff',
    position: 'absolute',
    top: '20%',
    left: width > 801 ? '25%' : '10%',
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    opacity: 40,
  },
};

export default CounterMixins;
