// 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_pwpb.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<BundledUpdateStatus::Message, sync::Mutex>;

// 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 = borrowed_status->note.max_size();             \
        borrowed_status->note.resize(note_size);                         \
        PW_TOKENIZE_TO_BUFFER(                                           \
            &borrowed_status->note, &(note_size), message, __VA_ARGS__); \
        borrowed_status->note.resize(note_size);                         \
      }                                                                  \
    }                                                                    \
  } while (false)
}  // namespace

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

Status BundledUpdateService::Start(const StartRequest::Message& request,
                                   BundledUpdateStatus::Message& response) {
  std::lock_guard lock(mutex_);
  // Check preconditions.
  const BundledUpdateState::Enum state = status_.acquire()->state;
  if (state != BundledUpdateState::Enum::kInactive) {
    SET_ERROR(BundledUpdateResult::Enum::kUnknownError,
              "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->transfer_id.has_value());
    PW_DCHECK(!borrowed_status->result.has_value());
    PW_DCHECK(
        !borrowed_status->current_state_progress_hundreth_percent.has_value());
    PW_DCHECK(borrowed_status->bundle_filename.empty());
    PW_DCHECK(borrowed_status->note.empty());
  }

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

  // Enable bundle transfer.
  Result<uint32_t> possible_transfer_id =
      backend_.EnableBundleTransferHandler(request.bundle_filename);
  if (!possible_transfer_id.ok()) {
    SET_ERROR(BundledUpdateResult::Enum::kTransferFailed,
              "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();
    if (!request.bundle_filename.empty()) {
      borrowed_status->bundle_filename = request.bundle_filename;
    }
    borrowed_status->state = BundledUpdateState::Enum::kTransferring;
    response = *borrowed_status;
  }
  return OkStatus();
}

Status BundledUpdateService::SetTransferred(
    const pw::protobuf::Empty::Message&,
    BundledUpdateStatus::Message& response) {
  const BundledUpdateState::Enum state = status_.acquire()->state;

  if (state != BundledUpdateState::Enum::kTransferring &&
      state != BundledUpdateState::Enum::kInactive) {
    std::lock_guard lock(mutex_);
    SET_ERROR(BundledUpdateResult::Enum::kUnknownError,
              "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::Enum state = status_.acquire()->state;

  if (state == BundledUpdateState::Enum::kVerified) {
    return;  // Already done!
  }

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

  status_.acquire()->state = BundledUpdateState::Enum::kVerifying;

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

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

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

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

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

  // Already done? Bail.
  if (state == BundledUpdateState::Enum::kVerified) {
    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 != BundledUpdateState::Enum::kTransferring) &&
      (state != BundledUpdateState::Enum::kTransferred)) {
    SET_ERROR(BundledUpdateResult::Enum::kVerifyFailed,
              "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(BundledUpdateResult::Enum::kVerifyFailed,
              "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::Message&,
                                   BundledUpdateStatus::Message& response) {
  std::lock_guard lock(mutex_);
  const BundledUpdateState::Enum 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 == BundledUpdateState::Enum::kApplying) {
    PW_LOG_DEBUG("Apply is already active");
    return OkStatus();
  }

  if ((state != BundledUpdateState::Enum::kTransferred) &&
      (state != BundledUpdateState::Enum::kVerified)) {
    SET_ERROR(BundledUpdateResult::Enum::kApplyFailed,
              "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(BundledUpdateResult::Enum::kApplyFailed,
              "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::Enum state = status_.acquire()->state;

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

  status_.acquire()->state = BundledUpdateState::Enum::kApplying;

  if (const Status status = backend_.BeforeApply(); !status.ok()) {
    SET_ERROR(BundledUpdateResult::Enum::kApplyFailed,
              "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(BundledUpdateResult::Enum::kApplyFailed,
                "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(BundledUpdateResult::Enum::kApplyFailed,
                "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;
    }
  }

  // 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(BundledUpdateResult::Enum::kApplyFailed,
              "Failed to do the apply reboot: %d",
              static_cast<int>(status.code()));
    return;
  }

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

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

  if (state == BundledUpdateState::Enum::kApplying) {
    return Status::FailedPrecondition();
  }

  if (state == BundledUpdateState::Enum::kInactive ||
      state == BundledUpdateState::Enum::kFinished) {
    SET_ERROR(BundledUpdateResult::Enum::kUnknownError,
              "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 = BundledUpdateState::Enum::kAborting;

  SET_ERROR(BundledUpdateResult::Enum::kAborted, "Update abort requested");
  response = *status_.acquire();
  return OkStatus();
}

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

  if (state == BundledUpdateState::Enum::kInactive) {
    return OkStatus();  // Already done.
  }

  if (state != BundledUpdateState::Enum::kFinished) {
    SET_ERROR(
        BundledUpdateResult::Enum::kUnknownError,
        "Reset() must be called from FINISHED or INACTIVE state. State: %d",
        static_cast<int>(state));
    response = *status_.acquire();
    return Status::FailedPrecondition();
  }

  {
    BorrowedStatus status = status_.acquire();
    *status = {};  // Force-init all fields to zero.
    status->state = BundledUpdateState::Enum::kInactive;
  }

  // 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::Enum state = status_.acquire()->state;

  if (state != BundledUpdateState::Enum::kTransferring) {
    // 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()->transfer_id.has_value();
  if (transfer_ongoing) {
    backend_.DisableBundleTransferHandler();
    status_.acquire()->transfer_id.reset();
  } else {
    PW_LOG_WARN("No ongoing transfer found, forcefully set TRANSFERRED.");
  }

  status_.acquire()->state = BundledUpdateState::Enum::kTransferred;
}

void BundledUpdateService::Finish(BundledUpdateResult::Enum result) {
  if (result == BundledUpdateResult::Enum::kSuccess) {
    BorrowedStatus borrowed_status = status_.acquire();
    borrowed_status->current_state_progress_hundreth_percent.reset();
  } 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()->transfer_id.has_value();
  if (transfer_ongoing) {
    backend_.DisableBundleTransferHandler();
  }
  status_.acquire()->transfer_id.reset();

  // 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 = BundledUpdateState::Enum::kFinished;
    borrowed_status->result = result;
  }
}

}  // namespace pw::software_update
