// Copyright 2021 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 "third_party/iwlwifi/test/mock-device.h"

#include <algorithm>

MockDevice::MockDevice(device_add_args_t* args, MockDevice* parent)
    : parent_(parent), ops_(args->ops), ctx_(args->ctx), name_(args->name) {
  if (args->proto_id && args->proto_ops) {
    AddProtocol(args->proto_id, args->proto_ops, ctx_);
  }
  if (args->props) {
    props_.insert(props_.begin(), args->props, args->props + args->prop_count);
  }
  if (args->str_props) {
    str_props_.insert(str_props_.begin(), args->str_props, args->str_props + args->str_prop_count);
  }
  if (args->metadata_list && args->metadata_count > 0) {
    for (size_t i = 0; i < args->metadata_count; ++i) {
      SetMetadata(args->metadata_list[i].type, args->metadata_list[i].data,
                  args->metadata_list[i].length);
    }
  }

  if (args->client_remote) {
    client_remote_ = zx::channel(args->client_remote);
  }
  inspect_ = zx::vmo(args->inspect_vmo);
}

// static
std::shared_ptr<MockDevice> MockDevice::FakeRootParent() {
  // Using `new` to access a non-public constructor.
  return std::shared_ptr<MockDevice>(new MockDevice());
}

// Static member function.
zx_status_t MockDevice::Create(device_add_args_t* args, MockDevice* parent, MockDevice** out_dev) {
  // We only check the minimum requirements to make sure the mock does not crash:
  if (!parent || !args || !args->name) {
    return ZX_ERR_INVALID_ARGS;
  }

  // Using `new` to access a non-public constructor.
  auto new_device = std::shared_ptr<MockDevice>(new MockDevice(args, parent));
  if (out_dev) {
    *out_dev = new_device.get();
  }
  parent->children_.emplace_back(std::move(new_device));
  // PropagateMetadata to last child:
  for (const auto& [key, value] : parent->metadata_) {
    parent->children().back()->metadata_[key] = value;
  }
  parent->children().back()->PropagateMetadata();
  return ZX_OK;
}

MockDevice* MockDevice::GetLatestChild() {
  if (child_count()) {
    return children_.back().get();
  }
  return nullptr;
}

// Templates that dispatch the protocol operations if they were set.
// If they were not set, the second parameter is returned to the caller
// (usually ZX_ERR_NOT_SUPPORTED)
template <typename RetType, typename... ArgTypes>
RetType Dispatch(void* ctx, RetType (*op)(void* ctx, ArgTypes...), RetType fallback,
                 ArgTypes... args) {
  return op ? (*op)(ctx, args...) : fallback;
}

template <typename... ArgTypes>
void Dispatch(void* ctx, void (*op)(void* ctx, ArgTypes...), ArgTypes... args) {
  if (op) {
    (*op)(ctx, args...);
  }
}

void MockDevice::InitOp() { Dispatch(ctx_, ops_->init); }

zx_status_t MockDevice::OpenOp(zx_device_t** dev_out, uint32_t flags) {
  return Dispatch(ctx_, ops_->open, ZX_OK, dev_out, flags);
}

zx_status_t MockDevice::CloseOp(uint32_t flags) {
  return Dispatch(ctx_, ops_->close, ZX_OK, flags);
}

void MockDevice::UnbindOp() { Dispatch(ctx_, ops_->unbind); }

void MockDevice::ReleaseOp() {
  Dispatch(ctx_, ops_->release);
  // Make parent release child now
  for (auto it = parent_->children_.begin(); it != parent_->children_.end(); ++it) {
    if (it->get() == this) {
      parent_->children_.erase(it);
      return;
    }
  }
  // Print error: we did not find ourselves!
}

MockDevice::~MockDevice() {
  while (!children_.empty()) {
    // This should remove the first child device from children_:
    children_.front()->ReleaseOp();
  }
}

void MockDevice::SuspendNewOp(uint8_t requested_state, bool enable_wake, uint8_t suspend_reason) {
  Dispatch(ctx_, ops_->suspend, requested_state, enable_wake, suspend_reason);
}

zx_status_t MockDevice::SetPerformanceStateOp(uint32_t requested_state, uint32_t* out_state) {
  return Dispatch(ctx_, ops_->set_performance_state, ZX_ERR_NOT_SUPPORTED, requested_state,
                  out_state);
}

