// 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.

#define PW_LOG_MODULE_NAME "PWSU"
#define PW_LOG_LEVEL PW_LOG_LEVEL_WARN

#include "pw_software_update/bundled_update_service.h"

#include <mutex>
#include <string_view>

#include "pw_log/log.h"
#include "pw_result/result.h"
#include "pw_software_update/config.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/string_builder.h"
#include "pw_string/util.h"
#include "pw_sync/borrow.h"
#include "pw_sync/mutex.h"
#include "pw_tokenizer/tokenize.h"

namespace pw::software_update {
namespace {
using BorrowedStatus =
    sync::BorrowedPointer<pw_software_update_BundledUpdateStatus, sync::Mutex>;
using BundledUpdateState = pw_software_update_BundledUpdateState_Enum;
using BundledUpdateStatus = pw_software_update_BundledUpdateStatus;

// TODO(keir): Convert all the CHECKs in the RPC service to gracefully report
// errors.
#define SET_ERROR(res, message, ...)                                          \
  do {                                                                        \
    PW_LOG_ERROR(message, __VA_ARGS__);                                       \
    if (!IsFinished()) {                                                      \
      Finish(res);                                                            \
      {                                                                       \
        BorrowedStatus borrowed_status = status_.acquire();                   \
        size_t note_size = sizeof(borrowed_status->note.bytes);               \
        PW_TOKENIZE_TO_BUFFER(                                                \
            borrowed_status->note.bytes, &(note_size), message, __VA_ARGS__); \
        borrowed_status->note.size = note_size;                               \
        borrowed_status->has_note = true;                                     \
      }                                                                       \
    }                                                                         \
  } while (false)
}  // namespace

Status BundledUpdateService::GetStatus(const pw_protobuf_Empty&,
                                       BundledUpdateStatus& response) {
  response = *status_.acquire();
  return OkStatus();
}

Status BundledUpdateService::Start(
    const pw_software_update_StartRequest& request,
    BundledUpdateStatus& response) {
  std::lock_guard lock(mutex_);
  // Check preconditions.
  const BundledUpdateState state = status_.acquire()->state;
  if (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>(state));
    response = *status_.acquire();
    return Status::FailedPrecondition();
  }

