// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "fake-paver.h"

#include <fidl/fuchsia.paver/cpp/common_types.h>
#include <lib/fzl/vmo-mapper.h>
#include <zircon/errors.h>

namespace paver_test {

void FakePaver::Connect(async_dispatcher_t* dispatcher,
                        fidl::ServerEnd<fuchsia_paver::Paver> request) {
  dispatcher_ = dispatcher;
  fidl::BindServer(dispatcher, std::move(request), this);
}

void FakePaver::FindDataSink(FindDataSinkRequestView request,
                             FindDataSinkCompleter::Sync& _completer) {
  fidl::BindServer(
      dispatcher_,
      fidl::ServerEnd<fuchsia_paver::DynamicDataSink>(request->data_sink.TakeChannel()), this);
}

void FakePaver::UseBlockDevice(UseBlockDeviceRequestView request,
                               UseBlockDeviceCompleter::Sync& _completer) {
  auto result = fidl::WireCall(fidl::UnownedClientEnd<fuchsia_device::Controller>(
                                   request->block_controller.borrow().channel()))
                    ->GetTopologicalPath();
  if (!result.ok() || result->is_error()) {
    return;
  }
  const auto& path = result->value()->path;
  {
    fbl::AutoLock al(&lock_);
    if (std::string(path.data(), path.size()) != expected_block_device_) {
      return;
    }
  }
  fidl::BindServer(dispatcher_, std::move(request->data_sink), this);
}

void FakePaver::FindBootManager(FindBootManagerRequestView request,
                                FindBootManagerCompleter::Sync& _completer) {
  fbl::AutoLock al(&lock_);
  AppendCommand(Command::kInitializeAbr);
  if (abr_supported_) {
    fidl::BindServer(dispatcher_, std::move(request->boot_manager), this);
  }
}

void FakePaver::QueryCurrentConfiguration(QueryCurrentConfigurationCompleter::Sync& completer) {
  fbl::AutoLock al(&lock_);
  AppendCommand(Command::kQueryCurrentConfiguration);
  completer.ReplySuccess(fuchsia_paver::wire::Configuration::kA);
}

void FakePaver::FindSysconfig(FindSysconfigRequestView request,
                              FindSysconfigCompleter::Sync& _completer) {}

void FakePaver::QueryActiveConfiguration(QueryActiveConfigurationCompleter::Sync& completer) {
  fbl::AutoLock al(&lock_);
  AppendCommand(Command::kQueryActiveConfiguration);

  // This is not quite the same logic as the paver uses, but for testing
  // purposes it is simpler and should be equivalent.
  // See:
  // https://cs.opensource.google/fuchsia/fuchsia/+/refs/heads/main:src/firmware/lib/abr/flow.c;l=80;drc=d0e362718c30f2e490c2e84607b6a37579058a17
  bool slot_a_active = abr_data_.slot_a.active && !abr_data_.slot_a.unbootable;
  bool slot_b_active = abr_data_.slot_b.active && !abr_data_.slot_b.unbootable;

  if (slot_a_active) {
    completer.ReplySuccess(fuchsia_paver::Configuration::kA);
    return;
  }

  if (slot_b_active) {
    completer.ReplySuccess(fuchsia_paver::Configuration::kB);
    return;
  }

  completer.ReplySuccess(fuchsia_paver::Configuration::kRecovery);
}

void FakePaver::QueryConfigurationLastSetActive(
    QueryConfigurationLastSetActiveCompleter::Sync& completer) {
  fbl::AutoLock al(&lock_);
  AppendCommand(Command::kQueryConfigurationLastSetActive);
  if (abr_data_.last_set_active.has_value()) {
    completer.ReplySuccess(abr_data_.last_set_active.value());
  } else {
    completer.ReplyError(ZX_ERR_NOT_FOUND);
  }
}

void FakePaver::QueryConfigurationStatus(QueryConfigurationStatusRequestView request,
                                         QueryConfigurationStatusCompleter::Sync& completer) {
  fbl::AutoLock al(&lock_);
  AppendCommand(Command::kQueryConfigurationStatus);
  AbrSlotData slot_data;
  zx_status_t status;
  switch (request->configuration) {
    case fuchsia_paver::wire::Configuration::kA:
      slot_data = abr_data_.slot_a;
      break;

    case fuchsia_paver::wire::Configuration::kB:
      slot_data = abr_data_.slot_b;
      status = ZX_OK;
      break;

    case fuchsia_paver::wire::Configuration::kRecovery:
      status = ZX_ERR_INVALID_ARGS;
      completer.ReplyError(status);
      return;
  }

  if (slot_data.unbootable) {
    completer.ReplySuccess(fuchsia_paver::wire::ConfigurationStatus::kUnbootable);
  } else if (!slot_data.healthy) {
    completer.ReplySuccess(fuchsia_paver::wire::ConfigurationStatus::kPending);
  } else {
    completer.ReplySuccess(fuchsia_paver::wire::ConfigurationStatus::kHealthy);
  }
}

void FakePaver::SetConfigurationActive(SetConfigurationActiveRequestView request,
                                       SetConfigurationActiveCompleter::Sync& completer) {
  fbl::AutoLock al(&lock_);
  AppendCommand(Command::kSetConfigurationActive);
  zx_status_t status;
  switch (request->configuration) {
    case fuchsia_paver::wire::Configuration::kA:
      abr_data_.slot_a.active = true;
      abr_data_.slot_b.active = false;

      abr_data_.slot_a.unbootable = false;
      abr_data_.slot_a.healthy = false;
      abr_data_.last_set_active = fuchsia_paver::Configuration::kA;
      status = ZX_OK;
      break;

    case fuchsia_paver::wire::Configuration::kB:
      abr_data_.slot_b.active = true;
      abr_data_.slot_a.active = false;

      abr_data_.slot_b.unbootable = false;
      abr_data_.slot_b.healthy = false;
      abr_data_.last_set_active = fuchsia_paver::Configuration::kB;
      status = ZX_OK;
      break;

    case fuchsia_paver::wire::Configuration::kRecovery:
      status = ZX_ERR_INVALID_ARGS;
      break;
  }
  completer.Reply(status);
}

void FakePaver::SetConfigurationUnbootable(SetConfigurationUnbootableRequestView request,
                                           SetConfigurationUnbootableCompleter::Sync& completer) {
  fbl::AutoLock al(&lock_);
  AppendCommand(Command::kSetConfigurationUnbootable);
  zx_status_t status;
  switch (request->configuration) {
    case fuchsia_paver::wire::Configuration::kA:
      abr_data_.slot_a.unbootable = true;
      abr_data_.slot_a.healthy = false;
      status = ZX_OK;
      break;

    case fuchsia_paver::wire::Configuration::kB:
      abr_data_.slot_b.unbootable = true;
      abr_data_.slot_b.healthy = false;
      status = ZX_OK;
      break;

    case fuchsia_paver::wire::Configuration::kRecovery:
      status = ZX_ERR_INVALID_ARGS;
      break;
  }
  completer.Reply(status);
}

void FakePaver::SetConfigurationHealthy(SetConfigurationHealthyRequestView request,
                                        SetConfigurationHealthyCompleter::Sync& completer) {
  fbl::AutoLock al(&lock_);
  AppendCommand(Command::kSetConfigurationHealthy);
  zx_status_t status;
  switch (request->configuration) {
    case fuchsia_paver::wire::Configuration::kA:
      abr_data_.slot_a.unbootable = false;
      abr_data_.slot_a.healthy = true;
      status = ZX_OK;
      break;

    case fuchsia_paver::wire::Configuration::kB:
      abr_data_.slot_b.unbootable = false;
      abr_data_.slot_b.healthy = true;
      status = ZX_OK;
      break;

    case fuchsia_paver::wire::Configuration::kRecovery:
      status = ZX_ERR_INVALID_ARGS;
      break;
  }
  completer.Reply(status);
}

void FakePaver::SetOneShotRecovery(SetOneShotRecoveryCompleter::Sync& completer) {
  completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
}

void FakePaver::Flush(
    fidl::WireServer<fuchsia_paver::DynamicDataSink>::FlushCompleter::Sync& completer) {
  fbl::AutoLock al(&lock_);
  AppendCommand(Command::kDataSinkFlush);
  completer.Reply(ZX_OK);
}

void FakePaver::Flush(
    fidl::WireServer<fuchsia_paver::BootManager>::FlushCompleter::Sync& completer) {
  fbl::AutoLock al(&lock_);
  AppendCommand(Command::kBootManagerFlush);
  completer.Reply(ZX_OK);
}

void FakePaver::ReadAsset(ReadAssetRequestView request, ReadAssetCompleter::Sync& completer) {
  fbl::AutoLock al(&lock_);
  AppendCommand(Command::kReadAsset);
  completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
}

void FakePaver::WriteAsset(WriteAssetRequestView request, WriteAssetCompleter::Sync& completer) {
  fbl::AutoLock al(&lock_);
  AppendCommand(Command::kWriteAsset);
  auto status = request->payload.size == expected_payload_size_ ? ZX_OK : ZX_ERR_INVALID_ARGS;
  last_asset_ = request->asset;
  last_asset_config_ = request->configuration;
  completer.Reply(status);
}

void FakePaver::WriteOpaqueVolume(WriteOpaqueVolumeRequestView request,
                                  WriteOpaqueVolumeCompleter::Sync& completer) {
  fbl::AutoLock al(&lock_);
  AppendCommand(Command::kWriteOpaqueVolume);
  if (request->payload.size == expected_payload_size_) {
    completer.ReplySuccess();
  } else {
    completer.ReplyError(ZX_ERR_INVALID_ARGS);
  }
}

void FakePaver::WriteSparseVolume(WriteSparseVolumeRequestView request,
                                  WriteSparseVolumeCompleter::Sync& completer) {
  fbl::AutoLock al(&lock_);
  AppendCommand(Command::kWriteSparseVolume);
  if (request->payload.size == expected_payload_size_) {
    completer.ReplySuccess();
  } else {
    completer.ReplyError(ZX_ERR_INVALID_ARGS);
  }
}

void FakePaver::WriteFirmware(WriteFirmwareRequestView request,
                              WriteFirmwareCompleter::Sync& completer) {
  using fuchsia_paver::wire::WriteFirmwareResult;
  fbl::AutoLock al(&lock_);
  AppendCommand(Command::kWriteFirmware);
  last_firmware_type_ = std::string(request->type.data(), request->type.size());
  last_firmware_config_ = request->configuration;

  // Reply varies depending on whether we support |type| or not.
  if (supported_firmware_type_ == std::string_view(request->type.data(), request->type.size())) {
    auto status = request->payload.size == expected_payload_size_ ? ZX_OK : ZX_ERR_INVALID_ARGS;
    completer.Reply(WriteFirmwareResult::WithStatus(status));
  } else {
    completer.Reply(WriteFirmwareResult::WithUnsupported(true));
  }
}

void FakePaver::ReadFirmware(ReadFirmwareRequestView request,
                             ReadFirmwareCompleter::Sync& completer) {
  completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
}

void FakePaver::WriteVolumes(WriteVolumesRequestView request,
                             WriteVolumesCompleter::Sync& completer) {
  {
    fbl::AutoLock al(&lock_);
    AppendCommand(Command::kWriteVolumes);
  }
  // Register VMO.
  zx::vmo vmo;
  auto status = zx::vmo::create(1024, 0, &vmo);
  if (status != ZX_OK) {
    completer.Reply(status);
    return;
  }
  fidl::WireSyncClient stream{std::move(request->payload)};
  auto result = stream->RegisterVmo(std::move(vmo));
  status = result.ok() ? result.value().status : result.status();
  if (status != ZX_OK) {
    completer.Reply(status);
    return;
  }
  // Stream until EOF.
  status = [&]() {
    size_t data_transferred = 0;
    for (;;) {
      {
        fbl::AutoLock al(&lock_);
        if (wait_for_start_signal_) {
          al.release();
          sync_completion_wait(&start_signal_, ZX_TIME_INFINITE);
          sync_completion_reset(&start_signal_);
        } else {
          signal_size_ = expected_payload_size_ + 1;
        }
      }
      while (data_transferred < signal_size_) {
        auto result = stream->ReadData();
        if (!result.ok()) {
          return result.status();
        }
        const auto& response = result.value();
        switch (response.result.Which()) {
          case fuchsia_paver::wire::ReadResult::Tag::kErr:
            return response.result.err();
          case fuchsia_paver::wire::ReadResult::Tag::kEof:
            return data_transferred == expected_payload_size_ ? ZX_OK : ZX_ERR_INVALID_ARGS;
          case fuchsia_paver::wire::ReadResult::Tag::kInfo:
            data_transferred += response.result.info().size;
            continue;
          default:
            return ZX_ERR_INTERNAL;
        }
      }
      sync_completion_signal(&done_signal_);
    }
  }();

  sync_completion_signal(&done_signal_);

  completer.Reply(status);
}

void FakePaver::InitializePartitionTables(InitializePartitionTablesCompleter::Sync& completer) {
  fbl::AutoLock al(&lock_);
  AppendCommand(Command::kInitPartitionTables);
  completer.Reply(ZX_OK);
}

void FakePaver::WipePartitionTables(WipePartitionTablesCompleter::Sync& completer) {
  fbl::AutoLock al(&lock_);
  AppendCommand(Command::kWipePartitionTables);
  completer.Reply(ZX_OK);
}

void FakePaver::WaitForWritten(size_t size) {
  signal_size_ = size;
  sync_completion_signal(&start_signal_);
  sync_completion_wait(&done_signal_, ZX_TIME_INFINITE);
  sync_completion_reset(&done_signal_);
}

std::vector<Command> FakePaver::GetCommandTrace() {
  fbl::AutoLock al(&lock_);
  return command_trace_;
}

std::string FakePaver::last_firmware_type() const {
  fbl::AutoLock al(&lock_);
  return last_firmware_type_;
}

fuchsia_paver::wire::Configuration FakePaver::last_firmware_config() const {
  fbl::AutoLock al(&lock_);
  return last_firmware_config_;
}

fuchsia_paver::wire::Configuration FakePaver::last_asset_config() const {
  fbl::AutoLock al(&lock_);
  return last_asset_config_;
}

fuchsia_paver::wire::Asset FakePaver::last_asset() const {
  fbl::AutoLock al(&lock_);
  return last_asset_;
}

const std::string& FakePaver::data_file_path() const {
  fbl::AutoLock al(&lock_);
  return data_file_path_;
}

void FakePaver::set_supported_firmware_type(std::string type) {
  fbl::AutoLock al(&lock_);
  supported_firmware_type_ = std::move(type);
}

void FakePaver::set_expected_device(std::string expected) {
  fbl::AutoLock al(&lock_);
  expected_block_device_ = std::move(expected);
}

AbrData FakePaver::abr_data() {
  fbl::AutoLock al(&lock_);
  return abr_data_;
}

}  // namespace paver_test
