// Copyright 2021 The Pigweed Authors
//
// 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
//
//     https://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 "pw_software_update/config.h"

#define PW_LOG_LEVEL PW_SOFTWARE_UPDATE_CONFIG_LOG_LEVEL

#include <mutex>
#include <string_view>

#include "pw_log/log.h"
#include "pw_result/result.h"
#include "pw_software_update/bundled_update_service.h"
#include "pw_software_update/manifest_accessor.h"
#include "pw_software_update/update_bundle.pwpb.h"
#include "pw_status/status.h"
#include "pw_status/status_with_size.h"
#include "pw_status/try.h"
#include "pw_string/util.h"
#include "pw_sync/mutex.h"
#include "pw_tokenizer/tokenize.h"

// TODO(keir): Convert all the CHECKs in the RPC service to gracefully report
// errors.
//
// TODO: It may be worth figuring out how to make this a function to prevent
// code bloat. It's hard due to the tokenized message handling.
#define SET_ERROR(res, message, ...)                                       \
  do {                                                                     \
    PW_LOG_ERROR(message, __VA_ARGS__);                                    \
    if (status_.state !=                                                   \
        pw_software_update_BundledUpdateState_Enum_FINISHED) {             \
      PW_CHECK_OK(backend_.BeforeUpdateAbort());                           \
      if (status_.has_transfer_id) {                                       \
        backend_.DisableBundleTransferHandler();                           \
      }                                                                    \
      status_.has_transfer_id = false;                                     \
      if (bundle_open_) {                                                  \
        /* TODO: Revisit this check; may be able to recover */             \
        PW_CHECK_OK(bundle_.Close());                                      \
        bundle_open_ = false;                                              \
      }                                                                    \
      status_.state = pw_software_update_BundledUpdateState_Enum_FINISHED; \
      status_.result = res;                                                \
      status_.has_result = true;                                           \
      size_t note_size = sizeof(status_.note.bytes);                       \
      PW_TOKENIZE_TO_BUFFER(                                               \
          status_.note.bytes, &note_size, message, __VA_ARGS__);           \
      status_.note.size = note_size;                                       \
      status_.has_note = true;                                             \
    }                                                                      \
  } while (false)

