// 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 "input_sample.h"

#include <lib/async/cpp/task.h>
#include <lib/driver/component/cpp/driver_export.h>

namespace input_sample {

zx::result<> InputSampleDriver::Start() {
  // Start sending fake reports
  input_report_readers_ =
      std::make_shared<input_report_reader::InputReportReaderManager<SampleInputReport>>();
  SendFakeReport();

  if (zx::result result = ExportToDevfs(); result.is_error()) {
    FDF_SLOG(ERROR, "Failed to export to devfs", KV("status", result.status_string()));
    return result.take_error();
  }

  return zx::ok();
}

// Periodically send a new input report with fake data.
void InputSampleDriver::SendFakeReport() {
  // Update fake mouse report
  report_.event_time = zx::time(zx_clock_get_monotonic());
  report_.buttons++;
  report_.rel_x++;
  report_.rel_y++;

  // Send fake mouse report
  input_report_readers_->SendReportToAllReaders(report_);

  // Run again in 1 second
  async::PostDelayedTask(dispatcher(), [this]() mutable { SendFakeReport(); }, zx::sec(1));
}

zx::result<> InputSampleDriver::ExportToDevfs() {
  // Create a node for devfs.
  fidl::Arena arena;
  zx::result connector = devfs_connector_.Bind(dispatcher());
  if (connector.is_error()) {
    return connector.take_error();
  }

  auto devfs = fuchsia_driver_framework::wire::DevfsAddArgs::Builder(arena)
                   .connector(std::move(connector.value()))
                   .class_name("input-report");

  auto args = fuchsia_driver_framework::wire::NodeAddArgs::Builder(arena)
                  .name(arena, name())
                  .devfs_args(devfs.Build())
                  .Build();

  // Create endpoints of the `NodeController` for the node.
  zx::result controller_endpoints =
      fidl::CreateEndpoints<fuchsia_driver_framework::NodeController>();
  ZX_ASSERT_MSG(controller_endpoints.is_ok(), "Failed: %s", controller_endpoints.status_string());

  zx::result node_endpoints = fidl::CreateEndpoints<fuchsia_driver_framework::Node>();
  ZX_ASSERT_MSG(node_endpoints.is_ok(), "Failed: %s", node_endpoints.status_string());

  fidl::WireResult result = fidl::WireCall(node())->AddChild(
      args, std::move(controller_endpoints->server), std::move(node_endpoints->server));
  if (!result.ok()) {
    FDF_SLOG(ERROR, "Failed to add child", KV("status", result.status_string()));
    return zx::error(result.status());
  }
  controller_.Bind(std::move(controller_endpoints->client));
  node_.Bind(std::move(node_endpoints->client));
  return zx::ok();
}

void InputSampleDriver::Serve(fidl::ServerEnd<fuchsia_input_report::InputDevice> request) {
  InputSampleServer::BindDeviceClient(dispatcher(), input_report_readers_, std::move(request));
}

}  // namespace input_sample

FUCHSIA_DRIVER_EXPORT(input_sample::InputSampleDriver);
