// File: ChristalC[P]Online-Outlier-Detection/thread_org.cpp
// Function: socket_thread_func(void*)
void* socket_thread_func(void* argv) {
  Socket_arg* sa = (Socket_arg*)argv;
  const char* host = sa->h;
  const char* port = sa->p;

  // Get ready for connecting to server
  int sockfd, numbytes;
  struct addrinfo hints, *servinfo, *p;
  int rv;

  hints = {};
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;

  if ((rv = getaddrinfo(host, port, &hints, &servinfo)) != 0) {
    cout << "Error: getaddrinfor: " << gai_strerror(rv) << endl;
    exit(1);
  }

  for (p = servinfo; p != NULL; p = p->ai_next) {
    if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
      cout << "socket error\n";
      continue;
    }

    if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
      close(sockfd);
      cout << "ai_addr = " << p->ai_addr << endl;
      cout << "client: connect error\n";
      continue;
    }

    break;
  }

  if (p == NULL) {
    cout << "Failed to connect\n";
    exit(2);
  }

  freeaddrinfo(servinfo);

  char recv_buffer[MAX_BUF_LENGTH];
  char buffer[MAX_BUF_LENGTH];
  string recv_str;
  string data_str;
  int buffer_start = 0;
  char* recv_start_pos = recv_buffer;
  char* recv_newline_pos;
  char* recv_end_pos;
  char* buffer_start_pos = buffer;
  char* buffer_end_pos;
  while ((numbytes = recv(sockfd, recv_buffer, MAX_BUF_LENGTH - 1, 0)) > 1) {
    recv_end_pos = recv_buffer + numbytes;
    *recv_end_pos = '\0';

    // Find '\n' in recv_buffer
    recv_start_pos = recv_buffer;
    recv_newline_pos = strchr(recv_buffer, '\n');
    while (recv_newline_pos != NULL) {
      strncpy(buffer_start_pos, recv_start_pos, recv_newline_pos - recv_start_pos);
      buffer_end_pos = buffer_start_pos + (recv_newline_pos - recv_start_pos);
      *buffer_end_pos = '\0';
      data_str = buffer;
      
      // Split data_str into a vector of doubles, push the vector to shared_data list
      vector<double> read_point = splitCsv(data_str);
      if (read_point.size() == 0) {
        cout << "read invalid point! End the program!" << endl;
        exit(1);
      }
      pthread_mutex_lock(&lock);
      shared_data.push_back(read_point);
      pthread_mutex_unlock(&lock);

      // Signal the has_new condition
      pthread_cond_signal(&has_new);

      buffer_start_pos = buffer;
      recv_start_pos = recv_newline_pos + 1;

      // If the previous found recv_newline_pos is already the last char of recv_buffer
      // Jump out of the loop
      if (recv_start_pos == recv_end_pos) {
        break;
      }
      recv_newline_pos = strchr(recv_start_pos, '\n');
    }
    if (recv_start_pos == recv_end_pos) {
      continue;
    }
    strcpy(buffer_start_pos, recv_start_pos);
    buffer_start_pos = strchr(buffer, '\0');
  }
  if (numbytes == -1) {
    cout << "recv error\n";
    exit(1);
  }
  if (numbytes == 0) {
    pthread_mutex_lock(&lock);
    shared_data.push_back({{-1}});
    pthread_mutex_unlock(&lock);
    pthread_cond_signal(&has_new);
  }

  close(sockfd);
  return NULL;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x9a0, %rsp            # imm = 0x9A0
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x20(%rbp)
leaq -0xa0(%rbp), %rdi
xorl %esi, %esi
movl $0x30, %edx
callq 0x3140
leaq -0x58(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
movl $0x30, %edx
callq 0x3220
movl $0x0, -0x54(%rbp)
movl $0x1, -0x50(%rbp)
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
leaq -0x58(%rbp), %rdx
leaq -0x60(%rbp), %rcx
callq 0x3320
movl %eax, -0x6c(%rbp)
cmpl $0x0, %eax
je 0xb0db
movq 0x8f30(%rip), %rdi      # 0x13fc8
leaq 0x2105(%rip), %rsi      # 0xd1a4
callq 0x3280
movq %rax, -0x980(%rbp)
movl -0x6c(%rbp), %edi
callq 0x3380
movq -0x980(%rbp), %rdi
movq %rax, %rsi
callq 0x3280
movq %rax, %rdi
movq 0x8ee4(%rip), %rsi      # 0x13fb0
callq 0x32d0
movl $0x1, %edi
callq 0x3300
movq -0x60(%rbp), %rax
movq %rax, -0x68(%rbp)
cmpq $0x0, -0x68(%rbp)
je 0xb1a3
movq -0x68(%rbp), %rax
movl 0x4(%rax), %edi
movq -0x68(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x68(%rbp), %rax
movl 0xc(%rax), %edx
callq 0x3090
movl %eax, -0x24(%rbp)
cmpl $-0x1, %eax
jne 0xb125
movq 0x8eb1(%rip), %rdi      # 0x13fc8
leaq 0x209c(%rip), %rsi      # 0xd1ba
callq 0x3280
jmp 0xb192
movl -0x24(%rbp), %edi
movq -0x68(%rbp), %rax
movq 0x18(%rax), %rsi
movq -0x68(%rbp), %rax
movl 0x10(%rax), %edx
callq 0x3230
cmpl $-0x1, %eax
jne 0xb190
movl -0x24(%rbp), %edi
callq 0x34a0
movq 0x8e78(%rip), %rdi      # 0x13fc8
leaq 0x2071(%rip), %rsi      # 0xd1c8
callq 0x3280
movq %rax, %rdi
movq -0x68(%rbp), %rax
movq 0x18(%rax), %rsi
callq 0x3200
movq %rax, %rdi
movq 0x8e3a(%rip), %rsi      # 0x13fb0
callq 0x32d0
movq 0x8e46(%rip), %rdi      # 0x13fc8
leaq 0x204a(%rip), %rsi      # 0xd1d3
callq 0x3280
jmp 0xb192
jmp 0xb1a3
movq -0x68(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x68(%rbp)
jmp 0xb0e3
cmpq $0x0, -0x68(%rbp)
jne 0xb1c7
movq 0x8e17(%rip), %rdi      # 0x13fc8
leaq 0x2032(%rip), %rsi      # 0xd1ea
callq 0x3280
movl $0x2, %edi
callq 0x3300
movq -0x60(%rbp), %rdi
callq 0x3350
leaq -0x8a0(%rbp), %rdi
callq 0x3370
leaq -0x8c0(%rbp), %rdi
callq 0x3370
movl $0x0, -0x8c4(%rbp)
leaq -0x490(%rbp), %rax
movq %rax, -0x8d0(%rbp)
leaq -0x880(%rbp), %rax
movq %rax, -0x8e8(%rbp)
movl -0x24(%rbp), %edi
leaq -0x490(%rbp), %rsi
movl $0x3e7, %edx            # imm = 0x3E7
xorl %ecx, %ecx
callq 0x30b0
movq %rax, -0x988(%rbp)
jmp 0xb22d
movq -0x988(%rbp), %rax
movl %eax, -0x28(%rbp)
cmpl $0x1, %eax
jle 0xb4cd
leaq -0x490(%rbp), %rax
movslq -0x28(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x8e0(%rbp)
movq -0x8e0(%rbp), %rax
movb $0x0, (%rax)
leaq -0x490(%rbp), %rax
movq %rax, -0x8d0(%rbp)
leaq -0x490(%rbp), %rdi
movl $0xa, %esi
callq 0x30d0
movq %rax, -0x8d8(%rbp)
cmpq $0x0, -0x8d8(%rbp)
je 0xb48b
movq -0x8e8(%rbp), %rdi
movq -0x8d0(%rbp), %rsi
movq -0x8d8(%rbp), %rdx
subq %rsi, %rdx
callq 0x3120
movq -0x8e8(%rbp), %rax
movq -0x8d8(%rbp), %rcx
movq -0x8d0(%rbp), %rdx
subq %rdx, %rcx
addq %rcx, %rax
movq %rax, -0x8f0(%rbp)
movq -0x8f0(%rbp), %rax
movb $0x0, (%rax)
leaq -0x8c0(%rbp), %rdi
leaq -0x880(%rbp), %rsi
callq 0x3360
jmp 0xb2f1
leaq -0x938(%rbp), %rdi
leaq -0x8c0(%rbp), %rsi
callq 0x3100
jmp 0xb306
leaq -0x918(%rbp), %rdi
leaq -0x938(%rbp), %rsi
callq 0x9130
jmp 0xb31b
leaq -0x938(%rbp), %rdi
callq 0x31a0
leaq -0x918(%rbp), %rdi
callq 0x3f60
cmpq $0x0, %rax
jne 0xb3d5
movq 0x8c84(%rip), %rdi      # 0x13fc8
leaq 0x1eb2(%rip), %rsi      # 0xd1fd
callq 0x3280
movq %rax, -0x990(%rbp)
jmp 0xb359
movq -0x990(%rbp), %rdi
movq 0x8c49(%rip), %rsi      # 0x13fb0
callq 0x32d0
jmp 0xb36e
movl $0x1, %edi
callq 0x3300
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x8f8(%rbp)
movl %eax, -0x8fc(%rbp)
jmp 0xb626
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x8f8(%rbp)
movl %eax, -0x8fc(%rbp)
leaq -0x938(%rbp), %rdi
callq 0x31a0
jmp 0xb626
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x8f8(%rbp)
movl %eax, -0x8fc(%rbp)
leaq -0x918(%rbp), %rdi
callq 0x3fa0
jmp 0xb626
leaq 0x8edc(%rip), %rdi      # 0x142b8
callq 0x33b0
leaq 0x8ef8(%rip), %rdi      # 0x142e0
leaq -0x918(%rbp), %rsi
callq 0xb890
jmp 0xb3f6
leaq 0x8ebb(%rip), %rdi      # 0x142b8
callq 0x31e0
leaq 0x8e7f(%rip), %rdi      # 0x14288
callq 0x3030
leaq -0x880(%rbp), %rax
movq %rax, -0x8e8(%rbp)
movq -0x8d8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x8d0(%rbp)
movq -0x8d0(%rbp), %rax
cmpq -0x8e0(%rbp), %rax
jne 0xb44a
movl $0x8, -0x93c(%rbp)
jmp 0xb46c
movq -0x8d0(%rbp), %rdi
movl $0xa, %esi
callq 0x30d0
movq %rax, -0x8d8(%rbp)
movl $0x0, -0x93c(%rbp)
leaq -0x918(%rbp), %rdi
callq 0x3fa0
movl -0x93c(%rbp), %eax
testl %eax, %eax
je 0xb486
jmp 0xb484
jmp 0xb48b
jmp 0xb285
movq -0x8d0(%rbp), %rax
cmpq -0x8e0(%rbp), %rax
jne 0xb4a0
jmp 0xb20e
movq -0x8e8(%rbp), %rdi
movq -0x8d0(%rbp), %rsi
callq 0x3260
leaq -0x880(%rbp), %rdi
xorl %esi, %esi
callq 0x30d0
movq %rax, -0x8e8(%rbp)
jmp 0xb20e
cmpl $-0x1, -0x28(%rbp)
jne 0xb4f2
movq 0x8aee(%rip), %rdi      # 0x13fc8
leaq 0x1d41(%rip), %rsi      # 0xd222
callq 0x3280
jmp 0xb4e8
movl $0x1, %edi
callq 0x3300
cmpl $0x0, -0x28(%rbp)
jne 0xb5ef
leaq 0x8db5(%rip), %rdi      # 0x142b8
callq 0x33b0
movabsq $-0x4010000000000000, %rax # imm = 0xBFF0000000000000
movq %rax, -0x970(%rbp)
leaq -0x970(%rbp), %rax
movq %rax, -0x968(%rbp)
movq $0x1, -0x960(%rbp)
leaq -0x971(%rbp), %rdi
movq %rdi, -0x998(%rbp)
callq 0x42e0
movq -0x998(%rbp), %rcx
movq -0x968(%rbp), %rsi
movq -0x960(%rbp), %rdx
leaq -0x958(%rbp), %rdi
callq 0xb910
jmp 0xb568
leaq 0x8d71(%rip), %rdi      # 0x142e0
leaq -0x958(%rbp), %rsi
callq 0xb8d0
jmp 0xb57d
leaq -0x958(%rbp), %rdi
callq 0x3fa0
leaq -0x971(%rbp), %rdi
callq 0x49f0
leaq 0x8d1c(%rip), %rdi      # 0x142b8
callq 0x31e0
leaq 0x8ce0(%rip), %rdi      # 0x14288
callq 0x3030
jmp 0xb5ef
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x8f8(%rbp)
movl %eax, -0x8fc(%rbp)
jmp 0xb5e1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x8f8(%rbp)
movl %eax, -0x8fc(%rbp)
leaq -0x958(%rbp), %rdi
callq 0x3fa0
leaq -0x971(%rbp), %rdi
callq 0x49f0
jmp 0xb626
movl -0x24(%rbp), %edi
callq 0x34a0
jmp 0xb5f9
movl $0x1, -0x93c(%rbp)
leaq -0x8c0(%rbp), %rdi
callq 0x31a0
leaq -0x8a0(%rbp), %rdi
callq 0x31a0
xorl %eax, %eax
addq $0x9a0, %rsp            # imm = 0x9A0
popq %rbp
retq
leaq -0x8c0(%rbp), %rdi
callq 0x31a0
leaq -0x8a0(%rbp), %rdi
callq 0x31a0
movq -0x8f8(%rbp), %rdi
callq 0x3450
nopw (%rax,%rax)