// Copyright 2020 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 "src/ui/lib/input_report_reader/input_interpreter.h"

#include <fuchsia/ui/input/cpp/fidl.h>
#include <lib/fidl/cpp/clone.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/trace/event.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <zircon/errors.h>
#include <zircon/types.h>

namespace ui_input {

namespace {

fuchsia::ui::input::Axis ConvertAxis(fuchsia::input::report::Axis axis) {
  fuchsia::ui::input::Axis a = {};
  a.range.min = static_cast<int32_t>(axis.range.min);
  a.range.max = static_cast<int32_t>(axis.range.max);
  return a;
}

// Sets the fuchsia::ui::input Mouse button bit vector.
// prev_buttons represents the current button bit vector.
// button_id is the new button to set.
// The function returns the new button bit vector.
uint32_t SetMouseButton(uint32_t prev_buttons, uint8_t button_id) {
  if (button_id == 0 || button_id > 32) {
    return prev_buttons;
  }
  return prev_buttons | (1 << (button_id - 1));
}

}  // namespace

InputInterpreter::InputInterpreter(InputReaderBase* base,
                                   fuchsia::ui::input::InputDeviceRegistry* registry,
                                   std::string name)
    : base_(base), registry_(registry), name_(name) {}

InputInterpreter::~InputInterpreter() {}

void InputInterpreter::DispatchReport(const fuchsia::ui::input::InputDevicePtr& device,
                                      fuchsia::ui::input::InputReport report) {
  report.trace_id = TRACE_NONCE();
  TRACE_FLOW_BEGIN("input", "hid_read_to_listener", report.trace_id);
  device->DispatchReport(std::move(report));
}

std::unique_ptr<InputInterpreter> InputInterpreter::Create(
    InputReaderBase* base, zx::channel channel, fuchsia::ui::input::InputDeviceRegistry* registry,
    std::string name) {
  // Using `new` to access a non-public constructor.
  auto interpreter = std::unique_ptr<InputInterpreter>(new InputInterpreter(base, registry, name));
  zx_status_t status = interpreter->device_.Bind(std::move(channel));
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "InputInterpreter::Create: Bind error: " << status;
    return nullptr;
  }
  interpreter->Initialize();
  return interpreter;
}

void InputInterpreter::Initialize() {
  device_.set_error_handler([this](zx_status_t status) {
    if (status != ZX_ERR_PEER_CLOSED) {
      FX_LOGS(ERROR) << "InputInterpreter: Device error: " << status;
    }
    base_->RemoveDevice(this);
  });

  RegisterDevices();
}

void InputInterpreter::RegisterConsumerControl(
    const fuchsia::input::report::DeviceDescriptor& descriptor) {
  fuchsia::ui::input::DeviceDescriptor ui_descriptor;

  if (descriptor.has_device_info()) {
    auto info = std::make_unique<fuchsia::ui::input::DeviceInfo>();
    info->vendor_id = descriptor.device_info().vendor_id;
    info->product_id = descriptor.device_info().product_id;
    info->version = descriptor.device_info().version;
    ui_descriptor.device_info = std::move(info);
  }

  auto media_buttons = std::make_unique<fuchsia::ui::input::MediaButtonsDescriptor>();
  if (descriptor.consumer_control().input().has_buttons()) {
    for (auto button : descriptor.consumer_control().input().buttons()) {
      switch (button) {
        case fuchsia::input::report::ConsumerControlButton::VOLUME_UP:
          media_buttons->buttons |= fuchsia::ui::input::kVolumeUp;
          break;
        case fuchsia::input::report::ConsumerControlButton::VOLUME_DOWN:
          media_buttons->buttons |= fuchsia::ui::input::kVolumeDown;
          break;
        case fuchsia::input::report::ConsumerControlButton::MIC_MUTE:
          media_buttons->buttons |= fuchsia::ui::input::kMicMute;
          break;
        case fuchsia::input::report::ConsumerControlButton::PAUSE:
          media_buttons->buttons |= fuchsia::ui::input::kPause;
          break;
        case fuchsia::input::report::ConsumerControlButton::REBOOT:
          media_buttons->buttons |= fuchsia::ui::input::kReset;
          break;
        case fuchsia::input::report::ConsumerControlButton::CAMERA_DISABLE:
          media_buttons->buttons |= fuchsia::ui::input::kCameraDisable;
          break;
        default:
          break;
      }
    }
  }
  ui_descriptor.media_buttons = std::move(media_buttons);
  registry_->RegisterDevice(std::move(ui_descriptor), consumer_control_ptr_.NewRequest());
}

