/*******************************************************************************
 * Copyright (c) 2013, 2014 IBM Corp.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 *
 * The Eclipse Public License is available at
 *    http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 *
 *******************************************************************************/

"undefined" === typeof Paho && (window.Paho = {});
Paho.MQTT = function (u) {
  function y(a, b, c) {
    b[c++] = a >> 8;
    b[c++] = a % 256;
    return c
  }

  function r(a, b, c, h) {
    h = y(b, c, h);
    F(a, c, h);
    return h + b
  }

  function m(a) {
    for (var b = 0, c = 0; c < a.length; c++) {
      var h = a.charCodeAt(c);
      2047 < h ? (55296 <= h && 56319 >= h && (c++, b++), b += 3) : 127 < h ? b += 2 : b++
    }
    return b
  }

  function F(a, b, c) {
    for (var h = 0; h < a.length; h++) {
      var e = a.charCodeAt(h);
      if (55296 <= e && 56319 >= e) {
        var d = a.charCodeAt(++h);
        if (isNaN(d)) throw Error(f(g.MALFORMED_UNICODE, [e, d]));
        e = (e - 55296 << 10) + (d - 56320) + 65536
      }
      127 >= e ? b[c++] = e : (2047 >= e ? b[c++] = e >> 6 & 31 |
        192 : (65535 >= e ? b[c++] = e >> 12 & 15 | 224 : (b[c++] = e >> 18 & 7 | 240, b[c++] = e >> 12 & 63 | 128), b[c++] = e >> 6 & 63 | 128), b[c++] = e & 63 | 128)
    }
    return b
  }

  function G(a, b, c) {
    for (var h = "", e, d = b; d < b + c;) {
      e = a[d++];
      if (!(128 > e)) {
        var p = a[d++] - 128;
        if (0 > p) throw Error(f(g.MALFORMED_UTF, [e.toString(16), p.toString(16), ""]));
        if (224 > e) e = 64 * (e - 192) + p; else {
          var t = a[d++] - 128;
          if (0 > t) throw Error(f(g.MALFORMED_UTF, [e.toString(16), p.toString(16), t.toString(16)]));
          if (240 > e) e = 4096 * (e - 224) + 64 * p + t; else {
            var l = a[d++] - 128;
            if (0 > l) throw Error(f(g.MALFORMED_UTF,
              [e.toString(16), p.toString(16), t.toString(16), l.toString(16)]));
            if (248 > e) e = 262144 * (e - 240) + 4096 * p + 64 * t + l; else throw Error(f(g.MALFORMED_UTF, [e.toString(16), p.toString(16), t.toString(16), l.toString(16)]));
          }
        }
      }
      65535 < e && (e -= 65536, h += String.fromCharCode(55296 + (e >> 10)), e = 56320 + (e & 1023));
      h += String.fromCharCode(e)
    }
    return h
  }

  var A = function (a, b) {
    for (var c in a) if (a.hasOwnProperty(c)) if (b.hasOwnProperty(c)) {
      if (typeof a[c] !== b[c]) throw Error(f(g.INVALID_TYPE, [typeof a[c], c]));
    } else {
      var h = "Unknown property, " + c +
        ". Valid properties are:";
      for (c in b) b.hasOwnProperty(c) && (h = h + " " + c);
      throw Error(h);
    }
  }, q = function (a, b) {
    return function () {
      return a.apply(b, arguments)
    }
  }, g = {
    OK: {code: 0, text: "AMQJSC0000I OK."},
    CONNECT_TIMEOUT: {code: 1, text: "AMQJSC0001E Connect timed out."},
    SUBSCRIBE_TIMEOUT: {code: 2, text: "AMQJS0002E Subscribe timed out."},
    UNSUBSCRIBE_TIMEOUT: {code: 3, text: "AMQJS0003E Unsubscribe timed out."},
    PING_TIMEOUT: {code: 4, text: "AMQJS0004E Ping timed out."},
    INTERNAL_ERROR: {code: 5, text: "AMQJS0005E Internal error. Error Message: {0}, Stack trace: {1}"},
    CONNACK_RETURNCODE: {code: 6, text: "AMQJS0006E Bad Connack return code:{0} {1}."},
    SOCKET_ERROR: {code: 7, text: "AMQJS0007E Socket error:{0}."},
    SOCKET_CLOSE: {code: 8, text: "AMQJS0008I Socket closed."},
    MALFORMED_UTF: {code: 9, text: "AMQJS0009E Malformed UTF data:{0} {1} {2}."},
    UNSUPPORTED: {code: 10, text: "AMQJS0010E {0} is not supported by this browser."},
    INVALID_STATE: {code: 11, text: "AMQJS0011E Invalid state {0}."},
    INVALID_TYPE: {code: 12, text: "AMQJS0012E Invalid type {0} for {1}."},
    INVALID_ARGUMENT: {code: 13, text: "AMQJS0013E Invalid argument {0} for {1}."},
    UNSUPPORTED_OPERATION: {code: 14, text: "AMQJS0014E Unsupported operation."},
    INVALID_STORED_DATA: {code: 15, text: "AMQJS0015E Invalid data in local storage key={0} value={1}."},
    INVALID_MQTT_MESSAGE_TYPE: {code: 16, text: "AMQJS0016E Invalid MQTT message type {0}."},
    MALFORMED_UNICODE: {code: 17, text: "AMQJS0017E Malformed Unicode string:{0} {1}."}
  }, J = {
    0: "Connection Accepted",
    1: "Connection Refused: unacceptable protocol version",
    2: "Connection Refused: identifier rejected",
    3: "Connection Refused: server unavailable",
    4: "Connection Refused: bad user name or password",
    5: "Connection Refused: not authorized"
  }, f = function (a, b) {
    var c = a.text;
    if (b) for (var h, e, d = 0; d < b.length; d++) if (h = "{" + d + "}", e = c.indexOf(h), 0 < e) var g = c.substring(0, e),
      c = c.substring(e + h.length), c = g + b[d] + c;
    return c
  }, B = [0, 6, 77, 81, 73, 115, 100, 112, 3], C = [0, 4, 77, 81, 84, 84, 4], n = function (a, b) {
    this.type = a;
    for (var c in b) b.hasOwnProperty(c) && (this[c] = b[c])
  };
  n.prototype.encode = function () {
    var a = (this.type & 15) << 4, b = 0, c = [], h = 0;
    void 0 != this.messageIdentifier && (b += 2);
    switch (this.type) {
      case 1:
        switch (this.mqttVersion) {
          case 3:
            b +=
              B.length + 3;
            break;
          case 4:
            b += C.length + 3
        }
        b += m(this.clientId) + 2;
        if (void 0 != this.willMessage) {
          var b = b + (m(this.willMessage.destinationName) + 2), e = this.willMessage.payloadBytes;
          e instanceof Uint8Array || (e = new Uint8Array(g));
          b += e.byteLength + 2
        }
        void 0 != this.userName && (b += m(this.userName) + 2);
        void 0 != this.password && (b += m(this.password) + 2);
        break;
      case 8:
        for (var a = a | 2, d = 0; d < this.topics.length; d++) c[d] = m(this.topics[d]), b += c[d] + 2;
        b += this.requestedQos.length;
        break;
      case 10:
        a |= 2;
        for (d = 0; d < this.topics.length; d++) c[d] =
          m(this.topics[d]), b += c[d] + 2;
        break;
      case 6:
        a |= 2;
        break;
      case 3:
        this.payloadMessage.duplicate && (a |= 8);
        a = a |= this.payloadMessage.qos << 1;
        this.payloadMessage.retained && (a |= 1);
        var h = m(this.payloadMessage.destinationName), g = this.payloadMessage.payloadBytes,
          b = b + (h + 2) + g.byteLength;
        g instanceof ArrayBuffer ? g = new Uint8Array(g) : g instanceof Uint8Array || (g = new Uint8Array(g.buffer))
    }
    var f = b, d = Array(1), l = 0;
    do {
      var z = f % 128, f = f >> 7;
      0 < f && (z |= 128);
      d[l++] = z
    } while (0 < f && 4 > l);
    f = d.length + 1;
    b = new ArrayBuffer(b + f);
    l = new Uint8Array(b);
    l[0] = a;
    l.set(d, 1);
    if (3 == this.type) f = r(this.payloadMessage.destinationName, h, l, f); else if (1 == this.type) {
      switch (this.mqttVersion) {
        case 3:
          l.set(B, f);
          f += B.length;
          break;
        case 4:
          l.set(C, f), f += C.length
      }
      a = 0;
      this.cleanSession && (a = 2);
      void 0 != this.willMessage && (a = a | 4 | this.willMessage.qos << 3, this.willMessage.retained && (a |= 32));
      void 0 != this.userName && (a |= 128);
      void 0 != this.password && (a |= 64);
      l[f++] = a;
      f = y(this.keepAliveInterval, l, f)
    }
    void 0 != this.messageIdentifier && (f = y(this.messageIdentifier, l, f));
    switch (this.type) {
      case 1:
        f =
          r(this.clientId, m(this.clientId), l, f);
        void 0 != this.willMessage && (f = r(this.willMessage.destinationName, m(this.willMessage.destinationName), l, f), f = y(e.byteLength, l, f), l.set(e, f), f += e.byteLength);
        void 0 != this.userName && (f = r(this.userName, m(this.userName), l, f));
        void 0 != this.password && r(this.password, m(this.password), l, f);
        break;
      case 3:
        l.set(g, f);
        break;
      case 8:
        for (d = 0; d < this.topics.length; d++) f = r(this.topics[d], c[d], l, f), l[f++] = this.requestedQos[d];
        break;
      case 10:
        for (d = 0; d < this.topics.length; d++) f = r(this.topics[d],
          c[d], l, f)
    }
    return b
  };
  var H = function (a, b, c) {
    this._client = a;
    this._window = b;
    this._keepAliveInterval = 1E3 * c;
    this.isReset = !1;
    var h = (new n(12)).encode(), e = function (a) {
      return function () {
        return d.apply(a)
      }
    }, d = function () {
      this.isReset ? (this.isReset = !1, this._client._trace("Pinger.doPing", "send PINGREQ"), this._client.socket.send(h), this.timeout = this._window.setTimeout(e(this), this._keepAliveInterval)) : (this._client._trace("Pinger.doPing", "Timed out"), this._client._disconnected(g.PING_TIMEOUT.code, f(g.PING_TIMEOUT)))
    };
    this.reset = function () {
      this.isReset = !0;
      this._window.clearTimeout(this.timeout);
      0 < this._keepAliveInterval && (this.timeout = setTimeout(e(this), this._keepAliveInterval))
    };
    this.cancel = function () {
      this._window.clearTimeout(this.timeout)
    }
  }, D = function (a, b, c, f, e) {
    this._window = b;
    c || (c = 30);
    this.timeout = setTimeout(function (a, b, c) {
      return function () {
        return a.apply(b, c)
      }
    }(f, a, e), 1E3 * c);
    this.cancel = function () {
      this._window.clearTimeout(this.timeout)
    }
  }, k = function (a, b, c, h, e) {
    if (!("WebSocket" in u && null !== u.WebSocket)) throw Error(f(g.UNSUPPORTED,
      ["WebSocket"]));
    if (!("localStorage" in u && null !== u.localStorage)) throw Error(f(g.UNSUPPORTED, ["localStorage"]));
    if (!("ArrayBuffer" in u && null !== u.ArrayBuffer)) throw Error(f(g.UNSUPPORTED, ["ArrayBuffer"]));
    this._trace("Paho.MQTT.Client", a, b, c, h, e);
    this.host = b;
    this.port = c;
    this.path = h;
    this.uri = a;
    this.clientId = e;
    this._localKey = b + ":" + c + ("/mqtt" != h ? ":" + h : "") + ":" + e + ":";
    this._msg_queue = [];
    this._sentMessages = {};
    this._receivedMessages = {};
    this._notify_msg_sent = {};
    this._message_identifier = 1;
    this._sequence = 0;
    for (var d in localStorage) 0 !=
    d.indexOf("Sent:" + this._localKey) && 0 != d.indexOf("Received:" + this._localKey) || this.restore(d)
  };
  k.prototype.host;
  k.prototype.port;
  k.prototype.path;
  k.prototype.uri;
  k.prototype.clientId;
  k.prototype.socket;
  k.prototype.connected = !1;
  k.prototype.maxMessageIdentifier = 65536;
  k.prototype.connectOptions;
  k.prototype.hostIndex;
  k.prototype.onConnectionLost;
  k.prototype.onMessageDelivered;
  k.prototype.onMessageArrived;
  k.prototype.traceFunction;
  k.prototype._msg_queue = null;
  k.prototype._connectTimeout;
  k.prototype.sendPinger =
    null;
  k.prototype.receivePinger = null;
  k.prototype.receiveBuffer = null;
  k.prototype._traceBuffer = null;
  k.prototype._MAX_TRACE_ENTRIES = 100;
  k.prototype.connect = function (a) {
    var b = this._traceMask(a, "password");
    this._trace("Client.connect", b, this.socket, this.connected);
    if (this.connected) throw Error(f(g.INVALID_STATE, ["already connected"]));
    if (this.socket) throw Error(f(g.INVALID_STATE, ["already connected"]));
    this.connectOptions = a;
    a.uris ? (this.hostIndex = 0, this._doConnect(a.uris[0])) : this._doConnect(this.uri)
  };
  k.prototype.subscribe = function (a, b) {
    this._trace("Client.subscribe", a, b);
    if (!this.connected) throw Error(f(g.INVALID_STATE, ["not connected"]));
    var c = new n(8);
    c.topics = [a];
    c.requestedQos = void 0 != b.qos ? [b.qos] : [0];
    b.onSuccess && (c.onSuccess = function (a) {
      b.onSuccess({invocationContext: b.invocationContext, grantedQos: a})
    });
    b.onFailure && (c.onFailure = function (a) {
      b.onFailure({invocationContext: b.invocationContext, errorCode: a})
    });
    b.timeout && (c.timeOut = new D(this, window, b.timeout, b.onFailure, [{
      invocationContext: b.invocationContext,
      errorCode: g.SUBSCRIBE_TIMEOUT.code, errorMessage: f(g.SUBSCRIBE_TIMEOUT)
    }]));
    this._requires_ack(c);
    this._schedule_message(c)
  };
  k.prototype.unsubscribe = function (a, b) {
    this._trace("Client.unsubscribe", a, b);
    if (!this.connected) throw Error(f(g.INVALID_STATE, ["not connected"]));
    var c = new n(10);
    c.topics = [a];
    b.onSuccess && (c.callback = function () {
      b.onSuccess({invocationContext: b.invocationContext})
    });
    b.timeout && (c.timeOut = new D(this, window, b.timeout, b.onFailure, [{
      invocationContext: b.invocationContext, errorCode: g.UNSUBSCRIBE_TIMEOUT.code,
      errorMessage: f(g.UNSUBSCRIBE_TIMEOUT)
    }]));
    this._requires_ack(c);
    this._schedule_message(c)
  };
  k.prototype.send = function (a) {
    this._trace("Client.send", a);
    if (!this.connected) throw Error(f(g.INVALID_STATE, ["not connected"]));
    wireMessage = new n(3);
    wireMessage.payloadMessage = a;
    0 < a.qos ? this._requires_ack(wireMessage) : this.onMessageDelivered && (this._notify_msg_sent[wireMessage] = this.onMessageDelivered(wireMessage.payloadMessage));
    this._schedule_message(wireMessage)
  };
  k.prototype.disconnect = function () {
    this._trace("Client.disconnect");
    if (!this.socket) throw Error(f(g.INVALID_STATE, ["not connecting or connected"]));
    wireMessage = new n(14);
    this._notify_msg_sent[wireMessage] = q(this._disconnected, this);
    this._schedule_message(wireMessage)
  };
  k.prototype.getTraceLog = function () {
    if (null !== this._traceBuffer) {
      this._trace("Client.getTraceLog", new Date);
      this._trace("Client.getTraceLog in flight messages", this._sentMessages.length);
      for (var a in this._sentMessages) this._trace("_sentMessages ", a, this._sentMessages[a]);
      for (a in this._receivedMessages) this._trace("_receivedMessages ",
        a, this._receivedMessages[a]);
      return this._traceBuffer
    }
  };
  k.prototype.startTrace = function () {
    null === this._traceBuffer && (this._traceBuffer = []);
    this._trace("Client.startTrace", new Date, "@VERSION@")
  };
  k.prototype.stopTrace = function () {
    delete this._traceBuffer
  };
  k.prototype._doConnect = function (a) {
    this.connectOptions.useSSL && (a = a.split(":"), a[0] = "wss", a = a.join(":"));
    this.connected = !1;
    this.socket = 4 > this.connectOptions.mqttVersion ? new WebSocket(a, ["mqttv3.1"]) : new WebSocket(a, ["mqtt"]);
    this.socket.binaryType =
      "arraybuffer";
    this.socket.onopen = q(this._on_socket_open, this);
    this.socket.onmessage = q(this._on_socket_message, this);
    this.socket.onerror = q(this._on_socket_error, this);
    this.socket.onclose = q(this._on_socket_close, this);
    this.sendPinger = new H(this, window, this.connectOptions.keepAliveInterval);
    this.receivePinger = new H(this, window, this.connectOptions.keepAliveInterval);
    this._connectTimeout = new D(this, window, this.connectOptions.timeout, this._disconnected, [g.CONNECT_TIMEOUT.code, f(g.CONNECT_TIMEOUT)])
  };
  k.prototype._schedule_message =
    function (a) {
      this._msg_queue.push(a);
      this.connected && this._process_queue()
    };
  k.prototype.store = function (a, b) {
    var c = {type: b.type, messageIdentifier: b.messageIdentifier, version: 1};
    switch (b.type) {
      case 3:
        b.pubRecReceived && (c.pubRecReceived = !0);
        c.payloadMessage = {};
        for (var h = "", e = b.payloadMessage.payloadBytes, d = 0; d < e.length; d++) h = 15 >= e[d] ? h + "0" + e[d].toString(16) : h + e[d].toString(16);
        c.payloadMessage.payloadHex = h;
        c.payloadMessage.qos = b.payloadMessage.qos;
        c.payloadMessage.destinationName = b.payloadMessage.destinationName;
        b.payloadMessage.duplicate && (c.payloadMessage.duplicate = !0);
        b.payloadMessage.retained && (c.payloadMessage.retained = !0);
        0 == a.indexOf("Sent:") && (void 0 === b.sequence && (b.sequence = ++this._sequence), c.sequence = b.sequence);
        break;
      default:
        throw Error(f(g.INVALID_STORED_DATA, [key, c]));
    }
    localStorage.setItem(a + this._localKey + b.messageIdentifier, JSON.stringify(c))
  };
  k.prototype.restore = function (a) {
    var b = localStorage.getItem(a), c = JSON.parse(b), h = new n(c.type, c);
    switch (c.type) {
      case 3:
        for (var b = c.payloadMessage.payloadHex,
               e = new ArrayBuffer(b.length / 2), e = new Uint8Array(e), d = 0; 2 <= b.length;) {
          var k = parseInt(b.substring(0, 2), 16), b = b.substring(2, b.length);
          e[d++] = k
        }
        b = new Paho.MQTT.Message(e);
        b.qos = c.payloadMessage.qos;
        b.destinationName = c.payloadMessage.destinationName;
        c.payloadMessage.duplicate && (b.duplicate = !0);
        c.payloadMessage.retained && (b.retained = !0);
        h.payloadMessage = b;
        break;
      default:
        throw Error(f(g.INVALID_STORED_DATA, [a, b]));
    }
    0 == a.indexOf("Sent:" + this._localKey) ? (h.payloadMessage.duplicate = !0, this._sentMessages[h.messageIdentifier] =
      h) : 0 == a.indexOf("Received:" + this._localKey) && (this._receivedMessages[h.messageIdentifier] = h)
  };
  k.prototype._process_queue = function () {
    for (var a = null, b = this._msg_queue.reverse(); a = b.pop();) this._socket_send(a), this._notify_msg_sent[a] && (this._notify_msg_sent[a](), delete this._notify_msg_sent[a])
  };
  k.prototype._requires_ack = function (a) {
    var b = Object.keys(this._sentMessages).length;
    if (b > this.maxMessageIdentifier) throw Error("Too many messages:" + b);
    for (; void 0 !== this._sentMessages[this._message_identifier];) this._message_identifier++;
    a.messageIdentifier = this._message_identifier;
    this._sentMessages[a.messageIdentifier] = a;
    3 === a.type && this.store("Sent:", a);
    this._message_identifier === this.maxMessageIdentifier && (this._message_identifier = 1)
  };
  k.prototype._on_socket_open = function () {
    var a = new n(1, this.connectOptions);
    a.clientId = this.clientId;
    this._socket_send(a)
  };
  k.prototype._on_socket_message = function (a) {
    this._trace("Client._on_socket_message", a.data);
    this.receivePinger.reset();
    a = this._deframeMessages(a.data);
    for (var b = 0; b < a.length; b +=
      1) this._handleMessage(a[b])
  };
  k.prototype._deframeMessages = function (a) {
    a = new Uint8Array(a);
    if (this.receiveBuffer) {
      var b = new Uint8Array(this.receiveBuffer.length + a.length);
      b.set(this.receiveBuffer);
      b.set(a, this.receiveBuffer.length);
      a = b;
      delete this.receiveBuffer
    }
    try {
      for (var b = 0, c = []; b < a.length;) {
        var h;
        a:{
          var e = a, d = b, k = d, t = e[d], l = t >> 4, z = t & 15, d = d + 1, v = void 0, E = 0, m = 1;
          do {
            if (d == e.length) {
              h = [null, k];
              break a
            }
            v = e[d++];
            E += (v & 127) * m;
            m *= 128
          } while (0 != (v & 128));
          v = d + E;
          if (v > e.length) h = [null, k]; else {
            var w = new n(l);
            switch (l) {
              case 2:
                e[d++] &
                1 && (w.sessionPresent = !0);
                w.returnCode = e[d++];
                break;
              case 3:
                var k = z >> 1 & 3, r = 256 * e[d] + e[d + 1], d = d + 2, u = G(e, d, r), d = d + r;
                0 < k && (w.messageIdentifier = 256 * e[d] + e[d + 1], d += 2);
                var q = new Paho.MQTT.Message(e.subarray(d, v));
                1 == (z & 1) && (q.retained = !0);
                8 == (z & 8) && (q.duplicate = !0);
                q.qos = k;
                q.destinationName = u;
                w.payloadMessage = q;
                break;
              case 4:
              case 5:
              case 6:
              case 7:
              case 11:
                w.messageIdentifier = 256 * e[d] + e[d + 1];
                break;
              case 9:
                w.messageIdentifier = 256 * e[d] + e[d + 1], d += 2, w.returnCode = e.subarray(d, v)
            }
            h = [w, v]
          }
        }
        var x = h[0], b = h[1];
        if (null !==
          x) c.push(x); else break
      }
      b < a.length && (this.receiveBuffer = a.subarray(b))
    } catch (y) {
      this._disconnected(g.INTERNAL_ERROR.code, f(g.INTERNAL_ERROR, [y.message, y.stack.toString()]));
      return
    }
    return c
  };
  k.prototype._handleMessage = function (a) {
    this._trace("Client._handleMessage", a);
    try {
      switch (a.type) {
        case 2:
          this._connectTimeout.cancel();
          if (this.connectOptions.cleanSession) {
            for (var b in this._sentMessages) {
              var c = this._sentMessages[b];
              localStorage.removeItem("Sent:" + this._localKey + c.messageIdentifier)
            }
            this._sentMessages =
              {};
            for (b in this._receivedMessages) {
              var h = this._receivedMessages[b];
              localStorage.removeItem("Received:" + this._localKey + h.messageIdentifier)
            }
            this._receivedMessages = {}
          }
          if (0 === a.returnCode) this.connected = !0, this.connectOptions.uris && (this.hostIndex = this.connectOptions.uris.length); else {
            this._disconnected(g.CONNACK_RETURNCODE.code, f(g.CONNACK_RETURNCODE, [a.returnCode, J[a.returnCode]]));
            break
          }
          a = [];
          for (var e in this._sentMessages) this._sentMessages.hasOwnProperty(e) && a.push(this._sentMessages[e]);
          a = a.sort(function (a,
                               b) {
            return a.sequence - b.sequence
          });
          e = 0;
          for (var d = a.length; e < d; e++) if (c = a[e], 3 == c.type && c.pubRecReceived) {
            var k = new n(6, {messageIdentifier: c.messageIdentifier});
            this._schedule_message(k)
          } else this._schedule_message(c);
          if (this.connectOptions.onSuccess) this.connectOptions.onSuccess({invocationContext: this.connectOptions.invocationContext});
          this._process_queue();
          break;
        case 3:
          this._receivePublish(a);
          break;
        case 4:
          if (c = this._sentMessages[a.messageIdentifier]) if (delete this._sentMessages[a.messageIdentifier],
              localStorage.removeItem("Sent:" + this._localKey + a.messageIdentifier), this.onMessageDelivered) this.onMessageDelivered(c.payloadMessage);
          break;
        case 5:
          if (c = this._sentMessages[a.messageIdentifier]) c.pubRecReceived = !0, k = new n(6, {messageIdentifier: a.messageIdentifier}), this.store("Sent:", c), this._schedule_message(k);
          break;
        case 6:
          h = this._receivedMessages[a.messageIdentifier];
          localStorage.removeItem("Received:" + this._localKey + a.messageIdentifier);
          h && (this._receiveMessage(h), delete this._receivedMessages[a.messageIdentifier]);
          var m = new n(7, {messageIdentifier: a.messageIdentifier});
          this._schedule_message(m);
          break;
        case 7:
          c = this._sentMessages[a.messageIdentifier];
          delete this._sentMessages[a.messageIdentifier];
          localStorage.removeItem("Sent:" + this._localKey + a.messageIdentifier);
          if (this.onMessageDelivered) this.onMessageDelivered(c.payloadMessage);
          break;
        case 9:
          if (c = this._sentMessages[a.messageIdentifier]) {
            c.timeOut && c.timeOut.cancel();
            a.returnCode.indexOf = Array.prototype.indexOf;
            if (-1 !== a.returnCode.indexOf(128)) {
              if (c.onFailure) c.onFailure(a.returnCode)
            } else if (c.onSuccess) c.onSuccess(a.returnCode);
            delete this._sentMessages[a.messageIdentifier]
          }
          break;
        case 11:
          if (c = this._sentMessages[a.messageIdentifier]) c.timeOut && c.timeOut.cancel(), c.callback && c.callback(), delete this._sentMessages[a.messageIdentifier];
          break;
        case 13:
          this.sendPinger.reset();
          break;
        case 14:
          this._disconnected(g.INVALID_MQTT_MESSAGE_TYPE.code, f(g.INVALID_MQTT_MESSAGE_TYPE, [a.type]));
          break;
        default:
          this._disconnected(g.INVALID_MQTT_MESSAGE_TYPE.code, f(g.INVALID_MQTT_MESSAGE_TYPE, [a.type]))
      }
    } catch (l) {
      this._disconnected(g.INTERNAL_ERROR.code,
        f(g.INTERNAL_ERROR, [l.message, l.stack.toString()]))
    }
  };
  k.prototype._on_socket_error = function (a) {
    this._disconnected(g.SOCKET_ERROR.code, f(g.SOCKET_ERROR, [a.data]))
  };
  k.prototype._on_socket_close = function () {
    this._disconnected(g.SOCKET_CLOSE.code, f(g.SOCKET_CLOSE))
  };
  k.prototype._socket_send = function (a) {
    if (1 == a.type) {
      var b = this._traceMask(a, "password");
      this._trace("Client._socket_send", b)
    } else this._trace("Client._socket_send", a);
    this.socket.send(a.encode());
    this.sendPinger.reset()
  };
  k.prototype._receivePublish =
    function (a) {
      switch (a.payloadMessage.qos) {
        case "undefined":
        case 0:
          this._receiveMessage(a);
          break;
        case 1:
          var b = new n(4, {messageIdentifier: a.messageIdentifier});
          this._schedule_message(b);
          this._receiveMessage(a);
          break;
        case 2:
          this._receivedMessages[a.messageIdentifier] = a;
          this.store("Received:", a);
          a = new n(5, {messageIdentifier: a.messageIdentifier});
          this._schedule_message(a);
          break;
        default:
          throw Error("Invaild qos=" + wireMmessage.payloadMessage.qos);
      }
    };
  k.prototype._receiveMessage = function (a) {
    if (this.onMessageArrived) this.onMessageArrived(a.payloadMessage)
  };
  k.prototype._disconnected = function (a, b) {
    this._trace("Client._disconnected", a, b);
    this.sendPinger.cancel();
    this.receivePinger.cancel();
    this._connectTimeout && this._connectTimeout.cancel();
    this._msg_queue = [];
    this._notify_msg_sent = {};
    this.socket && (this.socket.onopen = null, this.socket.onmessage = null, this.socket.onerror = null, this.socket.onclose = null, 1 === this.socket.readyState && this.socket.close(), delete this.socket);
    if (this.connectOptions.uris && this.hostIndex < this.connectOptions.uris.length - 1) this.hostIndex++,
      this._doConnect(this.connectOptions.uris[this.hostIndex]); else if (void 0 === a && (a = g.OK.code, b = f(g.OK)), this.connected) {
      if (this.connected = !1, this.onConnectionLost) this.onConnectionLost({errorCode: a, errorMessage: b})
    } else if (4 === this.connectOptions.mqttVersion && !1 === this.connectOptions.mqttVersionExplicit) this._trace("Failed to connect V4, dropping back to V3"), this.connectOptions.mqttVersion = 3, this.connectOptions.uris ? (this.hostIndex = 0, this._doConnect(this.connectOptions.uris[0])) : this._doConnect(this.uri);
    else if (this.connectOptions.onFailure) this.connectOptions.onFailure({
      invocationContext: this.connectOptions.invocationContext,
      errorCode: a,
      errorMessage: b
    })
  };
  k.prototype._trace = function () {
    if (this.traceFunction) {
      for (var a in arguments) "undefined" !== typeof arguments[a] && (arguments[a] = JSON.stringify(arguments[a]));
      a = Array.prototype.slice.call(arguments).join("");
      this.traceFunction({severity: "Debug", message: a})
    }
    if (null !== this._traceBuffer) {
      a = 0;
      for (var b = arguments.length; a < b; a++) this._traceBuffer.length ==
      this._MAX_TRACE_ENTRIES && this._traceBuffer.shift(), 0 === a ? this._traceBuffer.push(arguments[a]) : "undefined" === typeof arguments[a] ? this._traceBuffer.push(arguments[a]) : this._traceBuffer.push("  " + JSON.stringify(arguments[a]))
    }
  };
  k.prototype._traceMask = function (a, b) {
    var c = {}, f;
    for (f in a) a.hasOwnProperty(f) && (c[f] = f == b ? "******" : a[f]);
    return c
  };
  var I = function (a, b, c, h) {
    var e;
    if ("string" !== typeof a) throw Error(f(g.INVALID_TYPE, [typeof a, "host"]));
    if (2 == arguments.length) {
      h = b;
      e = a;
      var d = e.match(/^(wss?):\/\/((\[(.+)\])|([^\/]+?))(:(\d+))?(\/.*)$/);
      if (d) a = d[4] || d[2], b = parseInt(d[7]), c = d[8]; else throw Error(f(g.INVALID_ARGUMENT, [a, "host"]));
    } else {
      3 == arguments.length && (h = c, c = "/mqtt");
      if ("number" !== typeof b || 0 > b) throw Error(f(g.INVALID_TYPE, [typeof b, "port"]));
      if ("string" !== typeof c) throw Error(f(g.INVALID_TYPE, [typeof c, "path"]));
      e = "ws://" + (-1 != a.indexOf(":") && "[" != a.slice(0, 1) && "]" != a.slice(-1) ? "[" + a + "]" : a) + ":" + b + c
    }
    for (var p = d = 0; p < h.length; p++) {
      var m = h.charCodeAt(p);
      55296 <= m && 56319 >= m && p++;
      d++
    }
    if ("string" !== typeof h || 65535 < d) throw Error(f(g.INVALID_ARGUMENT,
      [h, "clientId"]));
    var l = new k(e, a, b, c, h);
    this._getHost = function () {
      return a
    };
    this._setHost = function () {
      throw Error(f(g.UNSUPPORTED_OPERATION));
    };
    this._getPort = function () {
      return b
    };
    this._setPort = function () {
      throw Error(f(g.UNSUPPORTED_OPERATION));
    };
    this._getPath = function () {
      return c
    };
    this._setPath = function () {
      throw Error(f(g.UNSUPPORTED_OPERATION));
    };
    this._getURI = function () {
      return e
    };
    this._setURI = function () {
      throw Error(f(g.UNSUPPORTED_OPERATION));
    };
    this._getClientId = function () {
      return l.clientId
    };
    this._setClientId =
      function () {
        throw Error(f(g.UNSUPPORTED_OPERATION));
      };
    this._getOnConnectionLost = function () {
      return l.onConnectionLost
    };
    this._setOnConnectionLost = function (a) {
      if ("function" === typeof a) l.onConnectionLost = a; else throw Error(f(g.INVALID_TYPE, [typeof a, "onConnectionLost"]));
    };
    this._getOnMessageDelivered = function () {
      return l.onMessageDelivered
    };
    this._setOnMessageDelivered = function (a) {
      if ("function" === typeof a) l.onMessageDelivered = a; else throw Error(f(g.INVALID_TYPE, [typeof a, "onMessageDelivered"]));
    };
    this._getOnMessageArrived =
      function () {
        return l.onMessageArrived
      };
    this._setOnMessageArrived = function (a) {
      if ("function" === typeof a) l.onMessageArrived = a; else throw Error(f(g.INVALID_TYPE, [typeof a, "onMessageArrived"]));
    };
    this._getTrace = function () {
      return l.traceFunction
    };
    this._setTrace = function (a) {
      if ("function" === typeof a) l.traceFunction = a; else throw Error(f(g.INVALID_TYPE, [typeof a, "onTrace"]));
    };
    this.connect = function (a) {
      a = a || {};
      A(a, {
        timeout: "number",
        userName: "string",
        password: "string",
        willMessage: "object",
        keepAliveInterval: "number",
        cleanSession: "boolean",
        useSSL: "boolean",
        invocationContext: "object",
        onSuccess: "function",
        onFailure: "function",
        hosts: "object",
        ports: "object",
        mqttVersion: "number"
      });
      void 0 === a.keepAliveInterval && (a.keepAliveInterval = 60);
      if (4 < a.mqttVersion || 3 > a.mqttVersion) throw Error(f(g.INVALID_ARGUMENT, [a.mqttVersion, "connectOptions.mqttVersion"]));
      void 0 === a.mqttVersion ? (a.mqttVersionExplicit = !1, a.mqttVersion = 4) : a.mqttVersionExplicit = !0;
      if (void 0 === a.password && void 0 !== a.userName) throw Error(f(g.INVALID_ARGUMENT,
        [a.password, "connectOptions.password"]));
      if (a.willMessage) {
        if (!(a.willMessage instanceof x)) throw Error(f(g.INVALID_TYPE, [a.willMessage, "connectOptions.willMessage"]));
        a.willMessage.stringPayload;
        if ("undefined" === typeof a.willMessage.destinationName) throw Error(f(g.INVALID_TYPE, [typeof a.willMessage.destinationName, "connectOptions.willMessage.destinationName"]));
      }
      "undefined" === typeof a.cleanSession && (a.cleanSession = !0);
      if (a.hosts) {
        if (!(a.hosts instanceof Array)) throw Error(f(g.INVALID_ARGUMENT, [a.hosts,
          "connectOptions.hosts"]));
        if (1 > a.hosts.length) throw Error(f(g.INVALID_ARGUMENT, [a.hosts, "connectOptions.hosts"]));
        for (var b = !1, d = 0; d < a.hosts.length; d++) {
          if ("string" !== typeof a.hosts[d]) throw Error(f(g.INVALID_TYPE, [typeof a.hosts[d], "connectOptions.hosts[" + d + "]"]));
          if (/^(wss?):\/\/((\[(.+)\])|([^\/]+?))(:(\d+))?(\/.*)$/.test(a.hosts[d])) if (0 == d) b = !0; else {
            if (!b) throw Error(f(g.INVALID_ARGUMENT, [a.hosts[d], "connectOptions.hosts[" + d + "]"]));
          } else if (b) throw Error(f(g.INVALID_ARGUMENT, [a.hosts[d], "connectOptions.hosts[" +
          d + "]"]));
        }
        if (b) a.uris = a.hosts; else {
          if (!a.ports) throw Error(f(g.INVALID_ARGUMENT, [a.ports, "connectOptions.ports"]));
          if (!(a.ports instanceof Array)) throw Error(f(g.INVALID_ARGUMENT, [a.ports, "connectOptions.ports"]));
          if (a.hosts.length != a.ports.length) throw Error(f(g.INVALID_ARGUMENT, [a.ports, "connectOptions.ports"]));
          a.uris = [];
          for (d = 0; d < a.hosts.length; d++) {
            if ("number" !== typeof a.ports[d] || 0 > a.ports[d]) throw Error(f(g.INVALID_TYPE, [typeof a.ports[d], "connectOptions.ports[" + d + "]"]));
            var b = a.hosts[d], h =
              a.ports[d];
            e = "ws://" + (-1 != b.indexOf(":") ? "[" + b + "]" : b) + ":" + h + c;
            a.uris.push(e)
          }
        }
      }
      l.connect(a)
    };
    this.subscribe = function (a, b) {
      if ("string" !== typeof a) throw Error("Invalid argument:" + a);
      b = b || {};
      A(b, {
        qos: "number",
        invocationContext: "object",
        onSuccess: "function",
        onFailure: "function",
        timeout: "number"
      });
      if (b.timeout && !b.onFailure) throw Error("subscribeOptions.timeout specified with no onFailure callback.");
      if ("undefined" !== typeof b.qos && 0 !== b.qos && 1 !== b.qos && 2 !== b.qos) throw Error(f(g.INVALID_ARGUMENT, [b.qos,
        "subscribeOptions.qos"]));
      l.subscribe(a, b)
    };
    this.unsubscribe = function (a, b) {
      if ("string" !== typeof a) throw Error("Invalid argument:" + a);
      b = b || {};
      A(b, {invocationContext: "object", onSuccess: "function", onFailure: "function", timeout: "number"});
      if (b.timeout && !b.onFailure) throw Error("unsubscribeOptions.timeout specified with no onFailure callback.");
      l.unsubscribe(a, b)
    };
    this.send = function (a, b, c, d) {
      var e;
      if (0 == arguments.length) throw Error("Invalid argument.length");
      if (1 == arguments.length) {
        if (!(a instanceof x) &&
          "string" !== typeof a) throw Error("Invalid argument:" + typeof a);
        e = a;
        if ("undefined" === typeof e.destinationName) throw Error(f(g.INVALID_ARGUMENT, [e.destinationName, "Message.destinationName"]));
      } else e = new x(b), e.destinationName = a, 3 <= arguments.length && (e.qos = c), 4 <= arguments.length && (e.retained = d);
      l.send(e)
    };
    this.disconnect = function () {
      l.disconnect()
    };
    this.getTraceLog = function () {
      return l.getTraceLog()
    };
    this.startTrace = function () {
      l.startTrace()
    };
    this.stopTrace = function () {
      l.stopTrace()
    };
    this.isConnected = function () {
      return l.connected
    }
  };
  I.prototype = {
    get host() {
      return this._getHost()
    }, set host(a) {
      this._setHost(a)
    }, get port() {
      return this._getPort()
    }, set port(a) {
      this._setPort(a)
    }, get path() {
      return this._getPath()
    }, set path(a) {
      this._setPath(a)
    }, get clientId() {
      return this._getClientId()
    }, set clientId(a) {
      this._setClientId(a)
    }, get onConnectionLost() {
      return this._getOnConnectionLost()
    }, set onConnectionLost(a) {
      this._setOnConnectionLost(a)
    }, get onMessageDelivered() {
      return this._getOnMessageDelivered()
    }, set onMessageDelivered(a) {
      this._setOnMessageDelivered(a)
    },
    get onMessageArrived() {
      return this._getOnMessageArrived()
    }, set onMessageArrived(a) {
      this._setOnMessageArrived(a)
    }, get trace() {
      return this._getTrace()
    }, set trace(a) {
      this._setTrace(a)
    }
  };
  var x = function (a) {
    var b;
    if ("string" === typeof a || a instanceof ArrayBuffer || a instanceof Int8Array || a instanceof Uint8Array || a instanceof Int16Array || a instanceof Uint16Array || a instanceof Int32Array || a instanceof Uint32Array || a instanceof Float32Array || a instanceof Float64Array) b = a; else throw f(g.INVALID_ARGUMENT, [a, "newPayload"]);
    this._getPayloadString = function () {
      return "string" === typeof b ? b : G(b, 0, b.length)
    };
    this._getPayloadBytes = function () {
      if ("string" === typeof b) {
        var a = new ArrayBuffer(m(b)), a = new Uint8Array(a);
        F(b, a, 0);
        return a
      }
      return b
    };
    var c = void 0;
    this._getDestinationName = function () {
      return c
    };
    this._setDestinationName = function (a) {
      if ("string" === typeof a) c = a; else throw Error(f(g.INVALID_ARGUMENT, [a, "newDestinationName"]));
    };
    var h = 0;
    this._getQos = function () {
      return h
    };
    this._setQos = function (a) {
      if (0 === a || 1 === a || 2 === a) h = a; else throw Error("Invalid argument:" +
        a);
    };
    var e = !1;
    this._getRetained = function () {
      return e
    };
    this._setRetained = function (a) {
      if ("boolean" === typeof a) e = a; else throw Error(f(g.INVALID_ARGUMENT, [a, "newRetained"]));
    };
    var d = !1;
    this._getDuplicate = function () {
      return d
    };
    this._setDuplicate = function (a) {
      d = a
    }
  };
  x.prototype = {
    get payloadString() {
      return this._getPayloadString()
    }, get payloadBytes() {
      return this._getPayloadBytes()
    }, get destinationName() {
      return this._getDestinationName()
    }, set destinationName(a) {
      this._setDestinationName(a)
    }, get qos() {
      return this._getQos()
    },
    set qos(a) {
      this._setQos(a)
    }, get retained() {
      return this._getRetained()
    }, set retained(a) {
      this._setRetained(a)
    }, get duplicate() {
      return this._getDuplicate()
    }, set duplicate(a) {
      this._setDuplicate(a)
    }
  };
  return {Client: I, Message: x}
}(window);
