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

#include <lib/driver/logging/cpp/structured_logger.h>

namespace input_sample {

// Convert local data structure to a `fuchsia.input.report/InputReport` format.
void SampleInputReport::ToFidlInputReport(
    fidl::WireTableBuilder<::fuchsia_input_report::wire::InputReport>& input_report,
    fidl::AnyArena& arena) {
  std::vector<uint8_t> pressed_buttons;
  for (uint8_t i = 0; i < kMouseButtonCount; i++) {
    if (buttons & (1 << i)) {
      pressed_buttons.push_back(i + 1);
    }
  }
  fidl::VectorView<uint8_t> buttons_vec(arena, pressed_buttons.size());
  size_t idx = 0;
  for (const auto& button : pressed_buttons) {
    buttons_vec[idx++] = button;
  }

  auto mouse_input_rpt = fuchsia_input_report::wire::MouseInputReport::Builder(arena);
  mouse_input_rpt.pressed_buttons(buttons_vec);
  mouse_input_rpt.movement_x(rel_x);
  mouse_input_rpt.movement_y(rel_y);

  input_report.mouse(mouse_input_rpt.Build());
  input_report.event_time(event_time.get());
}

// Static
// Handle incoming connection requests from FIDL clients
fidl::ServerBindingRef<fuchsia_input_report::InputDevice> InputSampleServer::BindDeviceClient(
    async_dispatcher_t* dispatcher,
    std::weak_ptr<input_report_reader::InputReportReaderManager<SampleInputReport>>
        input_report_readers,
    fidl::ServerEnd<fuchsia_input_report::InputDevice> request) {
  // Bind each connection request to a unique FIDL server instance
  auto server_impl = std::make_unique<InputSampleServer>(dispatcher, input_report_readers);
  return fidl::BindServer(dispatcher, std::move(request), std::move(server_impl),
                          std::mem_fn(&InputSampleServer::OnUnbound));
}

// This method is called when a server connection is torn down.
void InputSampleServer::OnUnbound(fidl::UnbindInfo info,
                                  fidl::ServerEnd<fuchsia_input_report::InputDevice> server_end) {
  if (info.is_peer_closed()) {
    FDF_LOG(DEBUG, "Client disconnected");
  } else if (!info.is_user_initiated()) {
    FDF_LOG(ERROR, "Client connection unbound: %s", info.status_string());
  }
}

// Protocol method for `fuchsia.input.report/InputDevice` to begin serving input reports
void InputSampleServer::GetInputReportsReader(GetInputReportsReaderRequestView request,
                                              GetInputReportsReaderCompleter::Sync& completer) {
  auto reader_manager = input_report_readers_.lock();
  if (!reader_manager) {
    FDF_LOG(ERROR, "Unable to access InputReport reader manager.");
    request->reader.Close(ZX_ERR_BAD_STATE);
    return;
  }

  zx_status_t status = reader_manager->CreateReader(dispatcher_, std::move(request->reader));
  if (status != ZX_OK) {
    FDF_LOG(ERROR, "Could not create input report reader: %d", status);
    request->reader.Close(ZX_ERR_BAD_STATE);
  }
}

// Protocol method for `fuchsia.input.report/InputDevice` to return the device descriptor
void InputSampleServer::GetDescriptor(GetDescriptorCompleter::Sync& completer) {
  fidl::Arena allocator;
  auto descriptor = fuchsia_input_report::wire::DeviceDescriptor::Builder(allocator);

  fuchsia_input_report::wire::DeviceInfo device_info;
  // We pick random VID/PIDs here, but these should be taken from the HID device,
  // or defined in fuchsia.input.report/device_ids.fidl
  device_info.vendor_id = 0x12345678;
  device_info.product_id = 0x87654321;

  fidl::VectorView<uint8_t> buttons(allocator, kMouseButtonCount);
  buttons[0] = 0x01;
  buttons[1] = 0x02;
  buttons[2] = 0x03;

  constexpr fuchsia_input_report::wire::Axis movement_x{
      .range = {.min = -127, .max = 127},
      .unit = {.type = fuchsia_input_report::wire::UnitType::kNone, .exponent = 0},
  };
  constexpr fuchsia_input_report::wire::Axis movement_y{
      .range = {.min = -127, .max = 127},
      .unit = {.type = fuchsia_input_report::wire::UnitType::kNone, .exponent = 0},
  };

  auto mouse_in_desc = fuchsia_input_report::wire::MouseInputDescriptor::Builder(allocator);
  mouse_in_desc.buttons(buttons);
  mouse_in_desc.movement_x(movement_x);
  mouse_in_desc.movement_y(movement_y);

  auto mouse_descriptor = fuchsia_input_report::wire::MouseDescriptor::Builder(allocator);
  mouse_descriptor.input(mouse_in_desc.Build());
  descriptor.mouse(mouse_descriptor.Build());
  descriptor.device_info(device_info);

  completer.Reply(descriptor.Build());
}

}  // namespace input_sample
