// Copyright 2017 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.

#ifndef SRC_LIB_UI_INPUT_DEVICE_STATE_H_
#define SRC_LIB_UI_INPUT_DEVICE_STATE_H_

#include <fuchsia/math/cpp/fidl.h>
#include <fuchsia/ui/input/cpp/fidl.h>
#include <lib/fit/function.h>
#include <lib/zx/time.h>
#include <stdint.h>

#include <vector>

#include <hid/hid.h>
#include <hid/usages.h>

#include "src/lib/fxl/memory/ref_counted.h"
#include "src/lib/fxl/memory/weak_ptr.h"

namespace ui_input {

using OnEventCallback = fit::function<void(fuchsia::ui::input::InputEvent event)>;

// In contrast to keyboard and mouse devices, which require extra state to
// correctly interpret their data, sensor devices are simpler, so we just pass
// through the raw InputReport. We do need a device_id to understand which
// sensor the report came from.
using OnSensorEventCallback =
    fit::function<void(uint32_t device_id, fuchsia::ui::input::InputReport event)>;

using OnMediaButtonsEventCallback = fit::function<void(fuchsia::ui::input::InputReport event)>;

class DeviceState;

class State {
 public:
  void OnRegistered() {}
  void OnUnregistered() {}
};

class KeyboardState : public State {
 public:
  KeyboardState(DeviceState* device_state);
  void Update(fuchsia::ui::input::InputReport report);

 private:
  void SendEvent(fuchsia::ui::input::KeyboardEventPhase phase, uint32_t key, uint64_t modifiers,
                 uint64_t timestamp);
  void Repeat(uint64_t sequence);
  void ScheduleRepeat(uint64_t sequence, zx::duration delta);

  DeviceState* device_state_;
  const keychar_t* keymap_;  // assigned to a global static qwerty_map or dvorak_map

  std::vector<uint32_t> keys_;
  std::vector<uint32_t> repeat_keys_;
  uint64_t modifiers_ = 0;
  uint64_t repeat_sequence_ = 0;

  fxl::WeakPtrFactory<KeyboardState> weak_ptr_factory_;
};

class MouseState : public State {
 public:
  MouseState(DeviceState* device_state) : device_state_(device_state) {}
  void Update(fuchsia::ui::input::InputReport report, fuchsia::math::Size display_size);
  void OnRegistered();
  void OnUnregistered();

 private:
  void SendEvent(float rel_x, float rel_y, int64_t timestamp,
                 fuchsia::ui::input::PointerEventPhase phase, uint32_t buttons);

  DeviceState* device_state_;
  uint8_t buttons_ = 0;
  fuchsia::math::PointF position_;
};

class StylusState : public State {
 public:
  StylusState(DeviceState* device_state) : device_state_(device_state) {}
  void Update(fuchsia::ui::input::InputReport report, fuchsia::math::Size display_size);

 private:
  void SendEvent(int64_t timestamp, fuchsia::ui::input::PointerEventPhase phase,
                 fuchsia::ui::input::PointerEventType type, float x, float y, uint32_t buttons);

  DeviceState* device_state_;
  bool stylus_down_ = false;
  bool stylus_in_range_ = false;
  bool inverted_stylus_ = false;
  fuchsia::ui::input::PointerEvent stylus_;
};

class TouchscreenState : public State {
 public:
  TouchscreenState(DeviceState* device_state) : device_state_(device_state) {}
  void Update(fuchsia::ui::input::InputReport report, fuchsia::math::Size display_size);

 private:
  DeviceState* device_state_;
  std::vector<fuchsia::ui::input::PointerEvent> pointers_;
};

class SensorState : public State {
 public:
  SensorState(DeviceState* device_state) : device_state_(device_state) {}
  void Update(fuchsia::ui::input::InputReport report);

 private:
  DeviceState* device_state_;
  // TODO(SCN-627): Remember sampling frequency and physical units.
};

class MediaButtonState : public State {
 public:
  MediaButtonState(DeviceState* device_state) : device_state_(device_state) {}
  void Update(fuchsia::ui::input::InputReport report);

 private:
  DeviceState* device_state_;
};

class DeviceState {
 public:
  DeviceState(uint32_t device_id, fuchsia::ui::input::DeviceDescriptor* descriptor,
              OnEventCallback callback);
  DeviceState(uint32_t device_id, fuchsia::ui::input::DeviceDescriptor* descriptor,
              OnSensorEventCallback callback);
  DeviceState(uint32_t device_id, fuchsia::ui::input::DeviceDescriptor* descriptor,
              OnMediaButtonsEventCallback callback);
  ~DeviceState();

  void OnRegistered();
  void OnUnregistered();

  void Update(fuchsia::ui::input::InputReport report, fuchsia::math::Size display_size);

  uint32_t device_id() { return device_id_; }
  const OnEventCallback& callback() { return callback_; }
  const OnSensorEventCallback& sensor_callback() { return sensor_callback_; }
  const OnMediaButtonsEventCallback& media_buttons_callback() { return media_buttons_callback_; }

  fuchsia::ui::input::KeyboardDescriptor* keyboard_descriptor() {
    return descriptor_->keyboard.get();
  }
  fuchsia::ui::input::MouseDescriptor* mouse_descriptor() { return descriptor_->mouse.get(); }
  fuchsia::ui::input::StylusDescriptor* stylus_descriptor() { return descriptor_->stylus.get(); }
  fuchsia::ui::input::TouchscreenDescriptor* touchscreen_descriptor() {
    return descriptor_->touchscreen.get();
  }
  fuchsia::ui::input::SensorDescriptor* sensor_descriptor() { return descriptor_->sensor.get(); }
  fuchsia::ui::input::MediaButtonsDescriptor* media_buttons_descriptor() {
    return descriptor_->media_buttons.get();
  }

 private:
  uint32_t device_id_;
  fuchsia::ui::input::DeviceDescriptor* descriptor_;

  KeyboardState keyboard_;
  MouseState mouse_;
  StylusState stylus_;
  TouchscreenState touchscreen_;
  OnEventCallback callback_;

  SensorState sensor_;
  OnSensorEventCallback sensor_callback_;

  OnMediaButtonsEventCallback media_buttons_callback_;
  MediaButtonState media_buttons_;
};

}  // namespace ui_input

#endif  // SRC_LIB_UI_INPUT_DEVICE_STATE_H_