zx_status_t MockDevice::ConfigureAutoSuspendOp(bool enable, uint8_t requested_state) {
  return Dispatch(ctx_, ops_->configure_auto_suspend, ZX_ERR_NOT_SUPPORTED, enable,
                  requested_state);
}

void MockDevice::ResumeNewOp(uint32_t requested_state) {
  Dispatch(ctx_, ops_->resume, requested_state);
}

zx_status_t MockDevice::ReadOp(void* buf, size_t count, zx_off_t off, size_t* actual) {
  return Dispatch(ctx_, ops_->read, ZX_ERR_NOT_SUPPORTED, buf, count, off, actual);
}

zx_status_t MockDevice::WriteOp(const void* buf, size_t count, zx_off_t off, size_t* actual) {
  return Dispatch(ctx_, ops_->write, ZX_ERR_NOT_SUPPORTED, buf, count, off, actual);
}

zx_off_t MockDevice::GetSizeOp() { return Dispatch(ctx_, ops_->get_size, 0lu); }

zx_status_t MockDevice::MessageOp(fidl_incoming_msg_t* msg, fidl_txn_t* txn) {
  return Dispatch(ctx_, ops_->message, ZX_ERR_NOT_SUPPORTED, msg, txn);
}

void MockDevice::ChildPreReleaseOp(void* child_ctx) {
  Dispatch(ctx_, ops_->child_pre_release, child_ctx);
}

void MockDevice::SetSize(size_t size) { size_ = size; }

zx_off_t MockDevice::GetSize() {
  if (size_ == 0) {
    size_ = GetSizeOp();
  }
  return size_;
}

void MockDevice::SetMetadata(uint32_t type, const void* data, size_t data_length) {
  std::vector<uint8_t> owned(data_length);
  memcpy(owned.data(), data, data_length);
  metadata_[type] = std::move(owned);
  PropagateMetadata();
}

void MockDevice::SetVariable(const char* name, const char* data) {
  if (data) {
    std::string owned(data);
    variables_[name] = std::move(owned);
  } else {
    auto itr = variables_.find(name);
    if (itr != variables_.end()) {
      variables_.erase(itr);
    }
  }
}

zx_status_t MockDevice::GetMetadata(uint32_t type, void* buf, size_t buflen, size_t* actual) {
  auto itr = metadata_.find(type);
  if (itr != metadata_.end()) {
    auto& metadata = itr->second;
    *actual = metadata.size();
    if (buflen < metadata.size()) {
      return ZX_ERR_BUFFER_TOO_SMALL;
    }

    memcpy(buf, metadata.data(), metadata.size());
    return ZX_OK;
  }
  return ZX_ERR_NOT_FOUND;
}

zx_status_t MockDevice::GetMetadataSize(uint32_t type, size_t* out_size) {
  auto itr = metadata_.find(type);
  if (itr != metadata_.end()) {
    auto metadata = itr->second;
    *out_size = metadata.size();
    return ZX_OK;
  }
  return ZX_ERR_BAD_STATE;
}

zx_status_t MockDevice::GetVariable(const char* name, char* out, size_t size, size_t* actual) {
  auto itr = variables_.find(name);
  if (itr == variables_.end()) {
    return ZX_ERR_NOT_FOUND;
  }

  auto& variable = itr->second;
  if (actual) {
    *actual = variable.size();
  }
  if (size < variable.size()) {
    return ZX_ERR_BUFFER_TOO_SMALL;
  }

  strncpy(out, variable.data(), size);
  return ZX_OK;
}

void MockDevice::PropagateMetadata() {
  for (auto& child : children_) {
    for (const auto& [key, value] : metadata_) {
      child->metadata_[key] = value;
    }
    child->PropagateMetadata();
  }
}

void MockDevice::AddProtocol(uint32_t id, const void* ops, void* ctx, const char* fragment_name) {
  protocols_[fragment_name].push_back(mock_ddk::ProtocolEntry{id, {ops, ctx}});
}

void MockDevice::AddFidlProtocol(const char* protocol_name, mock_ddk::ConnectCallback callback,
                                 const char* name) {
  fidl_protocols_.try_emplace(name, std::unordered_map<std::string, mock_ddk::ConnectCallback>());
  fidl_protocols_[name][protocol_name] = std::move(callback);
}