void InputInterpreter::RegisterMouse(const fuchsia::input::report::DeviceDescriptor& descriptor) {
  fuchsia::ui::input::DeviceDescriptor ui_descriptor;

  if (descriptor.has_device_info()) {
    auto info = std::make_unique<fuchsia::ui::input::DeviceInfo>();
    info->vendor_id = descriptor.device_info().vendor_id;
    info->product_id = descriptor.device_info().product_id;
    info->version = descriptor.device_info().version;
    ui_descriptor.device_info = std::move(info);
  }

  auto mouse = std::make_unique<fuchsia::ui::input::MouseDescriptor>();
  if (descriptor.mouse().input().has_movement_x()) {
    mouse->rel_x = ConvertAxis(descriptor.mouse().input().movement_x());
  }
  if (descriptor.mouse().input().has_movement_y()) {
    mouse->rel_y = ConvertAxis(descriptor.mouse().input().movement_y());
  }
  if (descriptor.mouse().input().has_buttons()) {
    for (uint8_t button : descriptor.mouse().input().buttons()) {
      mouse->buttons = SetMouseButton(mouse->buttons, button);
    }
  }
  ui_descriptor.mouse = std::move(mouse);
  registry_->RegisterDevice(std::move(ui_descriptor), mouse_ptr_.NewRequest());
}

void InputInterpreter::RegisterTouchscreen(
    const fuchsia::input::report::DeviceDescriptor& descriptor) {
  fuchsia::ui::input::DeviceDescriptor ui_descriptor;

  if (descriptor.has_device_info()) {
    auto info = std::make_unique<fuchsia::ui::input::DeviceInfo>();
    info->vendor_id = descriptor.device_info().vendor_id;
    info->product_id = descriptor.device_info().product_id;
    info->version = descriptor.device_info().version;
    ui_descriptor.device_info = std::move(info);
  }

  auto touch = std::make_unique<fuchsia::ui::input::TouchscreenDescriptor>();
  if (descriptor.touch().input().has_contacts()) {
    if (descriptor.touch().input().contacts()[0].has_position_x()) {
      touch->x.range.min =
          static_cast<int32_t>(descriptor.touch().input().contacts()[0].position_x().range.min);
      touch->x.range.max =
          static_cast<int32_t>(descriptor.touch().input().contacts()[0].position_x().range.max);
    }
    if (descriptor.touch().input().contacts()[0].has_position_y()) {
      touch->y.range.min =
          static_cast<int32_t>(descriptor.touch().input().contacts()[0].position_y().range.min);
      touch->y.range.max =
          static_cast<int32_t>(descriptor.touch().input().contacts()[0].position_y().range.max);
    }
  }
  if (descriptor.touch().input().has_max_contacts()) {
    touch->max_finger_id = descriptor.touch().input().max_contacts();
  }
  ui_descriptor.touchscreen = std::move(touch);
  registry_->RegisterDevice(std::move(ui_descriptor), touch_ptr_.NewRequest());
}

void InputInterpreter::RegisterDevices() {
  fuchsia::input::report::DeviceDescriptor descriptor;
  device_->GetDescriptor([this](fuchsia::input::report::DeviceDescriptor descriptor) {
    if (descriptor.has_touch() && descriptor.touch().has_input()) {
      if (descriptor.touch().input().has_touch_type() &&
          (descriptor.touch().input().touch_type() ==
           fuchsia::input::report::TouchType::TOUCHSCREEN)) {
        RegisterTouchscreen(descriptor);
      }
    }

    if (descriptor.has_mouse() && descriptor.mouse().has_input()) {
      RegisterMouse(descriptor);
    }

    if (descriptor.has_consumer_control() && descriptor.consumer_control().has_input()) {
      RegisterConsumerControl(descriptor);
    }

    // Now that devices are registered we can start reading requests.
    device_->GetInputReportsReader(reader_.NewRequest());
    reader_.set_error_handler([this](zx_status_t status) {
      if (status != ZX_ERR_PEER_CLOSED) {
        FX_LOGS(ERROR) << "InputInterpreter: Reader error: " << status;
      }
      base_->RemoveDevice(this);
    });

    // Kick off the first Read, which will queue up the rest of the reads.
    reader_->ReadInputReports([this](auto result) { ReadReports(std::move(result)); });
  });
}