namespace pw::software_update {

Status BundledUpdateService::GetStatus(
    ServerContext&,
    const pw_protobuf_Empty&,
    pw_software_update_BundledUpdateStatus& response) {
  std::lock_guard lock(mutex_);
  response = status_;
  return OkStatus();
}

Status BundledUpdateService::Start(
    ServerContext&,
    const pw_software_update_StartRequest& request,
    pw_software_update_BundledUpdateStatus& response) {
  std::lock_guard lock(mutex_);
  // Check preconditions.
  if (status_.state != pw_software_update_BundledUpdateState_Enum_INACTIVE) {
    SET_ERROR(pw_software_update_BundledUpdateResult_Enum_UNKNOWN_ERROR,
              "Start() can only be called from INACTIVE state. "
              "Current state: %d. Abort() then Reset() must be called first",
              static_cast<int>(status_.state));
    response = status_;
    return Status::FailedPrecondition();
  }
  PW_DCHECK(!status_.has_transfer_id);
  PW_DCHECK(!status_.has_result);
  PW_DCHECK(status_.current_state_progress_hundreth_percent == 0);
  PW_DCHECK(status_.bundle_filename[0] == '\0');
  PW_DCHECK(status_.note.size == 0);

  // Notify the backend of pending transfer.
  if (const Status status = backend_.BeforeUpdateStart(); !status.ok()) {
    SET_ERROR(pw_software_update_BundledUpdateResult_Enum_UNKNOWN_ERROR,
              "Backend error on BeforeUpdateStart()");
    response = status_;
    return status;
  }

  // Enable bundle transfer.
  Result<uint32_t> possible_transfer_id =
      backend_.EnableBundleTransferHandler(string::ClampedCString(
          request.bundle_filename, sizeof(request.bundle_filename)));
  if (!possible_transfer_id.ok()) {
    SET_ERROR(pw_software_update_BundledUpdateResult_Enum_TRANSFER_FAILED,
              "Couldn't enable bundle transfer");
    response = status_;
    return possible_transfer_id.status();
  }

  // Update state.
  status_.transfer_id = possible_transfer_id.value();
  status_.has_transfer_id = true;
  if (request.has_bundle_filename) {
    const StatusWithSize sws = string::Copy(request.bundle_filename,
                                            status_.bundle_filename,
                                            sizeof(status_.bundle_filename));
    PW_DCHECK_OK(sws.status(),
                 "bundle_filename options max_sizes do not match");
    status_.has_bundle_filename = true;
  }
  status_.state = pw_software_update_BundledUpdateState_Enum_TRANSFERRING;
  response = status_;
  return OkStatus();
}

// TODO: Check for "ABORTING" state and bail if it's set.
void BundledUpdateService::DoVerify() {
  {
    std::lock_guard guard(mutex_);
    if (status_.state == pw_software_update_BundledUpdateState_Enum_VERIFIED) {
      return;  // Already done!
    }

    // Ensure we're in the right state.
    if (status_.state !=
        pw_software_update_BundledUpdateState_Enum_TRANSFERRED) {
      SET_ERROR(pw_software_update_BundledUpdateResult_Enum_VERIFY_FAILED,
                "DoVerify() must be called from TRANSFERRED state. State: %d",
                static_cast<int>(status_.state));
      return;
    }

    status_.state = pw_software_update_BundledUpdateState_Enum_VERIFYING;
  }
  // Notify backend about pending verify.
  if (const Status status = backend_.BeforeBundleVerify(); !status.ok()) {
    std::lock_guard lock(mutex_);
    SET_ERROR(pw_software_update_BundledUpdateResult_Enum_VERIFY_FAILED,
              "Backend::BeforeBundleVerify() failed");
    return;
  }

  // Do the actual verify.
  ManifestAccessor manifest;  // TODO(pwbug/456): Place-holder for now.
  Status status = bundle_.OpenAndVerify(manifest);
  {
    std::lock_guard lock(mutex_);
    if (!status.ok()) {
      SET_ERROR(pw_software_update_BundledUpdateResult_Enum_VERIFY_FAILED,
                "Bundle::OpenAndVerify() failed");
      return;
    }
    bundle_open_ = true;
  }

  // Notify backend we're done verifying.
  status = backend_.AfterBundleVerified();
  {
    std::lock_guard lock(mutex_);
    if (!status.ok()) {
      SET_ERROR(pw_software_update_BundledUpdateResult_Enum_VERIFY_FAILED,
                "Backend::AfterBundleVerified() failed");
      return;
    }
    status_.state = pw_software_update_BundledUpdateState_Enum_VERIFIED;
  }
}

Status BundledUpdateService::Verify(
    ServerContext&,
    const pw_protobuf_Empty&,
    pw_software_update_BundledUpdateStatus& response) {
  std::lock_guard lock(mutex_);

  // Already done? Bail.
  if (status_.state == pw_software_update_BundledUpdateState_Enum_VERIFIED) {
    PW_LOG_DEBUG("Skipping verify since already verified");
    return OkStatus();
  }

  // TODO: Remove the transferring permitted state here ASAP.
  // Ensure we're in the right state.
  if ((status_.state !=
       pw_software_update_BundledUpdateState_Enum_TRANSFERRING) &&
      (status_.state !=
       pw_software_update_BundledUpdateState_Enum_TRANSFERRED)) {
    SET_ERROR(pw_software_update_BundledUpdateResult_Enum_VERIFY_FAILED,
              "Verify() must be called from TRANSFERRED state. State: %d",
              static_cast<int>(status_.state));
    response = status_;
    return Status::FailedPrecondition();
  }

  // TODO: We should probably make this mode idempotent.
  // Already doing what was asked? Bail.
  if (work_enqueued_) {
    PW_LOG_DEBUG("Verification is already active");
    return OkStatus();
  }

  // The backend's FinalizeApply as part of DoApply() shall be configured
  // such that this RPC can send out the reply before the device reboots.
  const Status status = work_queue_.PushWork([this] {
    {
      std::lock_guard y_lock(this->mutex_);
      PW_DCHECK(this->work_enqueued_);
    }
    this->DoVerify();
    {
      std::lock_guard y_lock(this->mutex_);
      this->work_enqueued_ = false;
    }
  });
  if (!status.ok()) {
    SET_ERROR(pw_software_update_BundledUpdateResult_Enum_VERIFY_FAILED,
              "Unable to equeue apply to work queue");
    response = status_;
    return status;
  }
  work_enqueued_ = true;

  response = status_;
  return OkStatus();
}

Status BundledUpdateService::Apply(
    ServerContext&,
    const pw_protobuf_Empty&,
    pw_software_update_BundledUpdateStatus& response) {
  std::lock_guard lock(mutex_);

  // We do not wait to go into a finished error state if we're already
  // applying, instead just let them know that yes we are working on it --
  // hold on.
  if (status_.state == pw_software_update_BundledUpdateState_Enum_APPLYING) {
    PW_LOG_DEBUG("Apply is already active");
    return OkStatus();
  }

  if ((status_.state !=
       pw_software_update_BundledUpdateState_Enum_TRANSFERRED) &&
      (status_.state != pw_software_update_BundledUpdateState_Enum_VERIFIED)) {
    SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
              "Apply() must be called from TRANSFERRED or VERIFIED state. "
              "State: %d",
              static_cast<int>(status_.state));
    return Status::FailedPrecondition();
  }

