/**
   * Create a new instance.
   *
   * @param builder the builder from which to get values
   */
  private DownloadTask(final Builder builder) {
    downloadId = builder.id;
    uri = builder.downloadUri;
    destination = builder.dest;
    listener = new WeakReference<>(builder.listener);
    provider = new WeakReference<>(builder.provider);
    downloadTag = builder.eTag;
    downloadOffset = 0L;
    totalBytes = 0L;
    try {
      if (null != builder.offset) {
        downloadOffset = Long.parseLong(builder.offset);
      }
    } catch (final NumberFormatException ex) {
      Log.e(LOG_TAG, "Error trying to figure out offset to start download", ex);
    }

    try {
      if (null != builder.totalBytes) {
        totalBytes = Long.parseLong(builder.totalBytes);
      }
    } catch (final NumberFormatException ex) {
      Log.e(LOG_TAG, "Error trying to figure out totalBytes to start download", ex);
    }

    forUser = DownloadFlags.isUserRequestFlagSet(builder.downloadFlags);
    isSilent = DownloadFlags.isSilentFlagSet(builder.downloadFlags);
    isMobileNetworkProhibited = DownloadFlags.isCellNetworkProhibited(builder.downloadFlags);
    networkStatusProvider = builder.networkStatusProvider;
    autoRestart = builder.autoRestart;
    downloadErrorCode = DownloadError.NO_ERROR.getValue();
    cancelReason = TaskCancelReason.UNEXPECTED;
  }
  /**
   * Execute the task.
   *
   * @return true if it works, false otherwise.
   */
  @Override
  public Boolean call() {
    final long start = System.nanoTime();
    CompletionStatus result = CompletionStatus.FAILED;
    try {
      Log.d(LOG_TAG, "Download Task started for download id = " + downloadId);
      failureMessage = MSG_OKAY;
      downloadErrorCode = DownloadError.NO_ERROR.getValue();

      if (!ensureFolderExists(destination)) {
        finish(
            CompletionStatus.FAILED,
            failureMessage,
            cumulativeBytesRead,
            totalBytes,
            autoRestart,
            downloadErrorCode);
        return false;
      }

      if (null != downloadTag && 0L < downloadOffset) {
        if (!ensurePartialFilePresent(destination, downloadOffset)) {
          // if we don't have the partial file any more, we have to start again
          downloadOffset = 0L;
        }
      }

      result = readFromUri(destination);
      finish(
          result, failureMessage, cumulativeBytesRead, totalBytes, autoRestart, downloadErrorCode);
      return CompletionStatus.SUCCEEDED == result;
    } finally {
      // Make sure we release wifi lock (if any)
      networkStatusProvider.releaseWifiLock(downloadId);

      final long duration = System.nanoTime() - start;

      Log.d(
          LOG_TAG,
          String.format(
              "Download result(%s) for download task with uri(%s) took %.3f seconds.",
              result.name(), uri, (double) duration / 1000000000));
    }
  }