// 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"

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(
    driver::Logger& logger, 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>(logger, 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