  // TODO: We should probably make these all idempotent properly.
  if (work_enqueued_) {
    PW_LOG_DEBUG("Apply is already active");
    return OkStatus();
  }

  // The backend's FinalizeApply as part of DoApply() shall be configured
  // such that this RPC can send out the reply before the device reboots.
  const Status status = work_queue_.PushWork([this] {
    {
      std::lock_guard y_lock(this->mutex_);
      PW_DCHECK(this->work_enqueued_);
    }
    // Error reporting is handled in DoVerify and DoApply.
    this->DoVerify();
    this->DoApply();
    {
      std::lock_guard y_lock(this->mutex_);
      this->work_enqueued_ = false;
    }
  });
  if (!status.ok()) {
    SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
              "Unable to equeue apply to work queue");
    response = status_;
    return status;
  }
  work_enqueued_ = true;

  return OkStatus();
}

void BundledUpdateService::DoApply() {
  {
    std::lock_guard guard(mutex_);

    PW_LOG_DEBUG("Attempting to apply the update");
    if (status_.state != pw_software_update_BundledUpdateState_Enum_VERIFIED) {
      std::lock_guard lock(mutex_);
      SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
                "Apply() must be called from VERIFIED state. State: %d",
                static_cast<int>(status_.state));
      return;
    }
    status_.state = pw_software_update_BundledUpdateState_Enum_APPLYING;
  }

  protobuf::StringToMessageMap signed_targets_metadata_map =
      bundle_.GetDecoder().AsStringToMessageMap(static_cast<uint32_t>(
          pw::software_update::UpdateBundle::Fields::TARGETS_METADATA));
  if (const Status status = signed_targets_metadata_map.status();
      !status.ok()) {
    std::lock_guard lock(mutex_);
    SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
              "Update bundle does not contain the targets_metadata map: %d",
              static_cast<int>(status.code()));
    return;
  }

  // There should only be one element in the map, which is the top-level
  // targets metadata.
  constexpr std::string_view kTopLevelTargetsName = "targets";
  protobuf::Message signed_targets_metadata =
      signed_targets_metadata_map[kTopLevelTargetsName];
  if (const Status status = signed_targets_metadata.status(); !status.ok()) {
    std::lock_guard lock(mutex_);
    SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
              "The targets_metadata map does not contain the targets entry: %d",
              static_cast<int>(status.code()));
    return;
  }

  protobuf::Message targets_metadata = signed_targets_metadata.AsMessage(
      static_cast<uint32_t>(pw::software_update::SignedTargetsMetadata::Fields::
                                SERIALIZED_TARGETS_METADATA));
  if (const Status status = targets_metadata.status(); !status.ok()) {
    std::lock_guard lock(mutex_);
    SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
              "The targets targets_metadata entry does not contain the "
              "serialized_target_metadata: %d",
              static_cast<int>(status.code()));
    return;
  }

  protobuf::RepeatedMessages target_files =
      targets_metadata.AsRepeatedMessages(static_cast<uint32_t>(
          pw::software_update::TargetsMetadata::Fields::TARGET_FILES));
  if (const Status status = target_files.status(); !status.ok()) {
    std::lock_guard lock(mutex_);
    SET_ERROR(
        pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
        "The serialized_target_metadata does not contain target_files: %d",
        static_cast<int>(status.code()));
    return;
  }

  // In order to report apply progress, quickly scan to see how many bytes will
  // be applied.
  size_t target_file_bytes_to_apply = 0;
  protobuf::StringToBytesMap target_payloads =
      bundle_.GetDecoder().AsStringToBytesMap(static_cast<uint32_t>(
          pw::software_update::UpdateBundle::Fields::TARGET_PAYLOADS));
  if (!target_payloads.status().ok()) {
    std::lock_guard lock(mutex_);
    SET_ERROR(
        pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
        "Failed to iterate the UpdateBundle target_payloads map entries: %d",
        static_cast<int>(target_payloads.status().code()));
    return;
  }
  for (pw::protobuf::StringToBytesMapEntry target_payload : target_payloads) {
    protobuf::Bytes target_payload_bytes = target_payload.Value();
    if (!target_payload_bytes.status().ok()) {
      std::lock_guard lock(mutex_);
      SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
                "Failed to read a UpdateBundle target_payloads map entry: %d",
                static_cast<int>(target_payload_bytes.status().code()));
      return;
    }
    target_file_bytes_to_apply +=
        target_payload_bytes.GetBytesReader().ConservativeReadLimit();
  }

  size_t target_file_bytes_applied = 0;
  for (pw::protobuf::Message file_name : target_files) {
    // TODO: Use a config.h parameter for this.
    constexpr size_t kFileNameMaxSize = 32;
    std::array<std::byte, kFileNameMaxSize> buf = {};
    protobuf::String name = file_name.AsString(static_cast<uint32_t>(
        pw::software_update::TargetFile::Fields::FILE_NAME));
    if (!name.status().ok()) {
      std::lock_guard lock(mutex_);
      SET_ERROR(
          pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
          "The serialized_target_metadata failed to iterate target files: %d",
          static_cast<int>(name.status().code()));
      return;
    }
    const Result<ByteSpan> read_result = name.GetBytesReader().Read(buf);
    if (!read_result.ok()) {
      std::lock_guard lock(mutex_);
      SET_ERROR(
          pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
          "The serialized_target_metadata failed to read target filename: %d",
          static_cast<int>(read_result.status().code()));
      return;
    }
    const ConstByteSpan file_name_span = read_result.value();
    const std::string_view file_name_view(
        reinterpret_cast<const char*>(file_name_span.data()),
        file_name_span.size_bytes());
    stream::IntervalReader file_reader =
        bundle_.GetTargetPayload(file_name_view);
    const size_t bundle_offset = file_reader.start();
    if (const Status status = backend_.ApplyTargetFile(
            file_name_view, file_reader, bundle_offset);
        !status.ok()) {
      std::lock_guard lock(mutex_);
      SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
                "Failed to apply target file: %d",
                static_cast<int>(status.code()));
      return;
    }
    target_file_bytes_applied += file_reader.interval_size();
    const uint32_t progress_hundreth_percent =
        (static_cast<uint64_t>(target_file_bytes_applied) * 100 * 100) /
        target_file_bytes_to_apply;
    PW_LOG_DEBUG("Apply progress: %d/%d Bytes (%ld%%)",
                 target_file_bytes_applied,
                 target_file_bytes_to_apply,
                 progress_hundreth_percent / 100);
    {
      std::lock_guard lock(mutex_);
      status_.current_state_progress_hundreth_percent =
          progress_hundreth_percent;
      status_.has_current_state_progress_hundreth_percent = true;
    }
  }

  // Finalize the apply.
  //
  // TODO(davidrogers): Ensure the backend documentation and API contract is
  // clear in regards to the flushing expectations for RPCs and logs surrounding
  // the reboot inside of this call.
  if (const Status status = backend_.FinalizeApply(); !status.ok()) {
    std::lock_guard lock(mutex_);
    SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
              "Failed to apply target file: %d",
              static_cast<int>(status.code()));
    return;
  }
  {
    std::lock_guard lock(mutex_);
    status_.current_state_progress_hundreth_percent = 0;
    status_.has_current_state_progress_hundreth_percent = false;
    status_.state = pw_software_update_BundledUpdateState_Enum_FINISHED;
    status_.result = pw_software_update_BundledUpdateResult_Enum_SUCCESS;
  }
}