  {
    BorrowedStatus borrowed_status = status_.acquire();
    PW_DCHECK(!borrowed_status->has_transfer_id);
    PW_DCHECK(!borrowed_status->has_result);
    PW_DCHECK(borrowed_status->current_state_progress_hundreth_percent == 0);
    PW_DCHECK(borrowed_status->bundle_filename[0] == '\0');
    PW_DCHECK(borrowed_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_.acquire();
    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_.acquire();
    return possible_transfer_id.status();
  }

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

Status BundledUpdateService::SetTransferred(const pw_protobuf_Empty&,
                                            BundledUpdateStatus& response) {
  const BundledUpdateState state = status_.acquire()->state;

  if (state != pw_software_update_BundledUpdateState_Enum_TRANSFERRING &&
      state != pw_software_update_BundledUpdateState_Enum_INACTIVE) {
    std::lock_guard lock(mutex_);
    SET_ERROR(pw_software_update_BundledUpdateResult_Enum_UNKNOWN_ERROR,
              "SetTransferred() can only be called from TRANSFERRING or "
              "INACTIVE state. State: %d",
              static_cast<int>(state));
    response = *status_.acquire();
    return OkStatus();
  }

  NotifyTransferSucceeded();

  response = *status_.acquire();
  return OkStatus();
}

// TODO: Check for "ABORTING" state and bail if it's set.
void BundledUpdateService::DoVerify() {
  std::lock_guard guard(mutex_);
  const BundledUpdateState state = status_.acquire()->state;

  if (state == pw_software_update_BundledUpdateState_Enum_VERIFIED) {
    return;  // Already done!
  }

  // Ensure we're in the right state.
  if (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>(state));
    return;
  }

  status_.acquire()->state =
      pw_software_update_BundledUpdateState_Enum_VERIFYING;

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

  // Do the actual verify.
  Status status = bundle_.OpenAndVerify();
  if (!status.ok()) {
    SET_ERROR(pw_software_update_BundledUpdateResult_Enum_VERIFY_FAILED,
              "Bundle::OpenAndVerify() failed");
    return;
  }
  bundle_open_ = true;

  // Have the backend verify the user_manifest if present.
  if (!backend_.VerifyManifest(bundle_.GetManifest()).ok()) {
    SET_ERROR(pw_software_update_BundledUpdateResult_Enum_VERIFY_FAILED,
              "Backend::VerifyUserManifest() failed");
    return;
  }

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

Status BundledUpdateService::Verify(const pw_protobuf_Empty&,
                                    BundledUpdateStatus& response) {
  std::lock_guard lock(mutex_);
  const BundledUpdateState state = status_.acquire()->state;

  // Already done? Bail.
  if (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 ((state != pw_software_update_BundledUpdateState_Enum_TRANSFERRING) &&
      (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>(state));
    response = *status_.acquire();
    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 ApplyReboot 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_.acquire();
    return status;
  }
  work_enqueued_ = true;

  response = *status_.acquire();
  return OkStatus();
}

Status BundledUpdateService::Apply(const pw_protobuf_Empty&,
                                   BundledUpdateStatus& response) {
  std::lock_guard lock(mutex_);
  const BundledUpdateState state = status_.acquire()->state;

  // 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 (state == pw_software_update_BundledUpdateState_Enum_APPLYING) {
    PW_LOG_DEBUG("Apply is already active");
    return OkStatus();
  }

  if ((state != pw_software_update_BundledUpdateState_Enum_TRANSFERRED) &&
      (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>(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 ApplyReboot 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_.acquire();
    return status;
  }
  work_enqueued_ = true;

  return OkStatus();
}

void BundledUpdateService::DoApply() {
  std::lock_guard guard(mutex_);
  const BundledUpdateState state = status_.acquire()->state;

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

  status_.acquire()->state =
      pw_software_update_BundledUpdateState_Enum_APPLYING;

  if (const Status status = backend_.BeforeApply(); !status.ok()) {
    SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
              "BeforeApply() returned unsuccessful result: %d",
              static_cast<int>(status.code()));
    return;
  }

  // In order to report apply progress, quickly scan to see how many bytes
  // will be applied.
  Result<uint64_t> total_payload_bytes = bundle_.GetTotalPayloadSize();
  PW_CHECK_OK(total_payload_bytes.status());
  size_t target_file_bytes_to_apply =
      static_cast<size_t>(total_payload_bytes.value());

  protobuf::RepeatedMessages target_files =
      bundle_.GetManifest().GetTargetFiles();
  PW_CHECK_OK(target_files.status());

  size_t target_file_bytes_applied = 0;
  for (pw::protobuf::Message file_name : target_files) {
    std::array<std::byte, MAX_TARGET_NAME_LENGTH> buf = {};
    protobuf::String name = file_name.AsString(static_cast<uint32_t>(
        pw::software_update::TargetFile::Fields::FILE_NAME));
    PW_CHECK_OK(name.status());
    const Result<ByteSpan> read_result = name.GetBytesReader().Read(buf);
    PW_CHECK_OK(read_result.status());
    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());
    if (file_name_view.compare(kUserManifestTargetFileName) == 0) {
      continue;  // user_manifest is not applied by the backend.
    }
    // Try to get an IntervalReader for the current file.
    stream::IntervalReader file_reader =
        bundle_.GetTargetPayload(file_name_view);
    if (file_reader.status().IsNotFound()) {
      PW_LOG_INFO(
          "Contents of file %s missing from bundle; ignoring",
          pw::MakeString<MAX_TARGET_NAME_LENGTH>(file_name_view).c_str());
      continue;
    }
    if (!file_reader.ok()) {
      SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
                "Could not open contents of file %s from bundle; "
                "aborting update apply phase",
                MakeString<MAX_TARGET_NAME_LENGTH>(file_name_view).c_str());
      return;
    }

    const size_t bundle_offset = file_reader.start();
    if (const Status status = backend_.ApplyTargetFile(
            file_name_view, file_reader, bundle_offset);
        !status.ok()) {
      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: %zu/%zu Bytes (%ld%%)",
                 target_file_bytes_applied,
                 target_file_bytes_to_apply,
                 static_cast<unsigned long>(progress_hundreth_percent / 100));
    {
      BorrowedStatus borrowed_status = status_.acquire();
      borrowed_status->current_state_progress_hundreth_percent =
          progress_hundreth_percent;
      borrowed_status->has_current_state_progress_hundreth_percent = true;
    }
  }

  // TODO(davidrogers): Add new APPLY_REBOOTING to distinguish between pre and
  // post reboot.

  // Finalize the apply.
  if (const Status status = backend_.ApplyReboot(); !status.ok()) {
    SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
              "Failed to do the apply reboot: %d",
              static_cast<int>(status.code()));
    return;
  }

