// Copyright 2018 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 <fuchsia/hardware/test/c/banjo.h>
#include <lib/ddk/binding_driver.h>
#include <lib/ddk/device.h>
#include <lib/ddk/driver.h>
#include <lib/fidl/cpp/wire/vector_view.h>
#include <lib/zircon-internal/thread_annotations.h>
#include <lib/zx/channel.h>
#include <lib/zx/vmo.h>
#include <stdio.h>
#include <threads.h>
#include <zircon/assert.h>
#include <zircon/errors.h>
#include <zircon/process.h>
#include <zircon/status.h>
#include <zircon/types.h>

#include <memory>
#include <optional>
#include <type_traits>
#include <variant>

#include <ddktl/device.h>
#include <fbl/array.h>
#include <fbl/auto_lock.h>
#include <fbl/mutex.h>
#include <fbl/vector.h>

#include "ddktl/suspend-txn.h"
#include "fidl.h"

namespace mock_device {

class MockDevice;
using MockDeviceType =
    ddk::Device<MockDevice, ddk::GetProtocolable, ddk::Initializable, ddk::Unbindable,
                ddk::Suspendable, ddk::Resumable, ddk::Rxrpcable>;

class MockDevice : public MockDeviceType {
 public:
  MockDevice(zx_device_t* device, fidl::ClientEnd<device_mock::MockDevice> controller);
  static zx_status_t Create(zx_device_t* parent,
                            fidl::ClientEnd<device_mock::MockDevice> controller,
                            std::unique_ptr<MockDevice>* out);

  // Device protocol implementation.
  void DdkRelease();
  zx_status_t DdkGetProtocol(uint32_t proto_id, void* out);
  void DdkInit(ddk::InitTxn txn) { txn.Reply(ZX_OK); }
  void DdkUnbind(ddk::UnbindTxn txn);
  void DdkSuspend(ddk::SuspendTxn txn);
  void DdkResume(ddk::ResumeTxn txn);
  zx_status_t DdkRxrpc(zx_handle_t channel);

  // Generate an invocation record for a hook RPC
  device_mock::wire::HookInvocation ConstructHookInvocation();
  static device_mock::wire::HookInvocation ConstructHookInvocation(uint64_t device_id);

  // Create a new thread that will serve a MockDeviceThread interface over |server_end|
  void CreateThread(fidl::ServerEnd<device_mock::MockDeviceThread> server_end);

 private:
  // Retrieve the current thread's process and thread koids
  static void GetThreadKoids(zx_koid_t* process, zx_koid_t* thread);

  static int ThreadFunc(void* arg);
  struct ThreadFuncArg {
    // channel that the thread will use to serve a MockDeviceThread
    // interface over
    fidl::ServerEnd<device_mock::MockDeviceThread> server_end;
    // Device this thread is executing for
    MockDevice* dev;
  };

  fbl::Mutex lock_;
  // List of threads spawned by Actions
  fbl::Vector<thrd_t> threads_ TA_GUARDED(lock_);

  // Our half of the controller channel.  We will send requests for input on
  // it.
  fidl::WireSyncClient<device_mock::MockDevice> controller_;
};

struct ProcessActionsContext {
  // A channel that is either borrowing (zx::unowned_channel) or
  // owned (ServerEnd).
  // In the borrowing case, the channel must outlive this variant.
  using ChannelVariants = std::variant<fidl::UnownedClientEnd<device_mock::MockDevice>,
                                       fidl::ServerEnd<device_mock::MockDeviceThread>>;

  // Constructs a process action context. Note that |channel_variants| must
  // outlive this context. Typically, the |channel_variants| is first created
  // on the caller's stack, after which |ProcessActionContext| is constructed
  // referencing it.
  ProcessActionsContext(ChannelVariants& channel_variants, bool has_hook_status,
                        MockDevice* mock_device, zx_device_t* device)
      : channel_variants(channel_variants),
        has_hook_status(has_hook_status),
        mock_device(mock_device),
        device(device) {}

  // IN: The channel that these actions came from.  Used for acknowledging
  // add/remove device requests.
  //
  // When this context is running in a separate thread, the context has the
  // |fidl::ServerEnd<device_mock::MockDeviceThread>| variant.
  // When this context is running in the same thread, the context has the
  // |zx::unowned_channel| variant, and is the client-end of the
  // MockDevice protocol.
  //
  // Note that in either case, the context does not own the underlying channel,
  // since this field is a reference. The channel is usually owned by a caller
  // which created the context.
  ChannelVariants& channel_variants;

