// File: /workspace/github_cpp_makefile_star2_O2/MarkOates[P]file-downloader/file_downloader.cpp
// Function: FileDownloader::download_file(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>)
FileDownloader::FileHandle FileDownloader::download_file(std::string file_url, std::string local_filename)
{
   FileHandle file_handle(file_url, local_filename);
   std::string temp_filename = std::string(local_filename).insert(0, "~");
   CURL *curl = nullptr;
   FILE *file_pointer = nullptr;
   CURLcode res;
   curl = curl_easy_init();

   if (!curl)
   {
      file_handle.status = ERROR;
      file_handle.error = "CURL initialization error";
      return file_handle;
   }

   file_pointer = fopen(temp_filename.c_str(), "wb");
   curl_easy_setopt(curl, CURLOPT_URL, file_url.c_str());
   curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, FileDownloader::write_data);
   curl_easy_setopt(curl, CURLOPT_WRITEDATA, file_pointer);
   curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
   curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_function);
   curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &file_handle);

   res = curl_easy_perform(curl);

   if (res == CURLE_OK)
   {
      long http_response_code = 0;
      curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_response_code);

      switch (http_response_code)
      {
      case 200:
         {
            // copy the temp file to the destination
            std::ifstream src(temp_filename, std::ios::binary);
            std::ofstream dst(local_filename, std::ios::binary);
            dst << src.rdbuf();

            file_handle.status = DOWNLOADED;
            file_handle.percentage = 1.0;
         }
         break;
      case 404:
      default:
         file_handle.status = ERROR;
         file_handle.error = std::to_string(http_response_code);
         break;
      }
   }
   else
   {
      file_handle.status = ERROR;
      file_handle.error = curl_easy_strerror(res);
   }

   // erase the temp file
   remove(temp_filename.c_str());

   // cleanup the curl session
   curl_easy_cleanup(curl);
   fclose(file_pointer);

   return file_handle;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x478, %rsp            # imm = 0x478
movq %rdx, %r14
movq %rsi, %r13
movq %rdi, %rbx
leaq -0x90(%rbp), %rdi
callq 0x31a0
leaq -0x70(%rbp), %rdi
movq %r14, %rsi
callq 0x31a0
leaq -0x90(%rbp), %rsi
leaq -0x70(%rbp), %rdx
movq %rbx, %rdi
callq 0x3a5c
leaq -0x70(%rbp), %rdi
callq 0x3230
leaq -0x90(%rbp), %rdi
callq 0x3230
leaq -0x298(%rbp), %rdi
movq %r14, %rsi
callq 0x31a0
leaq 0x53b7(%rip), %rdx      # 0x9004
leaq -0x298(%rbp), %rdi
xorl %esi, %esi
callq 0x3180
leaq -0x50(%rbp), %rdi
movq %rax, %rsi
callq 0x31a0
leaq -0x298(%rbp), %rdi
callq 0x3230
callq 0x32e0
movq %rax, %r15
testq %rax, %rax
je 0x3d34
movq -0x50(%rbp), %rdi
leaq 0x5391(%rip), %rsi      # 0x9020
callq 0x3360
movq %rax, %r12
movq (%r13), %rdx
movq %r15, %rdi
movl $0x2712, %esi           # imm = 0x2712
xorl %eax, %eax
callq 0x3270
leaq 0x1fd(%rip), %rdx       # 0x3eae
movq %r15, %rdi
movl $0x4e2b, %esi           # imm = 0x4E2B
xorl %eax, %eax
callq 0x3270
movq %r15, %rdi
movl $0x2711, %esi           # imm = 0x2711
movq %r12, %rdx
xorl %eax, %eax
callq 0x3270
pushq $0x2b
popq %rsi
movq %r15, %rdi
xorl %edx, %edx
xorl %eax, %eax
callq 0x3270
leaq 0x1d0(%rip), %rdx       # 0x3eb8
movq %r15, %rdi
movl $0x4e58, %esi           # imm = 0x4E58
xorl %eax, %eax
callq 0x3270
movq %r15, %rdi
movl $0x2749, %esi           # imm = 0x2749
movq %rbx, %rdx
xorl %eax, %eax
callq 0x3270
movq %r15, %rdi
callq 0x3210
testl %eax, %eax
je 0x3d50
movl $0x3, 0x4(%rbx)
movl %eax, %edi
callq 0x3170
leaq 0x58(%rbx), %rdi
movq %rax, %rsi
callq 0x3350
jmp 0x3e02
movl $0x3, 0x4(%rbx)
leaq 0x58(%rbx), %rdi
leaq 0x52c0(%rip), %rsi      # 0x9006
callq 0x3350
jmp 0x3e1b
leaq -0x30(%rbp), %rdx
andq $0x0, (%rdx)
movq %r15, %rdi
movl $0x200002, %esi         # imm = 0x200002
xorl %eax, %eax
callq 0x32d0
movq -0x30(%rbp), %rsi
cmpq $0xc8, %rsi
jne 0x3dd4
leaq -0x298(%rbp), %rdi
leaq -0x50(%rbp), %rsi
pushq $0x4
popq %rdx
callq 0x3300
leaq -0x498(%rbp), %rdi
pushq $0x4
popq %rdx
movq %r14, %rsi
callq 0x30b0
leaq -0x288(%rbp), %rsi
leaq -0x498(%rbp), %rdi
callq 0x30d0
movl $0x2, 0x4(%rbx)
movl $0x3f800000, 0xc(%rbx)  # imm = 0x3F800000
leaq -0x498(%rbp), %rdi
callq 0x3240
leaq -0x298(%rbp), %rdi
callq 0x3030
jmp 0x3e02
movl $0x3, 0x4(%rbx)
leaq -0x298(%rbp), %rdi
callq 0x3f31
leaq 0x58(%rbx), %rdi
leaq -0x298(%rbp), %r14
movq %r14, %rsi
callq 0x3190
movq %r14, %rdi
callq 0x3230
movq -0x50(%rbp), %rdi
callq 0x30e0
movq %r15, %rdi
callq 0x3090
movq %r12, %rdi
callq 0x3160
leaq -0x50(%rbp), %rdi
callq 0x3230
movq %rbx, %rax
addq $0x478, %rsp            # imm = 0x478
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %r14
leaq -0x498(%rbp), %rdi
callq 0x3240
jmp 0x3e4d
movq %rax, %r14
leaq -0x298(%rbp), %rdi
callq 0x3030
jmp 0x3e94
jmp 0x3e91
jmp 0x3e91
jmp 0x3e91
movq %rax, %r14
jmp 0x3e9d
movq %rax, %r14
leaq -0x70(%rbp), %rdi
callq 0x3230
jmp 0x3e77
movq %rax, %r14
leaq -0x90(%rbp), %rdi
callq 0x3230
jmp 0x3ea5
movq %rax, %r14
leaq -0x298(%rbp), %rdi
jmp 0x3e98
movq %rax, %r14
leaq -0x50(%rbp), %rdi
callq 0x3230
movq %rbx, %rdi
callq 0x3aec
movq %r14, %rdi
callq 0x31e0
nop