// File: /workspace/github_c_makefile_star2_O3/evanwire[P]GitClone/client.c
// Function: checkout
void checkout(char* project_name){
  DIR* dir = opendir(project_name);
  if(dir){
    printf("\nError: the project name you specified already exists on the client side.\n");
    return;
  }

  //Prepare message to server
  int i;
  char to_be_written[strlen(project_name) + 3];
  memset(to_be_written, 0, sizeof(to_be_written));
  to_be_written[0] = 'h';
  to_be_written[1] = ' ';
  int message_idx = 2;
  for(i = 0; i < strlen(project_name); i++){
    if(project_name[i]){
      to_be_written[message_idx] = project_name[i];
      message_idx++;
    }
  }
  printf("\nWritten to server: -%s- Size: %d passed in: -%s-\n", to_be_written, sizeof(to_be_written), project_name);

  //Connect to server, store the response
  char* response = connect_to_WTFserver(to_be_written);
  if(strcmp(response, "x") == 0){
    printf("\nError: the project you specified does not exist on the server.\n");
    return;
  }else if(strcmp(response, "e") == 0){
    printf("\nError: the server failed to open the project you specified. Please try again.\n");
    return;
  }

  //Prepare for tokenizing string and storing results
  char* token;
  char* saveptr = response;



  //Isolate the number of files
  token = strtok_r(saveptr, "$", &saveptr);
  int num_files = atoi(token);

  int* file_sizes = malloc(num_files * sizeof(int));
  int* file_name_sizes = malloc(num_files * sizeof(int));
  char** file_names = malloc(num_files * sizeof(char*));
  char** file_contents = malloc(num_files * sizeof(char*));

  int index = 0;

  //loop through the rest of the tokens
  while(token = strtok_r(saveptr, "$", &saveptr)){
    //for each token, take the specific pieces of information from each token
    char* inner_token;
    char* inner_saveptr = token;
    int data_type = 0;
    while(inner_token = strtok_r(inner_saveptr, "&", &inner_saveptr)){
      if(data_type == 0){
        file_name_sizes[index] = atoi(inner_token);
      }else if(data_type == 1){
        file_names[index] = malloc(file_name_sizes[index] * sizeof(char));
        strcpy(file_names[index], inner_token);
      }else if(data_type == 2){
        file_sizes[index] = atoi(inner_token);
      }else{
        file_contents[index] = malloc(file_sizes[index] * sizeof(char));
        strcpy(file_contents[index], inner_token);
      }
      data_type++;
    }
    index++;
  }

  //Tokenize each file name to open any necessary sub directories and create necessary files
  for(i = 0; i < num_files; i++){
    //To store the file path at a given moment
    char file_path_so_far[file_name_sizes[i]];

    //To tokenize the file path
    char* file_name_token;
    char* file_name_saveptr = file_names[i];

    //Get the current directory from path, add it to the path so far
    file_name_token = strtok_r(file_name_saveptr, "/", &file_name_saveptr);
    strcpy(file_path_so_far, file_name_token);


    //Loop through rest of file path, creating directories as needed
    while(file_name_token = strtok_r(file_name_saveptr, "/", &file_name_saveptr)){

      //if it has a '.' in it, it must not be a directory since we removed the current directory from the list of tokens already
      if(strchr(file_name_token, '.') != NULL){
        strcat(file_path_so_far, "/");
        strcat(file_path_so_far, file_name_token);
        int file_fd = open(file_path_so_far, O_WRONLY | O_TRUNC | O_CREAT, 0777);
        if(file_fd < 0){
          printf("\nError: was unable to create file %s. Will skip and continue replicating the rest of the project.\n");
        }else{
          int bytes_written = write(file_fd, file_contents[i], file_sizes[i]);
        }
        close(file_fd);
      //If its not a file, it must be a directory. Create it if the directory does not already exist, and add the directory's name to the current file path
      }else{
          strcat(file_path_so_far, "/");
          strcat(file_path_so_far, file_name_token);
          DIR* dir = opendir(project_name);
          if(!dir){
            int result = mkdir(file_path_so_far, 0777);
            if(result < 0){
              printf("\nError: could not create directory %s. Will skip continue replicating the rest of the project.\n");
            }
          }
          closedir(dir);
      }
    }

  }

  printf("\nStatus: Project %s has been cloned locally.\n", project_name);


  free(file_sizes);
  free(file_name_sizes);
  for(i = 0; i < num_files; i ++){
    free(file_names[i]);
    free(file_contents[i]);
  }
  free(file_names);
  free(file_contents);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rdi, %rbx
callq 0x11d0
testq %rax, %rax
je 0x19af
leaq 0x3e83(%rip), %rdi      # 0x581f
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x11e0
movq %rbx, %rdi
callq 0x10a0
movq %rbx, -0x58(%rbp)
movq %rax, %r15
movq %rsp, %r13
leaq 0x3(%rax), %rbx
movq %rsp, %r12
addq $0x12, %r15
andq $-0x10, %r15
movq %r12, %r14
subq %r15, %r14
movq %r14, %rsp
negq %r15
movq %r14, %rdi
xorl %esi, %esi
movq %rbx, %rdx
callq 0x10c0
movw $0x2068, (%r12,%r15)    # imm = 0x2068
movq -0x58(%rbp), %r15
movq %r15, %rdi
callq 0x10a0
testq %rax, %rax
je 0x1a22
movl $0x2, %ecx
xorl %edx, %edx
movb (%r15,%rdx), %sil
testb %sil, %sil
je 0x1a1a
movslq %ecx, %rcx
movb %sil, (%r14,%rcx)
incl %ecx
incq %rdx
cmpq %rdx, %rax
jne 0x1a08
leaq 0x3963(%rip), %rdi      # 0x538c
movq %r14, %rsi
movq %rbx, %rdx
movq %r15, %rcx
xorl %eax, %eax
callq 0x1040
movq %r14, %rdi
callq 0x41ca
movzbl (%rax), %ecx
cmpl $0x65, %ecx
je 0x1a60
cmpl $0x78, %ecx
jne 0x1a6a
cmpb $0x0, 0x1(%rax)
jne 0x1a6a
leaq 0x3fab(%rip), %rdi      # 0x5a06
jmp 0x1db3
cmpb $0x0, 0x1(%rax)
je 0x1dac
movq %r13, -0x70(%rbp)
leaq -0x68(%rbp), %rbx
movq %rax, (%rbx)
leaq 0x3a4e(%rip), %r14      # 0x54ca
movq %rax, %rdi
movq %r14, %rsi
movq %rbx, %rdx
callq 0x1240
movq %rax, %rdi
callq 0x1200
movl %eax, -0x44(%rbp)
movslq %eax, %r15
leaq (,%r15,4), %r13
movq %r13, %rdi
callq 0x1190
movq %rax, -0x40(%rbp)
movq %r13, %rdi
callq 0x1190
movq %rax, -0x38(%rbp)
shlq $0x3, %r15
movq %r15, %rdi
callq 0x1190
movq %rax, -0x50(%rbp)
movq %r15, %rdi
callq 0x1190
movq %rax, -0x60(%rbp)
movq (%rbx), %rdi
movq %r14, %rsi
movq %rbx, %rdx
callq 0x1240
testq %rax, %rax
je 0x1bb8
xorl %r15d, %r15d
leaq 0x39d7(%rip), %rbx      # 0x54cc
leaq -0x30(%rbp), %r14
movq %rax, -0x30(%rbp)
movq %rax, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x1240
testq %rax, %rax
je 0x1b98
movq %rax, %r13
xorl %r12d, %r12d
cmpl $0x2, %r12d
je 0x1b4c
cmpl $0x1, %r12d
je 0x1b39
testl %r12d, %r12d
jne 0x1b5e
movq %r13, %rdi
callq 0x1200
movq -0x38(%rbp), %rcx
jmp 0x1b58
movq -0x38(%rbp), %rax
movslq (%rax,%r15,4), %rdi
callq 0x1190
movq -0x50(%rbp), %rcx
jmp 0x1b6f
movq %r13, %rdi
callq 0x1200
movq -0x40(%rbp), %rcx
movl %eax, (%rcx,%r15,4)
jmp 0x1b7e
movq -0x40(%rbp), %rax
movslq (%rax,%r15,4), %rdi
callq 0x1190
movq -0x60(%rbp), %rcx
movq %rax, (%rcx,%r15,8)
movq %rax, %rdi
movq %r13, %rsi
callq 0x1150
incl %r12d
movq -0x30(%rbp), %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x1240
movq %rax, %r13
testq %rax, %rax
jne 0x1b1a
incq %r15
movq -0x68(%rbp), %rdi
leaq 0x3924(%rip), %rsi      # 0x54ca
leaq -0x68(%rbp), %rdx
callq 0x1240
testq %rax, %rax
jne 0x1af9
movl -0x44(%rbp), %eax
testl %eax, %eax
jle 0x1d6a
movl %eax, %r12d
leaq -0x30(%rbp), %rbx
xorl %r14d, %r14d
movq %r12, -0x78(%rbp)
movq %rsp, -0x80(%rbp)
movq -0x38(%rbp), %rax
movl (%rax,%r14,4), %eax
addq $0xf, %rax
andq $-0x10, %rax
movq %rsp, %r13
subq %rax, %r13
movq %r13, %rsp
movq -0x50(%rbp), %rax
movq (%rax,%r14,8), %rdi
movq %rdi, -0x30(%rbp)
leaq 0x39f4(%rip), %r15      # 0x55f5
movq %r15, %rsi
movq %rbx, %rdx
callq 0x1240
movq %r13, %rdi
movq %rax, %rsi
callq 0x1150
movq -0x30(%rbp), %rdi
movq %r15, %rsi
movq %rbx, %rdx
callq 0x1240
testq %rax, %rax
je 0x1d06
movq %rax, %r15
movq %r15, %rdi
movl $0x2e, %esi
callq 0x1090
movq %rax, %r12
movq %r13, %rdi
callq 0x10a0
movw $0x2f, (%r13,%rax)
movq %r13, %rdi
movq %r15, %rsi
callq 0x1230
testq %r12, %r12
je 0x1c97
movq %r13, %rdi
movl $0x241, %esi            # imm = 0x241
movl $0x1ff, %edx            # imm = 0x1FF
xorl %eax, %eax
callq 0x10f0
movl %eax, %r15d
testl %eax, %eax
js 0x1cd1
movq -0x60(%rbp), %rax
movq (%rax,%r14,8), %rsi
movq -0x40(%rbp), %rax
movslq (%rax,%r14,4), %rdx
movl %r15d, %edi
callq 0x1080
jmp 0x1cdf
movq -0x58(%rbp), %rdi
callq 0x11d0
movq %rax, %r15
testq %rax, %rax
jne 0x1cc7
movq %r13, %rdi
movl $0x1ff, %esi            # imm = 0x1FF
callq 0x10b0
testl %eax, %eax
jns 0x1cc7
leaq 0x3871(%rip), %rdi      # 0x5531
xorl %eax, %eax
callq 0x1040
movq %r15, %rdi
callq 0x1210
jmp 0x1ce7
leaq 0x37f6(%rip), %rdi      # 0x54ce
xorl %eax, %eax
callq 0x1040
movl %r15d, %edi
callq 0x1250
movq -0x30(%rbp), %rdi
leaq 0x3903(%rip), %rsi      # 0x55f5
movq %rbx, %rdx
callq 0x1240
movq %rax, %r15
testq %rax, %rax
jne 0x1c32
movq -0x80(%rbp), %rsp
incq %r14
movq -0x78(%rbp), %r12
cmpq %r12, %r14
jne 0x1bd1
leaq 0x3870(%rip), %rdi      # 0x5591
movq -0x58(%rbp), %rsi
xorl %eax, %eax
callq 0x1040
movq -0x40(%rbp), %rdi
callq 0x1170
movq -0x38(%rbp), %rdi
callq 0x1170
cmpl $0x0, -0x44(%rbp)
movq -0x50(%rbp), %r14
movq -0x60(%rbp), %r15
jle 0x1d96
xorl %ebx, %ebx
movq (%r14,%rbx,8), %rdi
callq 0x1170
movq (%r15,%rbx,8), %rdi
callq 0x1170
incq %rbx
cmpq %rbx, %r12
jne 0x1d4e
jmp 0x1d96
leaq 0x3820(%rip), %rdi      # 0x5591
movq -0x58(%rbp), %rsi
xorl %eax, %eax
callq 0x1040
movq -0x40(%rbp), %rdi
callq 0x1170
movq -0x38(%rbp), %rdi
callq 0x1170
movq -0x50(%rbp), %r14
movq -0x60(%rbp), %r15
movq %r14, %rdi
callq 0x1170
movq %r15, %rdi
callq 0x1170
movq -0x70(%rbp), %r13
jmp 0x1db8
leaq 0x3c04(%rip), %rdi      # 0x59b7
callq 0x11e0
movq %r13, %rsp
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq