import React, { useEffect } from 'react';
import MqttClient from 'mqtt-client';
import PropTypes from 'prop-types';
import CryptoJS from 'crypto-js';
class MqttView {
  constructor(props) {
    this.userName = props.userName;
    this.password = props.password;
    this.mqttIP = props.mqttIP;
    this.mqttPath = props.mqttPath;
    this.mqttSsl = props.mqttSsl;
    this.siteCode = props.siteCode;
    this.devices = props.devices;
    this.callback = props.callback;
    this.controlback = props.controlback;
    this.alarmback = props.alarmback;
    this.params = props.params || {};
    this.isAlarm = props.isAlarm || false;
    this.flag = false;
  }

  //Mqtt第一步
  saveWaterMqtt() {
    const hostname = this.mqttIP.split(':')[0],
      port = this.mqttIP.split(':')[1] * 1,
      clientId = 'PandaWeb-' + this.createGuid(),
      timeout = 50,
      keepAlive = 60,
      cleanSession = true,
      ssl = this.mqttSsl,
      path = this.mqttPath,
      userName = this.userName || 'admin',
      password = this.password ? getDecryptedValue(this.password) : 'public';
    const queryStr = this.toQueryString(this.params);
    this.saveWaCount = 0;
    this.saveWaClient = new MqttClient.Client(
      hostname,
      port,
      `${path}?_site=${this.siteCode}${queryStr ? '&' + queryStr : ''}`,
      clientId,
    );
    this.saveWaOptions = {
      invocationContext: {
        host: hostname,
        port: port,
        path: path,
        clientId: clientId,
      },
      timeout: timeout,
      keepAliveInterval: keepAlive,
      cleanSession: cleanSession,
      useSSL: ssl,
      userName: userName,
      password: password,
      onSuccess: this.onSaveWaConnect.bind(this),
      onFailure: function (e) {
        console.log(e);
      },
    };
    //注册连接断开处理事件
    this.saveWaClient.onConnectionLost = this.onSaveWaConnectionLost.bind(this);
    //注册消息接收处理事件
    this.saveWaClient.onMessageArrived = this.onSaveWaMessageArrived.bind(this);
    this.saveWaClient.connect(this.saveWaOptions);
  }

  //消息接收方法
  onSaveWaMessageArrived(message) {
    this.onMessageArrived(message, 'saveWaType');
  }