  bool has_hook_status = false;
  // OUT: What should be returned by the hook
  zx_status_t hook_status = ZX_ERR_INTERNAL;
  // IN: A buffer that can be written to by actions (nullptr if none)
  void* associated_buf = nullptr;
  size_t associated_buf_count = 0;
  // OUT: Number of bytes written by actions
  size_t associated_buf_actual = 0;
  // IN/OUT: MockDevice to use for associating threads with.  NULL'd out if
  // remove was called.
  MockDevice* mock_device = nullptr;
  // IN/OUT: Device to use for invoking add_device/remove_device.  NULL'd out
  // if remove was called.
  zx_device_t* device = nullptr;

  // IN: The txn used to reply to the unbind hook.
  std::optional<ddk::UnbindTxn> pending_unbind_txn = std::nullopt;
  // IN: The txn used to reply to the suspend hook.
  std::optional<ddk::SuspendTxn> pending_suspend_txn = std::nullopt;
  // IN: The txn used to reply to the resume hook.
  std::optional<ddk::ResumeTxn> pending_resume_txn = std::nullopt;
};

// Helper struct to simplify matching an |std::variant|.
template <class... Ts>
struct matchers : Ts... {
  using Ts::operator()...;
};
template <class... Ts>
matchers(Ts...) -> matchers<Ts...>;

// Execute the actions returned by a hook
zx_status_t ProcessActions(fidl::VectorView<device_mock::wire::Action> actions,
                           ProcessActionsContext* ctx);

MockDevice::MockDevice(zx_device_t* device, fidl::ClientEnd<device_mock::MockDevice> controller)
    : MockDeviceType(device),
      controller_(fidl::WireSyncClient<device_mock::MockDevice>(std::move(controller))) {}

int MockDevice::ThreadFunc(void* raw_arg) {
  auto arg = std::unique_ptr<ThreadFuncArg>(static_cast<ThreadFuncArg*>(raw_arg));
  ProcessActionsContext::ChannelVariants server_end = std::move(arg->server_end);

  while (true) {
    fbl::Array<device_mock::wire::Action> actions;
    zx_status_t status = WaitForPerformActions(
        std::get<fidl::ServerEnd<device_mock::MockDeviceThread>>(server_end).channel(), &actions);
    if (status != ZX_OK) {
      ZX_ASSERT_MSG(status == ZX_ERR_STOP, "MockDevice thread exiting: %s\n",
                    zx_status_get_string(status));
      break;
    }
    ProcessActionsContext ctx(server_end, false, arg->dev, arg->dev->zxdev());
    status = ProcessActions(
        fidl::VectorView<device_mock::wire::Action>::FromExternal(actions.data(), actions.size()),
        &ctx);
    ZX_ASSERT_MSG(status == ZX_OK, "%s", zx_status_get_string(status));
    if (ctx.device == nullptr) {
      // If the device was removed, bail out since we're releasing.
      break;
    }
  }
  return 0;
}

void MockDevice::CreateThread(fidl::ServerEnd<device_mock::MockDeviceThread> server_end) {
  auto arg = std::make_unique<ThreadFuncArg>();
  arg->server_end = std::move(server_end);
  arg->dev = this;

  fbl::AutoLock guard(&lock_);
  thrd_t thrd;
  int ret = thrd_create(&thrd, MockDevice::ThreadFunc, arg.get());
  ZX_ASSERT(ret == thrd_success);
  // The thread now owns this pointer
  [[maybe_unused]] auto ptr = arg.release();

  threads_.push_back(thrd);
}

void MockDevice::GetThreadKoids(zx_koid_t* process, zx_koid_t* thread) {
  struct Koids {
    zx_koid_t process;
    zx_koid_t thread;
  };
  thread_local Koids thread_koids;

  if (thread_koids.process == 0 && thread_koids.thread == 0) {
    zx_info_handle_basic_t info;
    zx_status_t status = zx_object_get_info(zx_thread_self(), ZX_INFO_HANDLE_BASIC, &info,
                                            sizeof(info), nullptr, nullptr);
    ZX_ASSERT_MSG(status == ZX_OK, "%s", zx_status_get_string(status));
    thread_koids.process = info.related_koid;
    thread_koids.thread = info.koid;
  }

  *process = thread_koids.process;
  *thread = thread_koids.thread;
}

device_mock::wire::HookInvocation MockDevice::ConstructHookInvocation(uint64_t device_id) {
  device_mock::wire::HookInvocation invoc;
  GetThreadKoids(&invoc.process_koid, &invoc.thread_koid);
  invoc.device_id = device_id;
  return invoc;
}

device_mock::wire::HookInvocation MockDevice::ConstructHookInvocation() {
  return ConstructHookInvocation(reinterpret_cast<uintptr_t>(zxdev()));
}

void MockDevice::DdkRelease() {
  auto result = controller_->Release(ConstructHookInvocation());
  ZX_ASSERT_MSG(result.ok(), "%s", result.status_string());

  // Launch a thread to do the actual joining and delete, since this could get
  // called from a thread.
  thrd_t thrd;
  int ret = thrd_create(
      &thrd,
      [](void* arg) {
        auto me = static_cast<MockDevice*>(arg);
        {
          fbl::AutoLock guard(&me->lock_);
          for (auto& t : me->threads_) {
            thrd_join(t, nullptr);
          }
        }
        delete me;
        return 0;
      },
      this);
  ZX_ASSERT(ret == thrd_success);
  thrd_detach(thrd);
}

zx_status_t MockDevice::DdkGetProtocol(uint32_t proto_id, void* out) {
  auto result = controller_->GetProtocol(ConstructHookInvocation(), proto_id);
  ZX_ASSERT_MSG(result.ok(), "%s", result.status_string());
  ProcessActionsContext::ChannelVariants channel = controller_.client_end().borrow();
  ProcessActionsContext ctx(channel, true, this, zxdev());
  zx_status_t status = ProcessActions(result.value().actions, &ctx);
  ZX_ASSERT_MSG(status == ZX_OK, "%s", zx_status_get_string(status));
  return ctx.hook_status;
}

void MockDevice::DdkUnbind(ddk::UnbindTxn txn) {
  auto result = controller_->Unbind(ConstructHookInvocation());
  ZX_ASSERT_MSG(result.ok(), "%s", result.status_string());
  ProcessActionsContext::ChannelVariants channel = controller_.client_end().borrow();
  ProcessActionsContext ctx(channel, false, this, zxdev());
  ctx.pending_unbind_txn = std::move(txn);
  zx_status_t status = ProcessActions(result.value().actions, &ctx);
  ZX_ASSERT_MSG(status == ZX_OK, "%s", zx_status_get_string(status));
}

void MockDevice::DdkSuspend(ddk::SuspendTxn txn) {
  auto result = controller_->Suspend(ConstructHookInvocation(), txn.requested_state(),
                                     txn.enable_wake(), txn.suspend_reason());
  ZX_ASSERT_MSG(result.ok(), "%s", result.status_string());
  ProcessActionsContext::ChannelVariants channel = controller_.client_end().borrow();
  ProcessActionsContext ctx(channel, true, this, zxdev());
  ctx.pending_suspend_txn = std::move(txn);
  zx_status_t status = ProcessActions(result.value().actions, &ctx);
  ZX_ASSERT_MSG(status == ZX_OK, "%s", zx_status_get_string(status));
}

void MockDevice::DdkResume(ddk::ResumeTxn txn) {
  auto result = controller_->Resume(ConstructHookInvocation(), txn.requested_state());
  ZX_ASSERT_MSG(result.ok(), "%s", result.status_string());
  ProcessActionsContext::ChannelVariants channel = controller_.client_end().borrow();
  ProcessActionsContext ctx(channel, true, this, zxdev());
  ctx.pending_resume_txn = std::move(txn);
  zx_status_t status = ProcessActions(result.value().actions, &ctx);
  ZX_ASSERT_MSG(status == ZX_OK, "%s", zx_status_get_string(status));
}

zx_status_t MockDevice::DdkRxrpc(zx_handle_t channel) {
  auto result = controller_->Rxrpc(ConstructHookInvocation());
  ZX_ASSERT_MSG(result.ok(), "%s", result.status_string());
  ProcessActionsContext::ChannelVariants channel_variants = controller_.client_end().borrow();
  ProcessActionsContext ctx(channel_variants, true, this, zxdev());
  zx_status_t status = ProcessActions(result.value().actions, &ctx);
  ZX_ASSERT_MSG(status == ZX_OK, "%s", zx_status_get_string(status));
  return ctx.hook_status;
}

zx_status_t MockDevice::Create(zx_device_t* parent,
                               fidl::ClientEnd<device_mock::MockDevice> controller,
                               std::unique_ptr<MockDevice>* out) {
  auto dev = std::make_unique<MockDevice>(parent, std::move(controller));
  *out = std::move(dev);
  return ZX_OK;
}

zx_status_t ProcessActions(fidl::VectorView<device_mock::wire::Action> actions,
                           ProcessActionsContext* ctx) {
  for (size_t i = 0; i < actions.count(); ++i) {
    auto& action = actions[i];
    switch (action.Which()) {
      case device_mock::wire::Action::Tag::kReturnStatus: {
        if (i != actions.count() - 1) {
          printf("MockDevice::ProcessActions: return_status was not the final entry\n");
          return ZX_ERR_INVALID_ARGS;
        }
        if (!ctx->has_hook_status) {
          printf("MockDevice::ProcessActions: return_status present for no-status hook\n");
          return ZX_ERR_INVALID_ARGS;
        }
        ctx->hook_status = action.return_status();
        return ZX_OK;
      }
      case device_mock::wire::Action::Tag::kCreateThread: {
        if (ctx->mock_device == nullptr) {
          printf("MockDevice::CreateThread: asked to create thread without device\n");
          return ZX_ERR_INVALID_ARGS;
        }
        ctx->mock_device->CreateThread(std::move(action.create_thread()));
        break;
      }
      case device_mock::wire::Action::Tag::kAsyncRemoveDevice: {
        if (ctx->mock_device == nullptr) {
          printf("MockDevice::RemoveDevice: asked to remove device but none populated\n");
          return ZX_ERR_INVALID_ARGS;
        }
        ctx->mock_device->DdkAsyncRemove();
        break;
      }
      case device_mock::wire::Action::Tag::kUnbindReply: {
        if (!ctx->pending_unbind_txn) {
          printf("MockDevice::UnbindReply: asked to reply to unbind but no unbind is pending\n");
          return ZX_ERR_INVALID_ARGS;
        }
        ctx->pending_unbind_txn->Reply();
        // Null out the device pointers, since the release hook might get
        // activated.
        ctx->device = nullptr;
        ctx->mock_device = nullptr;
        zx_status_t status =
            std::visit(matchers{
                           [&](fidl::ServerEnd<device_mock::MockDeviceThread>& server_end) {
                             return fidl::WireSendEvent(server_end)
                                 ->UnbindReplyDone(action.unbind_reply().action_id)
                                 .status();
                           },
                           [&](fidl::UnownedClientEnd<device_mock::MockDevice>& client_end) {
                             return fidl::WireCall(client_end)
                                 ->UnbindReplyDone(action.unbind_reply().action_id)
                                 .status();
                           },
                       },
                       ctx->channel_variants);
        ZX_ASSERT_MSG(status == ZX_OK, "%s", zx_status_get_string(status));
        break;
      }

      case device_mock::wire::Action::Tag::kSuspendReply: {
        if (!ctx->pending_suspend_txn) {
          printf("MockDevice::SuspendReply: asked to reply to suspend but no suspend is pending\n");
          return ZX_ERR_INVALID_ARGS;
        }
        ctx->pending_suspend_txn->Reply(ZX_OK, 0);
        zx_status_t status =
            std::visit(matchers{
                           [&](fidl::ServerEnd<device_mock::MockDeviceThread>& server_end) {
                             return fidl::WireSendEvent(server_end)
                                 ->SuspendReplyDone(action.suspend_reply().action_id)
                                 .status();
                           },
                           [&](fidl::UnownedClientEnd<device_mock::MockDevice>& client_end) {
                             return fidl::WireCall(client_end)
                                 ->SuspendReplyDone(action.suspend_reply().action_id)
                                 .status();
                           },
                       },
                       ctx->channel_variants);
        ZX_ASSERT_MSG(status == ZX_OK, "%s", zx_status_get_string(status));
        break;
      }

      case device_mock::wire::Action::Tag::kResumeReply: {
        if (!ctx->pending_resume_txn) {
          printf("MockDevice::ResumeReply: asked to reply to resume but no resume is pending\n");
          return ZX_ERR_INVALID_ARGS;
        }
        ctx->pending_resume_txn->Reply(ZX_OK, 0, 0);
        zx_status_t status =
            std::visit(matchers{
                           [&](fidl::ServerEnd<device_mock::MockDeviceThread>& server_end) {
                             return fidl::WireSendEvent(server_end)
                                 ->ResumeReplyDone(action.resume_reply().action_id)
                                 .status();
                           },
                           [&](fidl::UnownedClientEnd<device_mock::MockDevice>& client_end) {
                             return fidl::WireCall(client_end)
                                 ->ResumeReplyDone(action.resume_reply().action_id)
                                 .status();
                           },
                       },
                       ctx->channel_variants);
        ZX_ASSERT_MSG(status == ZX_OK, "%s", zx_status_get_string(status));
        break;
      }
      case device_mock::wire::Action::Tag::kAddDevice: {
        // TODO(teisenbe): Implement more functionality here
        auto& add_device_action = action.add_device();
        ZX_ASSERT_MSG(!add_device_action.do_bind, "bind not yet supported\n");
        std::unique_ptr<MockDevice> dev;
        zx_status_t status =
            MockDevice::Create(ctx->device, std::move(add_device_action.controller), &dev);
        if (status != ZX_OK) {
          return status;
        }

        char name[ZX_DEVICE_NAME_MAX + 1];
        if (add_device_action.name.size() > sizeof(name) - 1) {
          return ZX_ERR_INVALID_ARGS;
        }
        memcpy(name, add_device_action.name.data(), add_device_action.name.size());
        name[add_device_action.name.size()] = 0;

        cpp20::span<zx_device_prop_t> props(
            reinterpret_cast<zx_device_prop_t*>(add_device_action.properties.data()),
            add_device_action.properties.count());

        status = dev->DdkAdd(ddk::DeviceAddArgs(name).set_props(props));
        if (status == ZX_OK) {
          // Devmgr now owns this
          [[maybe_unused]] auto ptr = dev.release();
        }
        if (add_device_action.expect_status != status) {
          return status;
        }

        status = std::visit(matchers{
                                [&](fidl::ServerEnd<device_mock::MockDeviceThread>& server_end) {
                                  return fidl::WireSendEvent(server_end)
                                      ->AddDeviceDone(add_device_action.action_id)
                                      .status();
                                },
                                [&](fidl::UnownedClientEnd<device_mock::MockDevice>& client_end) {
                                  return fidl::WireCall(client_end)
                                      ->AddDeviceDone(add_device_action.action_id)
                                      .status();
                                },
                            },
                            ctx->channel_variants);
        ZX_ASSERT_MSG(status == ZX_OK, "%s", zx_status_get_string(status));
        break;
      }
    }
  }

  if (!ctx->has_hook_status) {
    return ZX_OK;
  }

  printf("MockDevice::ProcessActions: return_status was not the final entry\n");
  return ZX_ERR_INVALID_ARGS;
}

zx_status_t MockDeviceBind(void* ctx, zx_device_t* parent) {
  // It's expected that this driver is binding against a device created by the
  // fuchsia.device.test interface.  Get the protocol from the device we're
  // binding to so we can wire up the control channel.
  test_protocol_t proto;
  zx_status_t status = device_get_protocol(parent, ZX_PROTOCOL_TEST, &proto);
  ZX_ASSERT_MSG(status == ZX_OK, "%s", zx_status_get_string(status));

  fidl::ClientEnd<device_mock::MockDevice> client_end;
  test_get_channel(&proto, client_end.channel().reset_and_get_address());

  // Ask the control channel what to do about this bind().
  auto result =
      fidl::WireCall(client_end)
          ->Bind(MockDevice::ConstructHookInvocation(reinterpret_cast<uintptr_t>(parent)));
  ZX_ASSERT_MSG(result.ok(), "%s", result.status_string());

  ProcessActionsContext::ChannelVariants channel_variants = client_end.borrow();
  ProcessActionsContext pac_ctx(channel_variants, true, nullptr, parent);
  status = ProcessActions(result.value().actions, &pac_ctx);
  ZX_ASSERT_MSG(status == ZX_OK, "%s", zx_status_get_string(status));
  return pac_ctx.hook_status;
}

const zx_driver_ops_t kMockDeviceOps = []() {
  zx_driver_ops_t ops = {};
  ops.version = DRIVER_OPS_VERSION;
  ops.bind = MockDeviceBind;
  return ops;
}();

}  // namespace mock_device

ZIRCON_DRIVER(mock_device, mock_device::kMockDeviceOps, "zircon", "0.1");
