//
// Copyright (C) 2011 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "update_engine/common/download_action.h"

#include <string>

#include <base/files/file_path.h>
#include <base/metrics/statistics_recorder.h>
#include <android-base/stringprintf.h>

#include "update_engine/common/boot_control_interface.h"
#include "update_engine/common/error_code_utils.h"
#include "update_engine/common/multi_range_http_fetcher.h"
#include "update_engine/common/prefs_interface.h"
#include "update_engine/common/utils.h"

using base::FilePath;
using std::string;

namespace chromeos_update_engine {

DownloadAction::DownloadAction(PrefsInterface* prefs,
                               BootControlInterface* boot_control,
                               HardwareInterface* hardware,
                               HttpFetcher* http_fetcher,
                               bool interactive,
                               std::string update_certificates_path)
    : prefs_(prefs),
      boot_control_(boot_control),
      hardware_(hardware),
      http_fetcher_(new MultiRangeHttpFetcher(http_fetcher)),
      interactive_(interactive),
      code_(ErrorCode::kSuccess),
      delegate_(nullptr),
      update_certificates_path_(std::move(update_certificates_path)) {}

DownloadAction::~DownloadAction() {}

void DownloadAction::PerformAction() {
  http_fetcher_->set_delegate(this);

  // Get the InstallPlan and read it
  CHECK(HasInputObject());
  install_plan_ = GetInputObject();
  install_plan_.Dump();

  bytes_received_ = 0;
  bytes_received_previous_payloads_ = 0;
  bytes_total_ = 0;
  for (const auto& payload : install_plan_.payloads)
    bytes_total_ += payload.size;

  if (install_plan_.is_resume) {
    int64_t payload_index = 0;
    if (prefs_->GetInt64(kPrefsUpdateStatePayloadIndex, &payload_index) &&
        static_cast<size_t>(payload_index) < install_plan_.payloads.size()) {
      // Save the index for the resume payload before downloading any previous
      // payload, otherwise it will be overwritten.
      resume_payload_index_ = payload_index;
      for (int i = 0; i < payload_index; i++)
        install_plan_.payloads[i].already_applied = true;
    }
  }
  CHECK_GE(install_plan_.payloads.size(), 1UL);
  if (!payload_)
    payload_ = &install_plan_.payloads[0];

  LOG(INFO) << "Marking new slot as unbootable";
  if (!boot_control_->MarkSlotUnbootable(install_plan_.target_slot)) {
    LOG(WARNING) << "Unable to mark new slot "
                 << BootControlInterface::SlotName(install_plan_.target_slot)
                 << ". Proceeding with the update anyway.";
  }

  StartDownloading();
}

bool DownloadAction::LoadCachedManifest(int64_t manifest_size) {
  std::string cached_manifest_bytes;
  if (!prefs_->GetString(kPrefsManifestBytes, &cached_manifest_bytes) ||
      cached_manifest_bytes.size() <= 0) {
    LOG(INFO) << "Cached Manifest data not found";
    return false;
  }
  if (static_cast<int64_t>(cached_manifest_bytes.size()) != manifest_size) {
    LOG(WARNING) << "Cached metadata has unexpected size: "
                 << cached_manifest_bytes.size() << " vs. " << manifest_size;
    return false;
  }

  ErrorCode error{};
  const bool success =
      delta_performer_->Write(
          cached_manifest_bytes.data(), cached_manifest_bytes.size(), &error) &&
      delta_performer_->IsManifestValid();
  if (success) {
    LOG(INFO) << "Successfully parsed cached manifest";
  } else {
    // If parsing of cached data failed, fall back to fetch them using HTTP
    LOG(WARNING) << "Cached manifest data fails to load, error code:"
                 << static_cast<int>(error) << "," << error;
  }
  return success;
}

void DownloadAction::StartDownloading() {
  download_active_ = true;
  http_fetcher_->ClearRanges();

  if (delta_performer_ != nullptr) {
    LOG(INFO) << "Using writer for test.";
  } else {
    delta_performer_.reset(new DeltaPerformer(prefs_,
                                              boot_control_,
                                              hardware_,
                                              delegate_,
                                              &install_plan_,
                                              payload_,
                                              interactive_,
                                              update_certificates_path_));
  }

  if (install_plan_.is_resume &&
      payload_ == &install_plan_.payloads[resume_payload_index_]) {
    // Resuming an update so parse the cached manifest first
    int64_t manifest_metadata_size = 0;
    int64_t manifest_signature_size = 0;
    prefs_->GetInt64(kPrefsManifestMetadataSize, &manifest_metadata_size);
    prefs_->GetInt64(kPrefsManifestSignatureSize, &manifest_signature_size);

    // TODO(zhangkelvin) Add unittest for success and fallback route
    if (!LoadCachedManifest(manifest_metadata_size + manifest_signature_size)) {
      if (delta_performer_) {
        // Create a new DeltaPerformer to reset all its state
        delta_performer_ =
            std::make_unique<DeltaPerformer>(prefs_,
                                             boot_control_,
                                             hardware_,
                                             delegate_,
                                             &install_plan_,
                                             payload_,
                                             interactive_,
                                             update_certificates_path_);
      }
      http_fetcher_->AddRange(base_offset_,
                              manifest_metadata_size + manifest_signature_size);
    }

    // If there're remaining unprocessed data blobs, fetch them. Be careful
    // not to request data beyond the end of the payload to avoid 416 HTTP
    // response error codes.
    int64_t next_data_offset = 0;
    prefs_->GetInt64(kPrefsUpdateStateNextDataOffset, &next_data_offset);
    uint64_t resume_offset =
        manifest_metadata_size + manifest_signature_size + next_data_offset;
    if (!payload_->size) {
      http_fetcher_->AddRange(base_offset_ + resume_offset);
    } else if (resume_offset < payload_->size) {
      http_fetcher_->AddRange(base_offset_ + resume_offset,
                              payload_->size - resume_offset);
    }
  } else {
    if (payload_->size) {
      http_fetcher_->AddRange(base_offset_, payload_->size);
    } else {
      // If no payload size is passed we assume we read until the end of the
      // stream.
      http_fetcher_->AddRange(base_offset_);
    }
  }

  http_fetcher_->BeginTransfer(install_plan_.download_url);
}

void DownloadAction::SuspendAction() {
  http_fetcher_->Pause();
}

void DownloadAction::ResumeAction() {
  http_fetcher_->Unpause();
}

void DownloadAction::TerminateProcessing() {
  if (delta_performer_) {
    delta_performer_->Close();
    delta_performer_.reset();
  }
  download_active_ = false;
  // Terminates the transfer. The action is terminated, if necessary, when the
  // TransferTerminated callback is received.
  http_fetcher_->TerminateTransfer();
}

void DownloadAction::SeekToOffset(off_t offset) {
  bytes_received_ = offset;
}

bool DownloadAction::ReceivedBytes(HttpFetcher* fetcher,
                                   const void* bytes,
                                   size_t length) {
  bytes_received_ += length;
  uint64_t bytes_downloaded_total =
      bytes_received_previous_payloads_ + bytes_received_;
  if (delegate_ && download_active_) {
    delegate_->BytesReceived(
        length, bytes_downloaded_total - base_offset_, bytes_total_);
  }
  if (delta_performer_ && !delta_performer_->Write(bytes, length, &code_)) {
    if (code_ != ErrorCode::kSuccess) {
      LOG(ERROR) << "Error " << utils::ErrorCodeToString(code_) << " (" << code_
                 << ") in DeltaPerformer's Write method when "
                 << "processing the received payload -- Terminating processing";
    } else {
      LOG(ERROR) << "Unknown error in DeltaPerformer's Write method when "
                 << "processing the received payload -- Terminating processing";
      code_ = ErrorCode::kDownloadWriteError;
    }
    // Don't tell the action processor that the action is complete until we get
    // the TransferTerminated callback. Otherwise, this and the HTTP fetcher
    // objects may get destroyed before all callbacks are complete.
    TerminateProcessing();
    return false;
  }

  return true;
}

void DownloadAction::TransferComplete(HttpFetcher* fetcher, bool successful) {
  if (delta_performer_) {
    LOG_IF(WARNING, delta_performer_->Close() != 0)
        << "Error closing the writer.";
  }
  download_active_ = false;
  ErrorCode code =
      successful ? ErrorCode::kSuccess : ErrorCode::kDownloadTransferError;
  if (code == ErrorCode::kSuccess) {
    if (delta_performer_ && !payload_->already_applied)
      code = delta_performer_->VerifyPayload(payload_->hash, payload_->size);
    if (code == ErrorCode::kSuccess) {
      CHECK_EQ(install_plan_.payloads.size(), 1UL);
      // All payloads have been applied and verified.
      if (delegate_)
        delegate_->DownloadComplete();

      // Log UpdateEngine.DownloadAction.* histograms to help diagnose
      // long-blocking operations.
      std::string histogram_output;
      base::StatisticsRecorder::WriteGraph("UpdateEngine.DownloadAction.",
                                           &histogram_output);
      LOG(INFO) << histogram_output;
    } else {
      LOG(ERROR) << "Download of " << install_plan_.download_url
                 << " failed due to payload verification error.";
    }
  }

  // Write the path to the output pipe if we're successful.
  if (code == ErrorCode::kSuccess && HasOutputPipe())
    SetOutputObject(install_plan_);
  processor_->ActionComplete(this, code);
}

void DownloadAction::TransferTerminated(HttpFetcher* fetcher) {
  if (code_ != ErrorCode::kSuccess) {
    processor_->ActionComplete(this, code_);
  } else if (payload_->already_applied) {
    LOG(INFO) << "TransferTerminated with ErrorCode::kSuccess when the current "
                 "payload has already applied, treating as TransferComplete.";
    TransferComplete(fetcher, true);
  }
}

}  // namespace chromeos_update_engine