Status BundledUpdateService::Abort(
    ServerContext&,
    const pw_protobuf_Empty&,
    pw_software_update_BundledUpdateStatus& response) {
  std::lock_guard lock(mutex_);
  if (status_.state == pw_software_update_BundledUpdateState_Enum_APPLYING) {
    return Status::FailedPrecondition();
  }

  if (status_.state == pw_software_update_BundledUpdateState_Enum_INACTIVE ||
      status_.state == pw_software_update_BundledUpdateState_Enum_FINISHED) {
    SET_ERROR(pw_software_update_BundledUpdateResult_Enum_UNKNOWN_ERROR,
              "Tried to abort when already INACTIVE or FINISHED");
    return Status::FailedPrecondition();
  }
  // TODO: Switch abort to async; this state change isn't externally visible.
  status_.state = pw_software_update_BundledUpdateState_Enum_ABORTING;

  SET_ERROR(pw_software_update_BundledUpdateResult_Enum_ABORTED,
            "Update abort requested");
  response = status_;
  return OkStatus();
}

Status BundledUpdateService::Reset(
    ServerContext&,
    const pw_protobuf_Empty&,
    pw_software_update_BundledUpdateStatus& response) {
  std::lock_guard lock(mutex_);

  if (status_.state == pw_software_update_BundledUpdateState_Enum_INACTIVE) {
    return OkStatus();  // Already done.
  }

  if (status_.state != pw_software_update_BundledUpdateState_Enum_FINISHED) {
    SET_ERROR(
        pw_software_update_BundledUpdateResult_Enum_UNKNOWN_ERROR,
        "Reset() must be called from FINISHED or INACTIVE state. State: %d",
        static_cast<int>(status_.state));
    response = status_;
    return Status::FailedPrecondition();
  }

  status_ = {};
  status_.state = pw_software_update_BundledUpdateState_Enum_INACTIVE;

  // Reset the bundle.
  if (bundle_open_) {
    // TODO: Revisit whether this is recoverable; maybe eliminate CHECK.
    PW_CHECK_OK(bundle_.Close());
    bundle_open_ = false;
  }

  response = status_;
  return OkStatus();
}

void BundledUpdateService::NotifyTransferSucceeded() {
  std::lock_guard lock(mutex_);

  if (status_.state !=
      pw_software_update_BundledUpdateState_Enum_TRANSFERRING) {
    // This can happen if the update gets Abort()'d during the transfer and
    // the transfer completes successfuly.
    PW_LOG_WARN(
        "Got transfer succeeded notification when not in TRANSFERRING state. "
        "State: %d",
        static_cast<int>(status_.state));
    return;
  }

  PW_DCHECK(status_.has_transfer_id);
  backend_.DisableBundleTransferHandler();
  status_.has_transfer_id = false;
  status_.state = pw_software_update_BundledUpdateState_Enum_TRANSFERRED;
}

}  // namespace pw::software_update