void MockDevice::SetFirmware(std::vector<uint8_t> firmware, std::string_view path) {
  firmware_[path] = std::move(firmware);
}

void MockDevice::SetFirmware(std::string firmware, std::string_view path) {
  std::vector<uint8_t> vec(firmware.begin(), firmware.end());
  SetFirmware(vec, path);
}

zx_status_t MockDevice::LoadFirmware(std::string_view path, zx_handle_t* fw, size_t* size) {
  auto firmware = firmware_.find(path);
  // If a match is not found to 'path', check if there is a firmware that was loaded with
  // path == nullptr:
  if (firmware == firmware_.end()) {
    firmware = firmware_.find("");
  }
  if (firmware == firmware_.end()) {
    return ZX_ERR_NOT_FOUND;
  }
  zx_status_t status = ZX_OK;
  zx_handle_t vmo = ZX_HANDLE_INVALID;
  if ((status = zx_vmo_create(firmware->second.size(), 0, &vmo)) != ZX_OK) {
    return status;
  }
  if ((status = zx_vmo_write(vmo, firmware->second.data(), 0, firmware->second.size())) != ZX_OK) {
    return status;
  }

  *fw = vmo;
  *size = firmware->second.size();
  return ZX_OK;
}

zx_status_t MockDevice::GetProtocol(uint32_t proto_id, void* protocol,
                                    const char* fragment_name) const {
  // Check if there are protocols for the fragment/device:
  auto protocol_set = protocols_.find(fragment_name);
  if (protocol_set == protocols_.end()) {
    return ZX_ERR_NOT_SUPPORTED;
  }
  auto out = reinterpret_cast<mock_ddk::Protocol*>(protocol);
  // First we check if the user has added protocols:
  for (const auto& proto : protocol_set->second) {
    if (proto_id == proto.id) {
      out->ops = proto.proto.ops;
      out->ctx = proto.proto.ctx;
      return ZX_OK;
    }
  }
  return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t MockDevice::ConnectToFidlProtocol(const char* protocol_name, zx::channel request,
                                              const char* fragment_name) {
  // Check if there are protocols for the fragment/device:
  auto protocol_set = fidl_protocols_.find(fragment_name);
  if (protocol_set == fidl_protocols_.end()) {
    return ZX_ERR_NOT_SUPPORTED;
  }
  auto callback = protocol_set->second.find(protocol_name);
  if (callback == protocol_set->second.end()) {
    return ZX_ERR_NOT_FOUND;
  }
  return callback->second(std::move(request));
}

size_t MockDevice::descendant_count() const {
  size_t count = child_count();
  for (auto& child : children_) {
    count += child->descendant_count();
  }
  return count;
}

void MockDevice::SetDispatcher(async_dispatcher_t* dispatcher) {
  ZX_ASSERT_MSG(dispatcher_ == nullptr, "Dispatcher for '%s' cannot be changed after it is set.",
                name());
  dispatcher_ = dispatcher;
}

// helper functions:
namespace {

zx_status_t ProcessDeviceRemoval(MockDevice* device) {
  device->UnbindOp();
  // deleting children, so use a while loop:
  while (!device->children().empty()) {
    auto status = ProcessDeviceRemoval(device->children().back().get());
    if (status != ZX_OK) {
      return status;
    }
  }
  if (device->HasUnbindOp()) {
    zx_status_t status = device->WaitUntilUnbindReplyCalled();
    if (status != ZX_OK) {
      return status;
    }
  }
  device->ReleaseOp();
  return ZX_OK;
}
}  // anonymous namespace

zx_status_t mock_ddk::ReleaseFlaggedDevices(MockDevice* device) {
  if (device->AsyncRemoveCalled()) {
    return ProcessDeviceRemoval(device);
  }
  // Make a vector of the child device pointers, because we might delete the child:
  std::vector<MockDevice*> children;
  std::transform(device->children().begin(), device->children().end(), std::back_inserter(children),
                 [](std::shared_ptr<MockDevice> c) -> MockDevice* { return c.get(); });
  for (auto child : children) {
    auto ret = ReleaseFlaggedDevices(child);
    if (ret != ZX_OK) {
      return ret;
    }
  }
  return ZX_OK;
}
