// File: /workspace/github_cpp_makefile_star2_O3/king1600[P]cordpp/src/gateway.cc
// Function: cordpp::Gateway::connect()
void Gateway::connect() {
  // reset heartbeat data on connection
  conn->on_connect([this](const Error &err) {
    beat.cancel();
    heartbeat_acked = false;
    heartbeat_interval = 0;

    // log connection
    std::cout << "[cordpp] Gateway Connected!" << std::endl;
  });

  // reconnect with optional delay if set
  conn->on_close([this](const WebsockCloseData &data) {
    
    // display closing information
    std::cerr << "[cordpp] Close Received -> "
      << "Code: " << data.code << " Reason: " << 
      (DisconnectCodes.find(data.code) != DisconnectCodes.end()
        ? DisconnectCodes[data.code] : data.reason) << std::endl;

    // reconnect with optional delay
    beat.cancel();
    if (resume_delay > 0) {
      beat.expires_from_now(boost::posix_time::millisec(resume_delay));
      resume_delay = 0;
      beat.async_wait([this](const Error &err) {
        if (!err) reset();
      });

    // reconnect immediately
    } else {
      reset();
    }
  });

  // handle incoming messages
  conn->on_message([this](const char *raw, const size_t raw_len) {
    // check if message data is valid json
    std::string raw_data(raw, raw_len);
    if (raw_data.front() != '{' || raw_data.back() != '}') {
      conn->close(4002, "Invalid payload sent");

    // convert message to json and decide what to do with it
    } else {
      Json data = Json::parse(raw_data);
      if (data.find("s") != data.end() && !data["s"].is_null())
        sequence = data["s"].get<uint64_t>();

      // debug log
      std::cout << data.dump(2) << std::endl;
      
      // choose action using the opcode from the packet
      switch (data["op"].get<GatewayOp>()) {
        case GatewayOp::Hello:
          heartbeat_acked = true;
          heartbeat_interval = data["d"]["heartbeat_interval"];
          heartbeat_interval -= 100; // room for error
          beat.expires_from_now(boost::posix_time::millisec(heartbeat_interval));
          beat.async_wait([this](const Error &err) { if (!err) heartbeat(); });
          identify();
          break;

        case GatewayOp::Dispatch:
          dispatch(data["t"], data["d"]);
          break;

        case GatewayOp::HeartbeatAck:
          std::cout << "[cordpp] Heartbeat Ack!" << std::endl;
          heartbeat_acked = true;
          break;

        case GatewayOp::Reconnect:
          is_resume = true;
          conn->close();
          break;

        case GatewayOp::RequestGuildMembers:
          break;

        case GatewayOp::VoiceStateUpdate:
          break;

        case GatewayOp::InvalidSession:
          is_resume = data["d"].get<bool>();
          resume_delay = 4000;
          conn->close();
          break;

        default: break;
      }
    }
  });

  // start connection
  conn->connect(host_url);
}

// Assembly:
pushq %rbx
subq $0x20, %rsp
movq %rdi, %rbx
movl $0x308, %edi            # imm = 0x308
addq 0x30(%rbx), %rdi
movq %rsp, %rsi
movq $0x0, 0x8(%rsi)
movq %rbx, (%rsi)
leaq 0x2422(%rip), %rax      # 0x12f9a
movq %rax, 0x18(%rsi)
leaq 0x249b(%rip), %rax      # 0x1301e
movq %rax, 0x10(%rsi)
callq 0x153e2
movq 0x10(%rsp), %rax
testq %rax, %rax
je 0x10ba3
movq %rsp, %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
movl $0x328, %edi            # imm = 0x328
addq 0x30(%rbx), %rdi
movq %rsp, %rsi
movq $0x0, 0x8(%rsi)
movq %rbx, (%rsi)
leaq 0x2483(%rip), %rax      # 0x13044
movq %rax, 0x18(%rsi)
leaq 0x26da(%rip), %rax      # 0x132a6
movq %rax, 0x10(%rsi)
callq 0x154a6
movq 0x10(%rsp), %rax
testq %rax, %rax
je 0x10bec
movq %rsp, %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
movl $0x2e8, %edi            # imm = 0x2E8
addq 0x30(%rbx), %rdi
movq %rsp, %rsi
movq $0x0, 0x8(%rsi)
movq %rbx, (%rsi)
leaq 0x2a00(%rip), %rax      # 0x1360a
movq %rax, 0x18(%rsi)
leaq 0x301f(%rip), %rax      # 0x13c34
movq %rax, 0x10(%rsi)
callq 0x1556a
movq 0x10(%rsp), %rax
testq %rax, %rax
je 0x10c35
movq %rsp, %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
movq 0x30(%rbx), %rdi
addq $0x10, %rbx
movq %rbx, %rsi
callq 0x38c7c
addq $0x20, %rsp
popq %rbx
retq
jmp 0x10caf
jmp 0x10caf
jmp 0x10caf
movq %rax, %rbx
movq 0x10(%rsp), %rax
testq %rax, %rax
je 0x10ca7
movq %rsp, %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
jmp 0x10ca7
jmp 0x10caf
movq %rax, %rbx
movq 0x10(%rsp), %rax
testq %rax, %rax
je 0x10ca7
movq %rsp, %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
jmp 0x10ca7
jmp 0x10caf
movq %rax, %rbx
movq 0x10(%rsp), %rax
testq %rax, %rax
je 0x10ca7
movq %rsp, %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
movq %rbx, %rdi
callq 0xaa30
movq %rax, %rdi
callq 0xd3a3
nop