// File: /workspace/github_c_makefile_star2_O3/evanwire[P]GitClone/client.c
// Function: update
void update(char* projectName){
  //Prepare message to server
  int i;
  char to_be_written[strlen(projectName) + 3];
  memset(to_be_written, 0, sizeof(to_be_written));
  to_be_written[0] = 'u';
  to_be_written[1] = ' ';
  int message_idx = 2;
  for(i = 0; i < strlen(projectName); i++){
    if(projectName[i]){
      to_be_written[message_idx] = projectName[i];
      message_idx++;
    }
  }
  printf("\nWritten to server: -%s- Size: %d passed in: -%s-\n", to_be_written, sizeof(to_be_written), projectName);

  //Connect to server, store the response
  char* response = connect_to_WTFserver(to_be_written);

  //Report if server responded with an error
  if(strcmp(response, "x") == 0){
    printf("\nError: That project already exists. You can download the current version of the project that is on the server with the checkout command.\n");
    exit(1);
  }else if(strcmp(response, "e") == 0){
    printf("\nError: The server ran into an error processing your request. Please try again.\n");
    exit(1);
  }
  
  //Verify the project exists on the client side
  DIR* dir = opendir(projectName);
  if(!dir){
    printf("\nError: the project you specified does not seem to exist on the client side. Please create the project before running again.\n");
    exit(1);
  }
  closedir(dir);

  char manifest_path[sizeof(projectName) + 10];
  strcpy(manifest_path, projectName);
  strcat(manifest_path, "/.Manifest");



  //Read client manifest contents to a single char*
  char* clientManifest = readFile(manifest_path);


  
  //initialize for tokenizing clientMan and serverMan by line
  char* clientToken;
  char* serverToken;
  char* serverSaveptr=malloc(strlen(response));
  char* clientSaveptr = malloc(strlen(clientManifest));
  strcpy(serverSaveptr,response);
  strcpy(clientSaveptr,clientManifest);

  //helper variables for comparisons
  //REMEMBER TO FREE UPDATE FILE PATH, CONFLICT FILE PATH, AND COMMAND AS NEEDED
  int update_fd;
  int conflict_fd;
  char* updateFilePath=(char*)malloc(strlen(projectName) + 8);
  strcpy(updateFilePath, projectName);
  strcat(updateFilePath, "/.Update");
  char* conflictFilePath=(char*)malloc(strlen(projectName) + 10);
  strcpy(conflictFilePath, projectName);
  strcat(conflictFilePath, "/.Conflict");
  clientToken=strtok_r(clientSaveptr,"\n",&clientSaveptr);
  serverToken=strtok_r(serverSaveptr,"\n",&serverSaveptr);
  char* command=(char*)malloc(strlen(projectName)+strlen(conflictFilePath)+30);

  //FULL SUCCESS CASE
  //check to see if client and server manifests are same version numbers
  //if so the client is up to date and .update can be empty.
  //create new update and remove old one
  strcpy(command,"rm -rf ");
  strcat(command,updateFilePath);
  system(command);
  command=(char*)malloc(sizeof(projectName)+sizeof(conflictFilePath)+30);
  strcpy(command,"rm -rf ");
  strcat(command,conflictFilePath);
  system(command);
  update_fd = open(updateFilePath, O_WRONLY | O_CREAT, 0777);
  if(strcmp(clientToken,serverToken)==0){
    //remove .Conflict

    printf("Up To Date\n");
    free(updateFilePath);
    free(conflictFilePath);
    close(update_fd);
    return;

  }
  char* serverManCopy=(char*)malloc(strlen(response)+1);
  strcpy(serverManCopy,response);
  char* serverSaveptr2;
  int bytes_written;
  char* serverLineCopy=(char*)malloc(strlen(response));

  //create loop to tokenize server and check for files the client needs to download
  //skip project version line
  serverToken=strtok_r(serverManCopy,"\n",&serverSaveptr2);
  while(serverToken=strtok_r(NULL,"\n",&serverSaveptr2)){
    char* innerServerSaveptr;
    char* innerServerToken;
    strcpy(serverLineCopy,serverToken);
    innerServerToken=strtok_r(serverLineCopy,"~",&innerServerSaveptr);
    //Server file name should be in innerServerToken
    //if it isn't in client manifest, client will be notifed to download
    //in .Update. Else, we continue
    if(strstr(clientManifest,innerServerToken)==NULL){
      strcpy(command,"A");
      strcat(command,serverToken);
      strcat(command,"\n");
      bytes_written = write(update_fd, command, strlen(command));
      if(bytes_written < 0){
        printf("\nError: was unable to edit .Update. Will attempt to write the original information back into it.\n");
        exit(1);
      }
      printf(command);
    }

  }

  //now we must loop through and see if the client has files that the server got rid of
  char* clientManCopy=(char*)malloc(strlen(clientManifest)+1);
  strcpy(clientManCopy,clientManifest);
  char* clientSaveptr2;
  char* clientLineCopy=(char*)malloc(strlen(response));
  
  //skip project version line
  clientToken=strtok_r(clientManCopy,"\n",&clientSaveptr2);
  while(clientToken=strtok_r(NULL,"\n",&clientSaveptr2)){
    char* innerClientSaveptr;
    char* innerClientToken;
    strcpy(clientLineCopy,clientToken);
    innerClientToken=strtok_r(clientLineCopy,"~",&innerClientSaveptr);
    //Server file name should be in innerServerToken
    //if it isn't in client manifest, client will be notifed to download
    //in .Update. Else, we continue
    if(strstr(response,innerClientToken)==NULL){
      strcpy(command,"D");
      strcat(command,clientToken);
      strcat(command,"\n");
      bytes_written = write(update_fd, command, strlen(command));
      if(bytes_written < 0){
        printf("\nError: was unable to edit .Update. Will attempt to write the original information back into it.\n");
        exit(1);
      }
      printf(command);
    }

  }



  //loop for conflict and modify
  strcpy(serverManCopy,response);
  char* serverSaveptr3;
  char* innerClientToken3;
  char* innerServerToken3;
  char* filePath=(char*)malloc(strlen(clientManifest));
  char* liveHash=(char*)malloc(strlen(clientManifest));


  
  serverToken=strtok_r(serverManCopy,"\n",&serverSaveptr3);
  //for every file in server
  while(serverToken=strtok_r(NULL,"\n",&serverSaveptr3)){

    strcpy(clientManCopy,clientManifest);
    char* clientSaveptr3;
    clientToken =strtok_r(clientManCopy,"\n", &clientSaveptr3);

    //for every file in client
    while (clientToken=strtok_r(NULL,"\n", &clientSaveptr3)){
      char* innerServerSaveptr3;
      char* innerClientSaveptr3;
      //tokenize file names for each
      strcpy(clientLineCopy,clientToken);
      strcpy(serverLineCopy,serverToken);
      innerClientToken3=strtok_r(clientLineCopy,"~",&innerClientSaveptr3);
      innerServerToken3=strtok_r(serverLineCopy,"~",&innerServerSaveptr3);
      strcpy(filePath,innerClientToken3);



      //if the files have the same name we got some comparisons to make
      if(strcmp(innerClientToken3,innerServerToken3)==0){
        //now we check if the version numbers are the different
        innerClientToken3=strtok_r(NULL,"~",&innerClientSaveptr3);
        innerServerToken3=strtok_r(NULL,"~",&innerServerSaveptr3);

        //if they are different we must compare the live hash of the file
        //to the hash in the client manifest. If they are the same
        //its a modify. if they are different its a conflict
        if(strcmp(innerServerToken3,innerClientToken3)!=0){
          innerClientToken3=strtok_r(NULL,"~",&innerClientSaveptr3);
          char* fileContents=readFile(filePath);
          //innerClientToken3=strtok_r(NULL,"\n",&innerClientSaveptr3);

          char* fileHash=hashIt(fileContents);
          strcpy(liveHash,"H:");
          strcat(liveHash,fileHash);

          //if fileHashes are the same all it's a modify
          if(strcmp(liveHash,innerClientToken3)==0){
            strcpy(command,"M");
            strcat(command,serverToken);
            strcat(command,"\n");
            bytes_written = write(update_fd, command, strlen(command));
            if(bytes_written < 0){
              printf("\nError: was unable to edit .Update. Will attempt to write the original information back into it.\n");
              exit(1);
            }
            printf(command);
          }

          //else it's a conflict
          else{
            conflict_fd=open(conflictFilePath,O_WRONLY|O_CREAT|O_APPEND,0777);
            strcpy(command,"C");
            strcat(command,serverToken);
            strcat(command,"\n");
            bytes_written = write(conflict_fd, command, strlen(command));
            if(bytes_written < 0){
              printf("\nError: was unable to edit .Conflict. Will attempt to write the original information back into it.\n");
              exit(1);
            }
            printf(command);
            close(conflict_fd);
          }
          
          
        }

      }


    }
    
  }
  free(clientManCopy);
  free(serverManCopy);
  free(clientLineCopy);
  free(serverLineCopy);
  free(filePath);
  free(liveHash);
  free(conflictFilePath);
  free(updateFilePath);
  close(update_fd);
  return;
  
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xb8, %rsp
movq %rdi, %rbx
callq 0x10a0
movq %rax, %r12
leaq 0x3(%rax), %rdx
movq %rsp, %r13
leaq 0x12(%rax), %r14
andq $-0x10, %r14
movq %r13, %r15
subq %r14, %r15
movq %r15, %rsp
negq %r14
movq %r15, %rdi
xorl %esi, %esi
movq %rdx, -0x30(%rbp)
callq 0x10c0
movw $0x2075, (%r13,%r14)    # imm = 0x2075
testq %r12, %r12
je 0x1e3d
movl $0x2, %eax
xorl %ecx, %ecx
movb (%rbx,%rcx), %dl
testb %dl, %dl
je 0x1e35
cltq
movb %dl, (%r15,%rax)
incl %eax
incq %rcx
cmpq %rcx, %r12
jne 0x1e26
leaq 0x3548(%rip), %rdi      # 0x538c
movq %r15, %rsi
movq -0x30(%rbp), %rdx
movq %rbx, %rcx
xorl %eax, %eax
callq 0x1040
movq %r15, %rdi
callq 0x41ca
movzbl (%rax), %ecx
cmpl $0x65, %ecx
je 0x1e7c
cmpl $0x78, %ecx
jne 0x1e86
cmpb $0x0, 0x1(%rax)
jne 0x1e86
leaq 0x3fb7(%rip), %rdi      # 0x5e2e
jmp 0x25c8
cmpb $0x0, 0x1(%rax)
je 0x25e0
movq %rax, -0x30(%rbp)
movq %rbx, %rdi
callq 0x11d0
testq %rax, %rax
je 0x25d7
movq %rax, %rdi
callq 0x1210
leaq -0xe0(%rbp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1150
movq %r14, %rdi
callq 0x10a0
movabsq $0x6566696e614d2e2f, %rcx # imm = 0x6566696E614D2E2F
movq %rcx, -0xe0(%rbp,%rax)
movl $0x747365, -0xd9(%rbp,%rax) # imm = 0x747365
movq %r14, %rdi
callq 0x4387
movq %rax, %r15
movq -0x30(%rbp), %r14
movq %r14, %rdi
callq 0x10a0
movq %rax, %rdi
callq 0x1190
movq %rax, %r13
leaq -0xc0(%rbp), %rax
movq %r13, (%rax)
movq %r15, %rdi
callq 0x10a0
movq %rax, %rdi
callq 0x1190
movq %rax, %r12
leaq -0xb8(%rbp), %rax
movq %r12, (%rax)
movq %r13, %rdi
movq %r14, %rsi
callq 0x1150
movq %r12, %rdi
movq %r15, -0x48(%rbp)
movq %r15, %rsi
callq 0x1150
movq %rbx, %rdi
callq 0x10a0
movq %rax, %r13
leaq 0x8(%rax), %rdi
callq 0x1190
movq %rax, %r15
movq %rax, %rdi
movq %rbx, %rsi
callq 0x1150
movq %r15, %rdi
callq 0x10a0
movabsq $0x6574616470552e2f, %rcx # imm = 0x6574616470552E2F
movq %rcx, (%r15,%rax)
movb $0x0, 0x8(%r15,%rax)
addq $0xa, %r13
movq %r13, %rdi
callq 0x1190
movq %rax, %r14
movq %rax, %rdi
movq %rbx, %rsi
callq 0x1150
movq %r14, %rdi
callq 0x10a0
movabsq $0x696c666e6f432e2f, %rcx # imm = 0x696C666E6F432E2F
movq %rcx, (%r14,%rax)
movl $0x746369, 0x7(%r14,%rax) # imm = 0x746369
leaq 0x3703(%rip), %r13      # 0x56be
movq %r12, %rdi
movq %r13, %rsi
leaq -0xb8(%rbp), %rdx
callq 0x1240
movq %rax, -0x40(%rbp)
leaq -0xc0(%rbp), %rdx
movq (%rdx), %rdi
movq %r13, %rsi
callq 0x1240
movq %rax, %r13
movq %rbx, %rdi
callq 0x10a0
movq %rax, %rbx
movq %r14, %rdi
callq 0x10a0
leaq (%rbx,%rax), %rdi
addq $0x1e, %rdi
callq 0x1190
movq %rax, %rbx
movabsq $0x2066722d206d72, %r12 # imm = 0x2066722D206D72
movq %r12, (%rax)
movq %rax, %rdi
movq %r15, %rsi
callq 0x1230
movq %rbx, %rdi
callq 0x1130
movl $0x2e, %edi
callq 0x1190
movq %rax, %rbx
movq %r12, (%rax)
movq %rax, %rdi
movq %r14, %rsi
callq 0x1230
movq %rbx, -0x50(%rbp)
movq %rbx, %rdi
callq 0x1130
movq %r15, %rdi
movl $0x41, %esi
movl $0x1ff, %edx            # imm = 0x1FF
xorl %eax, %eax
callq 0x10f0
movl %eax, %ebx
movq -0x40(%rbp), %rdi
movq %r13, %rsi
callq 0x11b0
testl %eax, %eax
je 0x2586
movl %ebx, -0x34(%rbp)
movq %r14, -0x70(%rbp)
movq %r15, -0x98(%rbp)
movq -0x30(%rbp), %r14
movq %r14, %rdi
callq 0x10a0
movq %rax, %rbx
leaq 0x1(%rax), %rdi
callq 0x1190
movq %rax, %r15
movq %rax, %rdi
movq %r14, %rsi
callq 0x1150
movq %rbx, %rdi
callq 0x1190
movq %rax, -0x40(%rbp)
leaq 0x35fd(%rip), %rbx      # 0x56be
leaq -0xb0(%rbp), %r14
movq %r15, -0x60(%rbp)
movq %r15, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x1240
xorl %edi, %edi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x1240
testq %rax, %rax
je 0x219d
movq %rax, %rbx
leaq -0x90(%rbp), %r15
leaq 0x35bd(%rip), %r12      # 0x56be
leaq -0xb0(%rbp), %r13
movq -0x40(%rbp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1150
movq %r14, %rdi
leaq 0x3523(%rip), %rsi      # 0x5644
movq %r15, %rdx
callq 0x1240
movq -0x48(%rbp), %rdi
movq %rax, %rsi
callq 0x1060
testq %rax, %rax
jne 0x2184
movq -0x50(%rbp), %rdi
movw $0x41, (%rdi)
movq %rbx, %rsi
movq %rdi, %rbx
callq 0x1230
movq %rbx, %rdi
callq 0x10a0
movw $0xa, (%rbx,%rax)
movq %rbx, %rdi
callq 0x10a0
movl -0x34(%rbp), %edi
movq %rbx, %rsi
movq %rax, %rdx
callq 0x1080
testl %eax, %eax
js 0x25c1
movq %rbx, %rdi
xorl %eax, %eax
callq 0x1040
xorl %edi, %edi
movq %r12, %rsi
movq %r13, %rdx
callq 0x1240
movq %rax, %rbx
testq %rax, %rax
jne 0x210c
movq -0x48(%rbp), %rbx
movq %rbx, %rdi
callq 0x10a0
leaq 0x1(%rax), %rdi
callq 0x1190
movq %rax, %r13
movq %rax, %rdi
movq %rbx, %rsi
callq 0x1150
movq -0x30(%rbp), %r15
movq %r15, %rdi
callq 0x10a0
movq %rax, %rdi
callq 0x1190
movq %rax, -0x58(%rbp)
leaq 0x34df(%rip), %rbx      # 0x56be
leaq -0x90(%rbp), %r14
movq %r13, -0x68(%rbp)
movq %r13, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x1240
xorl %edi, %edi
movq %rbx, %rsi
movq %r14, %rdx
movq %r15, %r14
callq 0x1240
testq %rax, %rax
je 0x22c0
movq %rax, %r15
leaq 0x34a3(%rip), %r13      # 0x56be
leaq -0x90(%rbp), %rbx
movq -0x58(%rbp), %r12
movq %r12, %rdi
movq %r15, %rsi
callq 0x1150
movq %r12, %rdi
leaq 0x3409(%rip), %rsi      # 0x5644
leaq -0x88(%rbp), %rdx
callq 0x1240
movq %r14, %rdi
movq %rax, %rsi
callq 0x1060
testq %rax, %rax
jne 0x22a7
movq -0x50(%rbp), %r14
movw $0x44, (%r14)
movq %r14, %rdi
movq %r15, %rsi
callq 0x1230
movq %r14, %rdi
callq 0x10a0
movw $0xa, (%r14,%rax)
movq %r14, %rdi
callq 0x10a0
movl -0x34(%rbp), %edi
movq %r14, %rsi
movq %rax, %rdx
callq 0x1080
testl %eax, %eax
js 0x25c1
movq %r14, %rdi
xorl %eax, %eax
callq 0x1040
movq -0x30(%rbp), %r14
xorl %edi, %edi
movq %r13, %rsi
movq %rbx, %rdx
callq 0x1240
movq %rax, %r15
testq %rax, %rax
jne 0x2226
movq -0x60(%rbp), %rbx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x1150
movq -0x48(%rbp), %rdi
callq 0x10a0
movq %rax, %r14
movq %rax, %rdi
callq 0x1190
movq %rax, -0x30(%rbp)
movq %r14, %rdi
callq 0x1190
movq %rax, -0x78(%rbp)
leaq 0x33c4(%rip), %r14      # 0x56be
leaq -0x88(%rbp), %r15
movq %rbx, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x1240
xorl %edi, %edi
movq %r14, %rsi
movq %r15, %rdx
callq 0x1240
testq %rax, %rax
je 0x2536
movq %rax, %r15
leaq 0x338f(%rip), %r12      # 0x56be
leaq 0x330e(%rip), %r13      # 0x5644
movq -0x68(%rbp), %rbx
movq %rbx, %rdi
movq -0x48(%rbp), %rsi
callq 0x1150
movq %rbx, %rdi
movq %r12, %rsi
leaq -0xa8(%rbp), %rbx
movq %rbx, %rdx
callq 0x1240
xorl %edi, %edi
movq %r12, %rsi
movq %rbx, %rdx
callq 0x1240
testq %rax, %rax
je 0x2519
movq -0x58(%rbp), %r14
movq %r14, %rdi
movq %rax, %rsi
callq 0x1150
movq -0x40(%rbp), %rbx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x1150
movq %r14, %rdi
movq %r13, %rsi
leaq -0x80(%rbp), %rdx
callq 0x1240
movq %rax, %r14
movq %rbx, %rdi
movq %r13, %rsi
leaq -0xa0(%rbp), %rdx
callq 0x1240
movq %rax, %rbx
movq -0x30(%rbp), %rdi
movq %r14, %rsi
callq 0x1150
movq %r14, %rdi
movq %rbx, %rsi
callq 0x11b0
testl %eax, %eax
je 0x23df
xorl %edi, %edi
movq %r12, %rsi
leaq -0xa8(%rbp), %rdx
jmp 0x2363
xorl %edi, %edi
movq %r13, %rsi
leaq -0x80(%rbp), %rdx
callq 0x1240
movq %rax, %rbx
xorl %edi, %edi
movq %r13, %rsi
leaq -0xa0(%rbp), %rdx
callq 0x1240
movq %rax, %rdi
movq %rbx, %rsi
callq 0x11b0
testl %eax, %eax
je 0x23d1
xorl %edi, %edi
movq %r13, %rsi
leaq -0x80(%rbp), %rdx
callq 0x1240
movq %rax, %rbx
movq -0x30(%rbp), %rdi
callq 0x4387
movq %rax, %rdi
callq 0x4435
movq -0x78(%rbp), %r14
movw $0x3a48, (%r14)         # imm = 0x3A48
movb $0x0, 0x2(%r14)
movq %r14, %rdi
movq %rax, %rsi
callq 0x1230
movq %r14, %rdi
movq %rbx, %rsi
callq 0x11b0
testl %eax, %eax
je 0x24ca
movq -0x70(%rbp), %rdi
movl $0x441, %esi            # imm = 0x441
movl $0x1ff, %edx            # imm = 0x1FF
xorl %eax, %eax
callq 0x10f0
movl %eax, %r14d
movq -0x50(%rbp), %rbx
movw $0x43, (%rbx)
movq %rbx, %rdi
movq %r15, %rsi
callq 0x1230
movq %rbx, %rdi
callq 0x10a0
movw $0xa, (%rbx,%rax)
movq %rbx, %rdi
callq 0x10a0
movl %r14d, %edi
movq %rbx, %rsi
movq %rax, %rdx
callq 0x1080
testl %eax, %eax
js 0x25b8
movq %rbx, %rdi
xorl %eax, %eax
callq 0x1040
movl %r14d, %edi
callq 0x1250
jmp 0x23d1
movq -0x50(%rbp), %rbx
movw $0x4d, (%rbx)
movq %rbx, %rdi
movq %r15, %rsi
callq 0x1230
movq %rbx, %rdi
callq 0x10a0
movw $0xa, (%rbx,%rax)
movq %rbx, %rdi
callq 0x10a0
movl -0x34(%rbp), %edi
movq %rbx, %rsi
movq %rax, %rdx
callq 0x1080
testl %eax, %eax
js 0x25c1
movq %rbx, %rdi
xorl %eax, %eax
callq 0x1040
jmp 0x23d1
xorl %edi, %edi
movq %r12, %rsi
leaq -0x88(%rbp), %rdx
callq 0x1240
movq %rax, %r15
testq %rax, %rax
jne 0x2336
movq -0x68(%rbp), %rdi
callq 0x1170
movq -0x60(%rbp), %rdi
callq 0x1170
movq -0x58(%rbp), %rdi
callq 0x1170
movq -0x40(%rbp), %rdi
callq 0x1170
movq -0x30(%rbp), %rdi
callq 0x1170
movq -0x78(%rbp), %rdi
callq 0x1170
movq -0x70(%rbp), %rdi
callq 0x1170
movq -0x98(%rbp), %rdi
callq 0x1170
movl -0x34(%rbp), %edi
jmp 0x25a4
leaq 0x33a0(%rip), %rdi      # 0x592d
callq 0x11e0
movq %r15, %rdi
callq 0x1170
movq %r14, %rdi
callq 0x1170
movl %ebx, %edi
callq 0x1250
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x32aa(%rip), %rdi      # 0x5869
jmp 0x25c8
leaq 0x3304(%rip), %rdi      # 0x58cc
callq 0x11e0
movl $0x1, %edi
callq 0x1180
leaq 0x391c(%rip), %rdi      # 0x5efa
jmp 0x25c8
leaq 0x3a6b(%rip), %rdi      # 0x6052
jmp 0x25c8