# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.

cmake_minimum_required(VERSION 3.5)

set(quiet "@quiet@")
set(script_dir "@CMAKE_CURRENT_FUNCTION_LIST_DIR@/ExternalProject")
include(${script_dir}/captured_process_setup.cmake)

function(check_file_hash has_hash hash_is_good)
  if("${has_hash}" STREQUAL "")
    _ep_message_quiet_capture(FATAL_ERROR "has_hash Can't be empty")
  endif()

  if("${hash_is_good}" STREQUAL "")
    _ep_message_quiet_capture(FATAL_ERROR "hash_is_good Can't be empty")
  endif()

  if("@ALGO@" STREQUAL "")
    # No check
    set("${has_hash}" FALSE PARENT_SCOPE)
    set("${hash_is_good}" FALSE PARENT_SCOPE)
    return()
  endif()

  set("${has_hash}" TRUE PARENT_SCOPE)

  _ep_message_quiet_capture(STATUS "verifying file...
       file='@LOCAL@'")
  set(accumulated_output "${accumulated_output}" PARENT_SCOPE)

  file("@ALGO@" "@LOCAL@" actual_value)

  if(NOT "${actual_value}" STREQUAL "@EXPECT_VALUE@")
    set("${hash_is_good}" FALSE PARENT_SCOPE)
    _ep_message_quiet_capture(STATUS "@ALGO@ hash of
    @LOCAL@
  does not match expected value
    expected: '@EXPECT_VALUE@'
      actual: '${actual_value}'")
    set(accumulated_output "${accumulated_output}" PARENT_SCOPE)
  else()
    set("${hash_is_good}" TRUE PARENT_SCOPE)
  endif()
endfunction()

function(sleep_before_download attempt)
  if(attempt EQUAL 0)
    return()
  endif()

  if(attempt EQUAL 1)
    _ep_message_quiet_capture(STATUS "Retrying...")
    set(accumulated_output "${accumulated_output}" PARENT_SCOPE)
    return()
  endif()

  set(sleep_seconds 0)

  if(attempt EQUAL 2)
    set(sleep_seconds 5)
  elseif(attempt EQUAL 3)
    set(sleep_seconds 5)
  elseif(attempt EQUAL 4)
    set(sleep_seconds 15)
  elseif(attempt EQUAL 5)
    set(sleep_seconds 60)
  elseif(attempt EQUAL 6)
    set(sleep_seconds 90)
  elseif(attempt EQUAL 7)
    set(sleep_seconds 300)
  else()
    set(sleep_seconds 1200)
  endif()

  _ep_message_quiet_capture(STATUS
    "Retry after ${sleep_seconds} seconds (attempt #${attempt}) ..."
  )
  set(accumulated_output "${accumulated_output}" PARENT_SCOPE)

  execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep "${sleep_seconds}")
endfunction()

if("@LOCAL@" STREQUAL "")
  message(FATAL_ERROR "LOCAL can't be empty")
endif()

if("@REMOTE@" STREQUAL "")
  message(FATAL_ERROR "REMOTE can't be empty")
endif()

function(download_and_verify)
  if(EXISTS "@LOCAL@")
    check_file_hash(has_hash hash_is_good)
    if(has_hash)
      if(hash_is_good)
        _ep_message_quiet_capture(STATUS
"File already exists and hash match (skip download):
  file='@LOCAL@'
  @ALGO@='@EXPECT_VALUE@'"
        )
        set(accumulated_output "${accumulated_output}" PARENT_SCOPE)
        return()
      else()
        _ep_message_quiet_capture(STATUS
          "File already exists but hash mismatch. Removing..."
        )
        set(accumulated_output "${accumulated_output}" PARENT_SCOPE)
        file(REMOVE "@LOCAL@")
      endif()
    else()
      _ep_message_quiet_capture(STATUS
"File already exists but no hash specified (use URL_HASH):
  file='@LOCAL@'
Old file will be removed and new file downloaded from URL."
      )
      file(REMOVE "@LOCAL@")
    endif()
  endif()

  set(retry_number 5)

  _ep_message_quiet_capture(STATUS "Downloading...
   dst='@LOCAL@'
   timeout='@TIMEOUT_MSG@'
   inactivity timeout='@INACTIVITY_TIMEOUT_MSG@'"
  )
  set(accumulated_output "${accumulated_output}" PARENT_SCOPE)
  set(download_retry_codes 7 6 8 15)
  set(skip_url_list)
  set(status_code)
  foreach(i RANGE ${retry_number})
    if(status_code IN_LIST download_retry_codes)
      sleep_before_download(${i})
    endif()
    foreach(url @REMOTE@)
      if(NOT url IN_LIST skip_url_list)
        _ep_message_quiet_capture(STATUS "Using src='${url}'")
        set(accumulated_output "${accumulated_output}" PARENT_SCOPE)

        @TLS_VERIFY_CODE@
        @TLS_CAINFO_CODE@
        @NETRC_CODE@
        @NETRC_FILE_CODE@

        file(
          DOWNLOAD
          "${url}" "@LOCAL@"
          @SHOW_PROGRESS@
          @TIMEOUT_ARGS@
          @INACTIVITY_TIMEOUT_ARGS@
          STATUS status
          LOG log
          @USERPWD_ARGS@
          @HTTP_HEADERS_ARGS@
          )

        list(GET status 0 status_code)
        list(GET status 1 status_string)

        if(status_code EQUAL 0)
          check_file_hash(has_hash hash_is_good)
          if(has_hash AND NOT hash_is_good)
            _ep_message_quiet_capture(STATUS "Hash mismatch, removing...")
            set(accumulated_output "${accumulated_output}" PARENT_SCOPE)
            file(REMOVE "@LOCAL@")
          else()
            _ep_message_quiet_capture(STATUS "Downloading... done")
            set(accumulated_output "${accumulated_output}" PARENT_SCOPE)
            return()
          endif()
        else()
          string(APPEND logFailedURLs
"error: downloading '${url}' failed
        status_code: ${status_code}
        status_string: ${status_string}
        log:
        --- LOG BEGIN ---
        ${log}
        --- LOG END ---
        "
          )
        if(NOT status_code IN_LIST download_retry_codes)
          list(APPEND skip_url_list "${url}")
          break()
        endif()
      endif()
    endif()
    endforeach()
  endforeach()

  _ep_message_quiet_capture(FATAL_ERROR
"Each download failed!
  ${logFailedURLs}
  "
  )

endfunction()

download_and_verify()

set(extract_script @extract_script_filename@)
if(NOT "${extract_script}" STREQUAL "")
  include(${extract_script})
endif()
