// 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& request,
    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.view());
  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& request,
    BundledUpdateStatus::Message& response) {
  const BundledUpdateState::Enum state = status_.acquire()->state;

  if (state != BundledUpdateState::Enum::kTransferring &&
      state != BundledUpdateState::Enum::kInactive) {
    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& request,
                                    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& request,
                                   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",
                static_cast<int>(file_reader.status().code()));
      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& request,
                                   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& request,
                                   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();
  }

  { *status_.acquire() = {.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