  // TODO(davidrogers): Move this to MaybeFinishApply() once available.
  Finish(pw_software_update_BundledUpdateResult_Enum_SUCCESS);
}

Status BundledUpdateService::Abort(const pw_protobuf_Empty&,
                                   BundledUpdateStatus& response) {
  std::lock_guard lock(mutex_);
  const BundledUpdateState state = status_.acquire()->state;

  if (state == pw_software_update_BundledUpdateState_Enum_APPLYING) {
    return Status::FailedPrecondition();
  }

  if (state == pw_software_update_BundledUpdateState_Enum_INACTIVE ||
      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_.acquire()->state =
      pw_software_update_BundledUpdateState_Enum_ABORTING;

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

Status BundledUpdateService::Reset(const pw_protobuf_Empty&,
                                   BundledUpdateStatus& response) {
  std::lock_guard lock(mutex_);
  const BundledUpdateState state = status_.acquire()->state;

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

  if (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>(state));
    response = *status_.acquire();
    return Status::FailedPrecondition();
  }

  {
    *status_.acquire() = {
        .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_.acquire();
  return OkStatus();
}

void BundledUpdateService::NotifyTransferSucceeded() {
  std::lock_guard lock(mutex_);
  const BundledUpdateState state = status_.acquire()->state;

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

  const bool transfer_ongoing = status_.acquire()->has_transfer_id;
  if (transfer_ongoing) {
    backend_.DisableBundleTransferHandler();
    status_.acquire()->has_transfer_id = false;
  } else {
    PW_LOG_WARN("No ongoing transfer found, forcefully set TRANSFERRED.");
  }

  status_.acquire()->state =
      pw_software_update_BundledUpdateState_Enum_TRANSFERRED;
}

void BundledUpdateService::Finish(
    pw_software_update_BundledUpdateResult_Enum result) {
  if (result == pw_software_update_BundledUpdateResult_Enum_SUCCESS) {
    BorrowedStatus borrowed_status = status_.acquire();
    borrowed_status->current_state_progress_hundreth_percent = 0;
    borrowed_status->has_current_state_progress_hundreth_percent = false;
  } else {
    // In the case of error, notify backend that we're about to abort the
    // software update.
    PW_CHECK_OK(backend_.BeforeUpdateAbort());
  }

  // Turn down the transfer if one is in progress.
  const bool transfer_ongoing = status_.acquire()->has_transfer_id;
  if (transfer_ongoing) {
    backend_.DisableBundleTransferHandler();
  }
  status_.acquire()->has_transfer_id = false;

  // Close out any open bundles.
  if (bundle_open_) {
    // TODO: Revisit this check; may be able to recover.
    PW_CHECK_OK(bundle_.Close());
    bundle_open_ = false;
  }
  {
    BorrowedStatus borrowed_status = status_.acquire();
    borrowed_status->state =
        pw_software_update_BundledUpdateState_Enum_FINISHED;
    borrowed_status->result = result;
    borrowed_status->has_result = true;
  }
}

}  // namespace pw::software_update