void InputInterpreter::DispatchTouchReport(const fuchsia::input::report::InputReport& report) {
  fuchsia::ui::input::InputReport input_report;
  if (report.has_event_time()) {
    input_report.event_time = report.event_time();
  }
  auto input_touchscreen = std::make_unique<fuchsia::ui::input::TouchscreenReport>();
  if (report.touch().has_contacts()) {
    for (const fuchsia::input::report::ContactInputReport& contact : report.touch().contacts()) {
      fuchsia::ui::input::Touch input_touch;
      if (contact.has_contact_id()) {
        input_touch.finger_id = contact.contact_id();
      }
      if (contact.has_position_x()) {
        input_touch.x = static_cast<int32_t>(contact.position_x());
      }
      if (contact.has_position_y()) {
        input_touch.y = static_cast<int32_t>(contact.position_y());
      }
      input_touchscreen->touches.push_back(std::move(input_touch));
    }
  }
  input_report.touchscreen = std::move(input_touchscreen);
  DispatchReport(touch_ptr_, std::move(input_report));
}

void InputInterpreter::DispatchMouseReport(const fuchsia::input::report::InputReport& report) {
  fuchsia::ui::input::InputReport input_report;
  if (report.has_event_time()) {
    input_report.event_time = report.event_time();
  }
  auto input_mouse = std::make_unique<fuchsia::ui::input::MouseReport>();
  if (report.mouse().has_movement_x()) {
    input_mouse->rel_x = static_cast<uint32_t>(report.mouse().movement_x());
  }
  if (report.mouse().has_movement_y()) {
    input_mouse->rel_y = static_cast<uint32_t>(report.mouse().movement_y());
  }
  if (report.mouse().has_pressed_buttons()) {
    for (uint8_t button : report.mouse().pressed_buttons()) {
      input_mouse->pressed_buttons = SetMouseButton(input_mouse->pressed_buttons, button);
    }
  }
  input_report.mouse = std::move(input_mouse);
  DispatchReport(mouse_ptr_, std::move(input_report));
}

void InputInterpreter::DispatchConsumerControlReport(
    const fuchsia::input::report::InputReport& report) {
  fuchsia::ui::input::InputReport input_report;
  if (report.has_event_time()) {
    input_report.event_time = report.event_time();
  }
  auto media_buttons = std::make_unique<fuchsia::ui::input::MediaButtonsReport>();
  if (report.consumer_control().has_pressed_buttons()) {
    for (const fuchsia::input::report::ConsumerControlButton& button :
         report.consumer_control().pressed_buttons()) {
      switch (button) {
        case fuchsia::input::report::ConsumerControlButton::VOLUME_UP:
          media_buttons->volume_up = true;
          break;
        case fuchsia::input::report::ConsumerControlButton::VOLUME_DOWN:
          media_buttons->volume_down = true;
          break;
        case fuchsia::input::report::ConsumerControlButton::MIC_MUTE:
          media_buttons->mic_mute = true;
          break;
        case fuchsia::input::report::ConsumerControlButton::PAUSE:
          media_buttons->pause = true;
          break;
        case fuchsia::input::report::ConsumerControlButton::REBOOT:
          media_buttons->reset = true;
          break;
        case fuchsia::input::report::ConsumerControlButton::CAMERA_DISABLE:
          media_buttons->camera_disable = true;
          break;
        default:
          break;
      }
    }
  }
  input_report.media_buttons = std::move(media_buttons);
  DispatchReport(consumer_control_ptr_, std::move(input_report));
}

void InputInterpreter::ReadReports(
    fuchsia::input::report::InputReportsReader_ReadInputReports_Result result) {
  TRACE_DURATION("input", "input_report_reader Read");

  if (result.is_err()) {
    FX_LOGS(INFO) << "InputInterpreter: ReadInputReports received status code: " << result.err();
    base_->RemoveDevice(this);
    return;
  }

  if (base_->ActiveInput()) {
    for (const auto& report : result.response().reports) {
      if (report.has_trace_id()) {
        TRACE_FLOW_END("input", "input_report", report.trace_id());
      }
      if (report.has_touch()) {
        DispatchTouchReport(report);
      }
      if (report.has_consumer_control()) {
        DispatchConsumerControlReport(report);
      }
      if (report.has_mouse()) {
        DispatchMouseReport(report);
      }
    }
  }

  // Queue ourselves up again for another read.
  reader_->ReadInputReports([this](auto result) { ReadReports(std::move(result)); });
}

}  // namespace ui_input
