'use strict'
!(function(require, directRequire) {
  'use strict'
  function a(a) {
    return a
  }
  function b(c, a) {
    return c.seq - a.seq
  }
  function c(a) {
    return a === p.ClientRequestType.Login
      ? p.RemoteHttpUrlHost + 'remote_wxlogin'
      : a === p.ClientRequestType.JoinRoom
        ? p.RemoteHttpUrlHost + 'remote_wxjoinroom'
        : a === p.ClientRequestType.QuitRoom
          ? p.RemoteHttpUrlHost + 'remote_wxquitroom'
          : (i.expectFail.fail(() => {
              s.e(
                'invalid request type',
                a,
                'for httpUrlForClientRequestType()'
              )
            }),
            p.RemoteHttpUrlHost)
  }
  function d(a) {
    return a === p.RequestType.JoinRoom
      ? p.RemoteHttpUrlHost + 'remote_devjoinroom'
      : a === p.RequestType.QuitRoom
        ? p.RemoteHttpUrlHost + 'remote_devquitroom'
        : (i.expectFail.fail(() => {
            s.e('invalid request type', a, 'for httpUrlForDevtoolRequestType()')
          }),
          p.RemoteHttpUrlHost)
  }
  var e =
    (this && this.__decorate) ||
    function(a, b, e, f) {
      var g,
        d = arguments.length,
        c =
          3 > d
            ? b
            : null === f
              ? (f = Object.getOwnPropertyDescriptor(b, e))
              : f
      if ('object' == typeof Reflect && 'function' == typeof Reflect.decorate)
        c = Reflect.decorate(a, b, e, f)
      else
        for (var h = a.length - 1; 0 <= h; h--)
          (g = a[h]) && (c = (3 > d ? g(c) : 3 < d ? g(b, e, c) : g(b, e)) || c)
      return 3 < d && c && Object.defineProperty(b, e, c), c
    }
  Object.defineProperty(exports, '__esModule', { value: !0 })
  const f = require('ws'),
    g = require('eventemitter3'),
    h = require('child_process'),
    i = require('./46d7303eb986fa402d60bf5e929aa077.js'),
    j = require('path'),
    { getNewTicket: k } = require('./89ba85d67a88f7636d657c22b5d3e038.js'),
    l = i.isDev
      ? j.join(
          __dirname,
          '../../../../../bin/ios-remote-debug-proxy/WARemoteDebugProxy'
        )
      : j.join(
          process.execPath,
          '../../../../../Resources/bin/ios-remote-debug-proxy/WARemoteDebugProxy'
        ),
    m = require('./56a764ae9cb4336bf6babe1c1da0275b.js'),
    n = require('./dd320c6b45ca97d2e34cfcab75e86aca.js'),
    o = require('./1c9e324c5ce9b5feb007c03bcb3f41dc.js'),
    p = require('./a148d3a11fd5268109e21fb40c9d527b.js')
  exports.sorterForDebugMessage = b
  const q = require('./15ba1827c7f6564a45df6bd44da3a977.js'),
    r = (a, b, c = !0) =>
      q({
        needRandom: 1,
        needToken: 1,
        needAppID: 1,
        needParse: 1,
        needCheckErrCode: -1,
        needCheckStatusCode: 1,
        method: 'post',
        url: a,
        body: JSON.stringify(b || {})
      }),
    s = m.default('[wsserver]'),
    t = i.logInvoke(s),
    u = i.logStack(s)
  var v
  ;(function(a) {
    ;(a[(a.Dead = -1)] = 'Dead'),
      (a[(a.Uninitialized = 0)] = 'Uninitialized'),
      (a[(a.Connected = 1)] = 'Connected'),
      (a[(a.InDebug = 2)] = 'InDebug')
  })((v = exports.DebugServerStatus || (exports.DebugServerStatus = {})))
  class w extends g.EventEmitter {
    constructor(a) {
      super(),
        (this.wss = null),
        (this.client = null),
        (this.devtool = null),
        (this.cpws = null),
        (this.cp = null),
        (this.androidDeviceId = void 0),
        (this.clientProxyPort = void 0),
        (this.status = 0),
        (this.transTicket = ''),
        (this._httpRequesting = !1),
        (this.archivedDebugMessages = []),
        (this.managedSendAck = 0),
        (this.httpRequestQueue = []),
        (this.inBytesCount = 0),
        (this.outBytesCount = 0),
        (global.ds = this),
        (this.port = a.port),
        (this.mode = a.mode || 'server'),
        (this.androidDeviceId = a.androidDeviceId),
        (this.clientProxyPort = a.clientProxyPort)
    }
    setStatus(a) {
      ;(this.status = a), this.emit('statuschange')
    }
    async init() {
      this.setStatus(v.Uninitialized),
        this.wss &&
          (s.w('reinit while wss exists'),
          this.client && this.disconnectClient(404, 'wsserver closed'),
          this.wss.removeAllListeners(),
          i.tryCatch(() => this.wss.close()),
          (this.wss = null))
      const a = (this.wss = new f.Server({
        perMessageDeflate: !1,
        port: this.port
      }))
      a.on('connection', this.onWsConnection.bind(this)),
        a.on('error', this.onWssError.bind(this)),
        'ios' === this.mode
          ? this.initCp()
          : 'android' === this.mode
            ? await this.initAdb()
            : s.i('server mode')
    }
    onCpError(a = !0) {
      a ? this.initCp() : this.destroy()
    }
    async initAdb() {
      const a = await n.version()
      s.i('adb version running', a)
      const b = this.androidDeviceId,
        c = this.clientProxyPort,
        d = this.port
      await n.reverse(b, `tcp:${c}`, `tcp:${d}`)
    }
    initCp() {
      if (this.cp) {
        this.cp.removeAllListeners()
        try {
          this.cp.kill()
        } catch (a) {}
      }
      const a = (this.cp = h.spawn(l, [
        `--wsurl=ws://localhost:${this.port}`,
        `--usbport=${this.clientProxyPort}`
      ]))
      a.stdout && a.stdout.setEncoding('utf8'),
        a.stdout &&
          a.stdout.on('data', a => {
            console.log(a.toString())
          }),
        a.stderr &&
          a.stderr.on('data', a => {
            console.warn(a.toString())
          }),
        a.on('disconnect', this.onCpError.bind(this, !1)),
        a.on('close', this.onCpError.bind(this, !1)),
        a.on('exit', a => {
          s.w('cp exited with code ' + a), this.onCpError(!1)
        }),
        a.on('error', a => {
          s.e('cp encountered error', a.toString()), this.onCpError(!0)
        }),
        s.i('debugserver cp inited')
    }
    onWsConnection(a, b) {
      if (!a) return void s.w('invalid connection', a)
      const c = a.protocol || (b && b.headers.protocol)
      return c && 'string' == typeof c
        ? void ('client' === c
            ? (s.i('registered client'),
              this.client &&
                this.disconnectClient(301, 'new client registered'),
              (this.client = a),
              a.on('message', this.onClientWsMessage.bind(this)),
              this.onClientConnected())
            : 'cp' === c
              ? (s.i('registered cp'),
                (this.cpws = a),
                a.on('message', this.onCpWsMessage.bind(this)))
              : s.w('invalid protocol', c))
        : void s.w('invalid protocol', c)
    }
    onCpWsMessage(a) {
      this.emit('cpmessage', a)
    }
    sendMessageToCp(a) {
      this.cpws
        ? this.cpws.send(a, a => a && s.e(a))
        : s.w('cp not ready sending messages')
    }
    setDevtool(a) {
      this.devtool && s.w('setting devtool while devtool exists'),
        (this.devtool = a),
        this.onDevtoolSet()
    }
    onWssError(a) {
      s.e('websocket server error', a),
        this.disconnectClient(500, 'server error'),
        this.cpws &&
          (i.tryCatch(() => this.cpws.close(500, 'server error')),
          (this.cpws = null)),
        this.restart()
    }
    restart() {
      this.disconnectClient(200, 'server restart'), this.init()
    }
    onClientConnected() {
      this.devtool &&
        this.status >= v.Uninitialized &&
        this.setStatus(v.Connected),
        this.emit('clientready')
    }
    onDevtoolSet() {
      this.client &&
        this.status >= v.Uninitialized &&
        this.setStatus(v.Connected)
    }
    disconnectClient(a, b) {
      this.client &&
        (500 !== a && 200 !== a && this.devtoolQuitRoom(),
        i.tryCatch(() => this.client.removeAllListeners()),
        i.tryCatch(() => this.client.close(a, b))),
        (this.client = null),
        this.status > v.Uninitialized && this.setStatus(v.Uninitialized)
    }
    async devtoolJoinRoom(a = !0) {
      if (
        (this.status > v.Connected &&
          s.w('devtool join room while status =', this.status),
        !this.devtool)
      )
        return void s.e('devtool not ready join room', this.devtool)
      const b = this.devtool.getRoomInfo(),
        c = {
          uri: d(p.RequestType.JoinRoom),
          room_id: b.room_id,
          wxpkg_info: b.wxpkg_info,
          appid: b.appid
        },
        e = await this.makeHttpRequest(c)
      return e.baseresponse && e.baseresponse.errcode
        ? void this.onErrorCode(
            e.baseresponse.errcode,
            a ? this.devtoolJoinRoom.bind(this) : void 0
          )
        : void (e.ready && this.onRemoteDebugReady())
    }
    async devtoolQuitRoom() {
      if (
        (this.status < v.Connected &&
          s.w('devtool quit room while status =', this.status),
        !this.devtool)
      )
        return void s.e('devtool not ready quit room', this.devtool)
      const a = { uri: d(p.RequestType.QuitRoom) }
      this.makeHttpRequest(a).catch(s.w)
      this.sendMessageToClient(
        {},
        p.ClientResponseType.EventNotifyEnd,
        'debugserver-3002-client-' + Date.now()
      ),
        this.onDebugEnd()
    }
    onDebugEnd() {
      this.client && this.client.removeAllListeners(),
        (this.client = null),
        (this.devtool = null),
        this.emit('debugend'),
        this.destroy()
    }
    devtoolSendDebugMessages(a) {
      this.archivedDebugMessages.push(...a), this.archivedDebugMessages.sort(b)
      const c = []
      let d = this.managedSendAck
      for (let b = 0; b < this.archivedDebugMessages.length; b++) {
        const a = this.archivedDebugMessages[b]
        if (a.seq === d + 1) c.push(a), ++d
        else if (a.seq < d + 1) continue
        else break
      }
      if (((this.managedSendAck = d), !(1 > c.length))) {
        this.sendMessageToClient(
          { debug_message: c },
          p.ClientResponseType.MessageNotifyParallelly,
          `debugserver-2006-client-${c[0].seq}-${
            c[c.length - 1].seq
          }-${Date.now()}`
        )
      }
    }
    onRemoteDebugReady() {
      this.status < v.Connected &&
        s.w('received debug ready while status =', this.status),
        this.setStatus(v.InDebug),
        this.emit('remotedebugready')
      this.sendMessageToClient(
        {},
        p.ClientResponseType.EventNotifyBegin,
        'debugserver-3001-client-' + Date.now()
      )
    }
    onClientWsMessage(b) {
      if ('string' == typeof b) {
        const a = parseInt(b),
          c = Date.now()
        return void s.i_('delta ===', c - a)
      }
      let c
      if (!b)
        return (
          s.w('received empty message from client ws', b),
          void s.f('<RECEIVED> <CLIENT> <EMPTY>  ' + b)
        )
      if (Buffer.isBuffer(b)) c = b
      else if ('string' == typeof b) c = Buffer.from(b)
      else if (Buffer.isBuffer(b.data)) c = b.data
      else if ('string' == typeof b.data) c = Buffer.from(b.data)
      else
        return (
          s.w('received invalid message from client ws', b),
          void s.f('<RECEIVED> <CLIENT> <INVALID>  ' + b)
        )
      this.inBytesCount += c.byteLength || 0
      const d = i.tryCatch(() => o.unwrapClientProtoToDataFormat(c))
      if (i.invalidTryCatchResult(d)) {
        const a = { type: 'receivedbrokenmessage', message: d.error.message }
        return (
          this.emit('event', a),
          s.e('invalid client ws message', b, d.error.stack),
          void s.f('<RECEIVED CLIENT BROKEN>')
        )
      }
      s.f('<RECEIVED CLIENT> {(cmd): ' + d.cmd, ', (uuid): ' + d.uuid)
      const e = a(d.cmd)
      if (e === p.ClientRequestType.Login)
        s.i('client login'), this.onClientLogin(d.data, d)
      else if (e === p.ClientRequestType.Heartbeat)
        s.i('client heartbeat'), this.onClientHeartbeat(d.data, d)
      else if (e === p.ClientRequestType.JoinRoom)
        s.i('client join room'), this.onClientJoinRoom(d.data, d)
      else if (e === p.ClientRequestType.QuitRoom)
        s.i('client quit room'), this.onClientQuitRoom(d.data, d)
      else if (e === p.ClientRequestType.SyncMessage)
        s.i('client sync'), this.onClientSyncMessage(d.data, d)
      else if (e === p.ClientRequestType.SendDebugMessageParallelly)
        this.onClientSendDebugMessageParallelly(d.data, d)
      else {
        this.emit('event', { type: 'receivedinvalidmessage' }),
          s.w('invalid client cmd', d.cmd, e)
      }
    }
    async onClientLogin(a, b) {
      this.status < v.Connected &&
        s.w('received client login while status < connected')
      const d = b.uuid || '',
        e = {
          url: c(p.ClientRequestType.Login),
          login_ticket: a.loginticket + ''
        },
        f = await this.makeHttpRequest(e),
        g = {
          base_response: {
            errcode: (f.baseresponse || {}).errcode || 0,
            errmsg: (f.baseresponse || {}).errmsg || ''
          }
        }
      if (this.devtool) {
        const a = this.devtool.getRoomInfo()
        ;(g.room_info = a),
          this.transTicket &&
            0 < this.transTicket.length &&
            (g.room_info.join_room = !0)
      } else s.e('devtool not ready for room infos')
      ;(this.transTicket = f.trans_ticket || ''),
        this.sendMessageToClient(g, p.ClientResponseType.Login, d)
    }
    onClientHeartbeat(a, b) {
      const c = b.uuid
      this.sendMessageToClient(
        { base_response: { errcode: 0 } },
        p.ClientResponseType.Heartbeat,
        c
      )
    }
    async onClientJoinRoom(a, b) {
      const d = b.uuid,
        e = {
          url: c(p.ClientRequestType.JoinRoom),
          trans_ticket: this.transTicket,
          room_id: a.room_id,
          wxpkg_info: a.wxpkg_info
        }
      this.devtool && (e.appid = this.devtool.getRoomInfo().appid)
      const f = await this.makeHttpRequest(e),
        g = {
          base_response: {
            errcode: (f.baseresponse || {}).errcode || 0,
            errmsg: (f.baseresponse || {}).errmsg || ''
          }
        }
      this.sendMessageToClient(g, p.ClientResponseType.JoinRoom, d),
        f.ready && this.onRemoteDebugReady()
    }
    async onClientQuitRoom(a, b) {
      const d = b.uuid,
        e = {
          url: c(p.ClientRequestType.QuitRoom),
          trans_ticket: this.transTicket
        },
        f = await this.makeHttpRequest(e),
        g = {
          base_response: {
            errcode: (f.baseresponse || {}).errcode || 0,
            errmsg: (f.baseresponse || {}).errmsg || ''
          }
        }
      this.sendMessageToClient(g, p.ClientResponseType.QuitRoom, d),
        this.onDebugEnd()
    }
    onClientSyncMessage(a, b) {
      const c = b.uuid || '',
        d = this.archivedDebugMessages,
        e = a.min_seq,
        f = a.max_seq,
        g = []
      if (e) {
        const a = d.findIndex(a => a.seq === e)
        if (0 <= a) {
          const b = f ? Math.min(d[d.length - 1].seq, f) : d[d.length - 1].seq
          for (let c = a; c < d.length; c++) {
            const a = d[c]
            if (!(a.seq <= b && a.seq >= e)) break
            else if (1 > g.length || g[g.length - 1].seq === a.seq + 1)
              g.push(a)
            else {
              s.w('archivedDebugMessages seq error', g[g.length - 1].seq, a.seq)
              continue
            }
          }
        }
      }
      const h = { base_response: { errcode: 0 }, debug_message: g }
      this.devtool &&
        this.devtool.receivedSeq &&
        (h.send_ack = this.devtool.receivedSeq),
        this.sendMessageToClient(h, p.ClientResponseType.SyncMessage, c)
    }
    onClientSendDebugMessageParallelly(a, b) {
      const c = a.debug_message
      if (c && !(1 > c.length)) {
        const d = c[0].seq,
          e = c[c.length - 1].seq,
          f = a.recv_ack
        if (f) {
          const a = this.archivedDebugMessages
          this.archivedDebugMessages = []
          for (const b of a) b.seq <= f || this.archivedDebugMessages.push(b)
        }
        const g = b.uuid || ''
        this.sendMessageToClient(
          { base_response: { errcode: 0 }, min_ack: d, max_ack: e },
          p.ClientResponseType.SendDebugMessageParallelly,
          g
        ),
          this.emit('debugmessages', c)
      }
    }
    async makeHttpRequest(a = {}) {
      const b = a.url || a.uri || p.RemoteHttpUrlHost
      s.f(
        `<HTTP REQUEST> ${b}, data = {${i.tryCatch(() => i.jsonStringify(a))}}`
      )
      let c
      delete a.uri, delete a.url
      try {
        c = await r(b, a)
      } catch (a) {
        return (
          s.e('<HTTP REQUEST FAIL> ' + b, a),
          {
            baseresponse: {
              errcode: p.KnownErrorCode.ERR_SYS,
              errmsg: 'http request error'
            }
          }
        )
      }
      if (!c || !c.body)
        throw (s.e('invalid remote request response', c),
        new Error('invalid response'))
      let d = c.body
      return (
        'string' == typeof d &&
          ((d = i.tryCatch(() => i.jsonParse(d))),
          i.invalidTryCatchResult(d) &&
            (s.e('invalid raw result body', c, b), (d = c.body))),
        s.i('http response result', b, a, d),
        (d.baseresponse = {
          errcode: parseInt(d.baseresponse.errcode, 10),
          errmsg: (d.baseresponse.errmsg || '') + ''
        }),
        d
      )
    }
    onErrorCode(a, b) {
      const c = {
        type: 'receivederrorcode',
        errorCode: a,
        errorMessage: p.KnownErrorCode[a],
        message: 'received error code ' + a,
        kind: 'error'
      }
      this.emit('event', c),
        p.KnownErrorCode.hasOwnProperty(a) &&
          (s.w('known error code', a), this.onKnownErrorCode(a, b))
    }
    async onKnownErrorCode(a, b) {
      switch (a) {
        case p.KnownErrorCode.USER_IN_DEBUGGING: {
          s.i('already in debugging'), await this.getRidOfRoom(), b && b()
          break
        }
        default:
      }
    }
    async getRidOfRoom() {
      const a = { uri: d(p.RequestType.QuitRoom) },
        b = await this.makeHttpRequest(a)
      s.i(b)
    }
    sendMessageToClient(a, b, c) {
      if (!this.client) return void s.w('client not valid for sending messages')
      s.f('<SEND CLIENT> type: ' + b + ', uuid: ' + c)
      const d = i.tryCatch(() => o.wrapClientResponseDataFormatToProto(a, b, c))
      return i.invalidTryCatchResult(d)
        ? void s.e('sending broken client response message', d.error.message)
        : void i.tryCatch(() => {
            this.client.send(d, { binary: !0 }, a => a && s.e(a)),
              (this.outBytesCount += d.byteLength || 0)
          })
    }
    destroy() {
      if (!(this.status <= v.Dead)) {
        if (
          (this.disconnectClient(101, 'destroy'),
          (this.devtool = null),
          this.cpws &&
            (i.tryCatch(() => this.cpws.close()), (this.cpws = null)),
          this.wss &&
            (this.wss.removeAllListeners(),
            i.tryCatch(() => this.wss.close()),
            (this.wss = null)),
          this.cp)
        ) {
          this.cp.removeAllListeners()
          try {
            this.cp.kill()
          } catch (a) {}
          this.cp = null
        }
        'android' === this.mode && n.kill().catch(a => s.w(a)),
          (this.archivedDebugMessages = []),
          (this.httpRequestQueue = []),
          (this.transTicket = ''),
          this.setStatus(v.Dead),
          this.emit('destroy')
      }
    }
  }
  e([t], w.prototype, 'setStatus', null),
    e([t], w.prototype, 'onCpError', null),
    e([t], w.prototype, 'initAdb', null),
    e([t], w.prototype, 'initCp', null),
    e([t], w.prototype, 'onWsConnection', null),
    e([t], w.prototype, 'onWssError', null),
    e([u], w.prototype, 'restart', null),
    e([t], w.prototype, 'onClientConnected', null),
    e([t], w.prototype, 'onDevtoolSet', null),
    e([t], w.prototype, 'onClientLogin', null),
    e([t], w.prototype, 'onClientJoinRoom', null),
    e([t], w.prototype, 'onClientQuitRoom', null),
    e([t], w.prototype, 'onClientSyncMessage', null),
    e([t], w.prototype, 'onClientSendDebugMessageParallelly', null),
    e([t], w.prototype, 'makeHttpRequest', null),
    e([t], w.prototype, 'onErrorCode', null),
    e([t], w.prototype, 'getRidOfRoom', null),
    (exports.DebugServer = w)
})(require('lazyload'), require)
