// File: /workspace/github_c_makefile_star2_O2/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, %r15
movq %r15, -0x40(%rbp)
leaq 0x12(%rax), %r14
andq $-0x10, %r14
subq %r14, %r15
movq %r15, %rsp
negq %r14
xorl %r13d, %r13d
movq %r15, %rdi
xorl %esi, %esi
movq %rdx, -0x30(%rbp)
callq 0x10c0
movq -0x40(%rbp), %rax
movw $0x2075, (%rax,%r14)    # imm = 0x2075
pushq $0x2
popq %rax
cmpq %r13, %r12
je 0x1daa
movb (%rbx,%r13), %cl
testb %cl, %cl
je 0x1da5
cltq
movb %cl, (%r15,%rax)
incl %eax
incq %r13
jmp 0x1d90
leaq 0x35db(%rip), %rdi      # 0x538c
movq %r15, %rsi
movq -0x30(%rbp), %rdx
movq %rbx, %rcx
xorl %eax, %eax
callq 0x1040
movq %r15, %rdi
callq 0x401a
movq %rax, %r12
movzbl (%rax), %eax
cmpl $0x65, %eax
je 0x1dee
cmpl $0x78, %eax
jne 0x1dfa
cmpb $0x0, 0x1(%r12)
jne 0x1dfa
leaq 0x4045(%rip), %rdi      # 0x5e2e
jmp 0x24c2
cmpb $0x0, 0x1(%r12)
je 0x24d8
movq %rbx, %rdi
callq 0x11c0
testq %rax, %rax
je 0x24cf
movq %rax, %rdi
callq 0x1200
leaq -0xd0(%rbp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1140
movq %r14, %rdi
callq 0x10a0
movabsq $0x6566696e614d2e2f, %rcx # imm = 0x6566696E614D2E2F
movq %rcx, -0xd0(%rbp,%rax)
movl $0x747365, -0xc9(%rbp,%rax) # imm = 0x747365
movq %r14, %rdi
callq 0x41b4
movq %rax, %r15
movq %r12, %rdi
callq 0x10a0
movq %rax, %rdi
callq 0x1180
movq %rax, %r13
leaq -0xb8(%rbp), %rax
movq %r13, (%rax)
movq %r15, %rdi
callq 0x10a0
movq %rax, %rdi
callq 0x1180
movq %r12, %rsi
movq %rax, %r12
leaq -0xb0(%rbp), %rax
movq %r12, (%rax)
movq %r13, %rdi
movq %rsi, -0x30(%rbp)
callq 0x1140
movq %r12, %rdi
movq %r15, -0x48(%rbp)
movq %r15, %rsi
callq 0x1140
movq %rbx, %rdi
callq 0x10a0
movq %rax, %r13
leaq 0x8(%rax), %rdi
callq 0x1180
movq %rax, %r15
movq %rax, %rdi
movq %rbx, %rsi
callq 0x1140
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 0x1180
movq %rax, %r14
movq %rax, %rdi
movq %rbx, %rsi
callq 0x1140
movq %r14, %rdi
callq 0x10a0
movabsq $0x696c666e6f432e2f, %rcx # imm = 0x696C666E6F432E2F
movq %rcx, (%r14,%rax)
movl $0x746369, 0x7(%r14,%rax) # imm = 0x746369
leaq 0x3793(%rip), %r13      # 0x56be
movq %r12, %rdi
movq %r13, %rsi
leaq -0xb0(%rbp), %rdx
callq 0x1230
movq %rax, -0x40(%rbp)
leaq -0xb8(%rbp), %rdx
movq (%rdx), %rdi
movq %r13, %rsi
callq 0x1230
movq %rax, %r13
movq %rbx, %rdi
callq 0x10a0
movq %rax, %rbx
movq %r14, %rdi
callq 0x10a0
leaq (%rbx,%rax), %rdi
addq $0x1e, %rdi
callq 0x1180
movq %rax, %rbx
movabsq $0x2066722d206d72, %r12 # imm = 0x2066722D206D72
movq %r12, (%rax)
movq %rax, %rdi
movq %r15, %rsi
callq 0x1220
movq %rbx, %rdi
callq 0x1120
pushq $0x2e
popq %rdi
callq 0x1180
movq %rax, %rbx
movq %r12, (%rax)
movq %rax, %rdi
movq %r14, %rsi
callq 0x1220
movq %rbx, -0x50(%rbp)
movq %rbx, %rdi
callq 0x1120
pushq $0x41
popq %rsi
movq %r15, %rdi
movl $0x1ff, %edx            # imm = 0x1FF
xorl %eax, %eax
callq 0x10f0
movl %eax, %ebx
movq -0x40(%rbp), %rdi
movq %r13, %rsi
callq 0x11a0
testl %eax, %eax
je 0x2480
movl %ebx, -0x34(%rbp)
movq %r14, -0x70(%rbp)
movq %r15, -0x90(%rbp)
movq -0x30(%rbp), %r15
movq %r15, %rdi
callq 0x10a0
movq %rax, %rbx
leaq 0x1(%rax), %rdi
callq 0x1180
movq %rax, %r14
movq %rax, %rdi
movq %r15, %rsi
callq 0x1140
movq %rbx, %rdi
callq 0x1180
movq %rax, -0x40(%rbp)
leaq 0x3691(%rip), %rsi      # 0x56be
leaq -0xd8(%rbp), %r15
movq %r14, -0x60(%rbp)
movq %r14, %rdi
movq %r15, %rdx
callq 0x1230
leaq 0x35fa(%rip), %r12      # 0x5644
leaq -0xa8(%rbp), %r13
movq -0x40(%rbp), %rbx
xorl %edi, %edi
leaq 0x3660(%rip), %rsi      # 0x56be
movq %r15, %rdx
callq 0x1230
testq %rax, %rax
je 0x20e8
movq %rax, %r14
movq %rbx, %rdi
movq %rax, %rsi
callq 0x1140
movq %rbx, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq 0x1230
movq -0x48(%rbp), %rdi
movq %rax, %rsi
callq 0x1060
testq %rax, %rax
jne 0x2055
movq -0x50(%rbp), %rdi
movw $0x41, (%rdi)
movq %r14, %rsi
movq %rdi, %r14
callq 0x1220
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 0x24bb
movq %r14, %rdi
xorl %eax, %eax
callq 0x1040
jmp 0x2055
movq -0x48(%rbp), %rbx
movq %rbx, %rdi
callq 0x10a0
leaq 0x1(%rax), %rdi
callq 0x1180
movq %rax, %r14
movq %rax, %rdi
movq %rbx, %rsi
callq 0x1140
movq -0x30(%rbp), %rdi
callq 0x10a0
movq %rax, %rdi
callq 0x1180
movq %rax, -0x58(%rbp)
leaq 0x3597(%rip), %rsi      # 0x56be
leaq -0xa8(%rbp), %r12
movq %r14, -0x68(%rbp)
movq %r14, %rdi
movq %r12, %rdx
callq 0x1230
leaq 0x3500(%rip), %r13      # 0x5644
leaq -0x88(%rbp), %r15
movq -0x58(%rbp), %rbx
xorl %edi, %edi
leaq 0x3566(%rip), %rsi      # 0x56be
movq %r12, %rdx
callq 0x1230
testq %rax, %rax
je 0x21e2
movq %rax, %r14
movq %rbx, %rdi
movq %rax, %rsi
callq 0x1140
movq %rbx, %rdi
movq %r13, %rsi
movq %r15, %rdx
callq 0x1230
movq -0x30(%rbp), %rdi
movq %rax, %rsi
callq 0x1060
testq %rax, %rax
jne 0x214f
movq -0x50(%rbp), %rdi
movw $0x44, (%rdi)
movq %r14, %rsi
movq %rdi, %r14
callq 0x1220
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 0x24bb
movq %r14, %rdi
xorl %eax, %eax
callq 0x1040
jmp 0x214f
movq -0x60(%rbp), %r15
movq %r15, %rdi
movq -0x30(%rbp), %rsi
callq 0x1140
movq -0x48(%rbp), %rdi
callq 0x10a0
movq %rax, %r14
movq %rax, %rdi
callq 0x1180
movq %rax, -0x30(%rbp)
movq %r14, %rdi
callq 0x1180
movq %rax, -0x78(%rbp)
leaq 0x34a1(%rip), %rbx      # 0x56be
leaq -0x88(%rbp), %rdx
movq %r15, %rdi
movq %rbx, %rsi
callq 0x1230
leaq 0x340e(%rip), %r15      # 0x5644
xorl %edi, %edi
movq %rbx, %rsi
leaq -0x88(%rbp), %rdx
callq 0x1230
testq %rax, %rax
je 0x2430
movq %rax, %r13
movq -0x68(%rbp), %r14
movq %r14, %rdi
movq -0x48(%rbp), %rsi
callq 0x1140
movq %r14, %rdi
movq %rbx, %rsi
leaq -0xa0(%rbp), %rdx
callq 0x1230
xorl %edi, %edi
movq %rbx, %rsi
leaq -0xa0(%rbp), %rdx
callq 0x1230
testq %rax, %rax
je 0x2236
movq -0x58(%rbp), %r14
movq %r14, %rdi
movq %rax, %rsi
callq 0x1140
movq -0x40(%rbp), %r12
movq %r12, %rdi
movq %r13, %rsi
callq 0x1140
movq %r14, %rdi
movq %r15, %rsi
leaq -0x80(%rbp), %rdx
callq 0x1230
movq %rax, %r14
movq %r12, %rdi
movq %r15, %rsi
leaq -0x98(%rbp), %rdx
callq 0x1230
movq %rax, %r12
movq -0x30(%rbp), %rdi
movq %r14, %rsi
callq 0x1140
movq %r14, %rdi
movq %r12, %rsi
callq 0x11a0
testl %eax, %eax
jne 0x2275
xorl %edi, %edi
movq %r15, %rsi
leaq -0x80(%rbp), %rdx
callq 0x1230
movq %rax, %r14
xorl %edi, %edi
movq %r15, %rsi
leaq -0x98(%rbp), %rdx
callq 0x1230
movq %rax, %rdi
movq %r14, %rsi
callq 0x11a0
testl %eax, %eax
je 0x2275
xorl %edi, %edi
movq %r15, %rsi
leaq -0x80(%rbp), %rdx
callq 0x1230
movq %rax, %r14
movq -0x30(%rbp), %rdi
callq 0x41b4
movq %rax, %rdi
callq 0x425e
movq -0x78(%rbp), %r12
movw $0x3a48, (%r12)         # imm = 0x3A48
movb $0x0, 0x2(%r12)
movq %r12, %rdi
movq %rax, %rsi
callq 0x1220
movq %r12, %rdi
movq %r14, %rsi
callq 0x11a0
testl %eax, %eax
je 0x23df
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), %r12
movw $0x43, (%r12)
movq %r12, %rdi
movq %r13, %rsi
callq 0x1220
movq %r12, %rdi
callq 0x10a0
movw $0xa, (%r12,%rax)
movq %r12, %rdi
callq 0x10a0
movl %r14d, %edi
movq %r12, %rsi
movq %rax, %rdx
callq 0x1080
testl %eax, %eax
js 0x24b2
movq %r12, %rdi
xorl %eax, %eax
callq 0x1040
movl %r14d, %edi
callq 0x1240
jmp 0x2275
movq -0x50(%rbp), %r14
movw $0x4d, (%r14)
movq %r14, %rdi
movq %r13, %rsi
callq 0x1220
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 0x24bb
movq %r14, %rdi
xorl %eax, %eax
callq 0x1040
jmp 0x2275
movq -0x68(%rbp), %rdi
callq 0x1160
movq -0x60(%rbp), %rdi
callq 0x1160
movq -0x58(%rbp), %rdi
callq 0x1160
movq -0x40(%rbp), %rdi
callq 0x1160
movq -0x30(%rbp), %rdi
callq 0x1160
movq -0x78(%rbp), %rdi
callq 0x1160
movq -0x70(%rbp), %rdi
callq 0x1160
movq -0x90(%rbp), %rdi
callq 0x1160
movl -0x34(%rbp), %edi
jmp 0x249e
leaq 0x34a6(%rip), %rdi      # 0x592d
callq 0x11d0
movq %r15, %rdi
callq 0x1160
movq %r14, %rdi
callq 0x1160
movl %ebx, %edi
callq 0x1240
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x33b0(%rip), %rdi      # 0x5869
jmp 0x24c2
leaq 0x340a(%rip), %rdi      # 0x58cc
callq 0x11d0
pushq $0x1
popq %rdi
callq 0x1170
leaq 0x3a24(%rip), %rdi      # 0x5efa
jmp 0x24c2
leaq 0x3b73(%rip), %rdi      # 0x6052
jmp 0x24c2