  //主题建立连接
  onSaveWaConnect() {
    this.flag = true;
    this.devices.forEach((item) => {
      if (item) {
        const saveWaTopic = this.siteCode + '/' + item.replace(/[#+]/g, '@');
        this.saveWaClient.subscribe(saveWaTopic);
      }
    });
    this.devices.forEach((item) => {
      if (item) {
        this.saveWaClient.subscribe(
          'callback/control/' + this.siteCode + '/' + item.replace(/[#+]/g, '@') + '/#',
        );
      }
    });
    this.isAlarm &&
      this.devices.forEach((item) => {
        if (item) {
          const saveWaTopic = this.siteCode + '/' + item.replace(/[#+]/g, '@') + '/alarm' + '/#';
          this.saveWaClient.subscribe(saveWaTopic);
        }
      });
  }

  //主题断开连接
  disSaveWaconnect() {
    if (this.saveWaClient) {
      this.flag = false;
      // this.saveWaClient.disconnect();
      if (this.saveWaClient.isConnected()) this.saveWaClient.disconnect();
      if (this.saveWatester) {
        clearInterval(this.saveWatester);
        this.saveWatester = null;
      }
    }
  }

  //主题掉线重连接
  onSaveWaConnectionLost() {
    if (this.flag) this.saveWaClient.connect(this.saveWaOptions);
    this.saveWatester = setInterval(() => {
      if (this.saveWaClient.isConnected()) {
        clearInterval(this.saveWatester);
        this.saveWatester = null;
      } else {
        this.saveWaClient.connect(this.saveWaOptions);
      }
    }, 1000);
  }

  //消息接收(控制和订阅)
  onMessageArrived(message, infoType) {
    try {
      const topic = message.topic;
      const code = topic.split('/')[topic.split('/').length - 1];
      if(!message?.payloadString) return false;
      const payloadString = JSON.stringify(JSON.parse(message.payloadString));
      if (topic.indexOf('callback/control/' + this.siteCode) > -1) {
        this.controlback(payloadString, code, topic);
        return false;
      }
      if (topic.indexOf('alarm') > -1) {
        const alarmCode = topic.split('/')[1];
        this.alarmback(payloadString, alarmCode, topic);
        return false;
      }
      this.callback(payloadString, code, topic);
    } catch (err) {}
  }

  //消息发送
  onSendWaMessageArrived(
    userName,
    password,
    callbackGuid,
    devicecode,
    tag,
    type,
    val,
    controlMode,
  ) {
    const info = {
      userName: userName,
      password: password,
      callbackGuid: callbackGuid,
      type: '',
      operateType: type,
      controlValue: val || String(val) != '' ? val : '',
      sitecode: this.siteCode,
      devicecode: devicecode,
      controlMode: controlMode ? controlMode : '',
      tag: tag,
    };
    let message = new MqttClient.Message(JSON.stringify(info));
    message.destinationName = 'setdata/' + this.siteCode + '/' + devicecode;
    this.saveWaClient.send(message);
  }

  //生成GUID
  createGuid() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
      .replace(/[xy]/g, function (c) {
        const r = (Math.random() * 16) | 0,
          v = c == 'x' ? r : (r & 0x3) | 0x8;
        return v.toString(16);
      })
      .toUpperCase();
  }

  // 转为url参数
  toQueryString(obj) {
    return Object.keys(obj)
      .map((key) => encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]))
      .join('&');
  }
}

MqttView.propTypes = {
  userName: PropTypes.string,
  password: PropTypes.string,
  mqttIP: PropTypes.string,
  mqttPath: PropTypes.string,
  mqttSsl: PropTypes.bool,
  siteCode: PropTypes.string,
  devices: PropTypes.array,
  params: PropTypes.object,
  isAlarm: PropTypes.bool,
  callback: PropTypes.func,
  controlback: PropTypes.func,
  alarmback: PropTypes.func,
};

MqttView.defaultProps = {
  userName: 'admin',
  password: 'public',
  mqttIP: '',
  mqttPath: '/mqtt',
  mqttSsl: false,
  siteCode: '',
  devices: [],
  params: {},
  isAlarm: false,
  callback: () => {},
  controlback: () => {},
  alarmback: () => {},
};

// 解密
export const getDecryptedValue = (encryptedText) => {
  const AESKey = '1p2a3n4d5a6o7m8s9a10n1e2t3c4o5re'; //32位
  const AES_IV = '1234567890000000'; //16位
  const key = CryptoJS.enc.Utf8.parse(AESKey);
  const iv = CryptoJS.enc.Utf8.parse(AES_IV);

  // 解密
  const decrypted = CryptoJS.AES.decrypt(
    { ciphertext: CryptoJS.enc.Hex.parse(encryptedText) },
    key,
    { iv: iv },
  );
  // 转换为明文
  const plaintext = decrypted.toString(CryptoJS.enc.Utf8);

  return plaintext;
};

// 加密
export const getEncryptedValue = (password) => {
  const AESKey = '1p2a3n4d5a6o7m8s9a10n1e2t3c4o5re'; //32位
  const AES_IV = '1234567890000000'; //16位
  const key = CryptoJS.enc.Utf8.parse(AESKey);
  const iv = CryptoJS.enc.Utf8.parse(AES_IV);

  const psd = CryptoJS.AES.encrypt(password, key, { iv: iv })
    .ciphertext.toString(CryptoJS.enc.Hex)
    .toUpperCase();

  return psd;
};

export default MqttView;
