# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Implementation of a USB HID mouse.

Two classes are provided by this module. The MouseFeature class implements
the core functionality of a HID mouse and can be included in any HID gadget.
The MouseGadget class implements an example mouse gadget.
"""

import struct

import hid_constants
import hid_descriptors
import hid_gadget
import usb_constants


class MouseFeature(hid_gadget.HidFeature):
  """HID feature implementation for a mouse.

  REPORT_DESC provides an example HID report descriptor for a device including
  this functionality.
  """

  REPORT_DESC = hid_descriptors.ReportDescriptor(
      hid_descriptors.UsagePage(0x01),  # Generic Desktop
      hid_descriptors.Usage(0x02),  # Mouse
      hid_descriptors.Collection(
          hid_constants.CollectionType.APPLICATION,
          hid_descriptors.Usage(0x01),  # Pointer
          hid_descriptors.Collection(
              hid_constants.CollectionType.PHYSICAL,
              hid_descriptors.UsagePage(0x09),  # Buttons
              hid_descriptors.UsageMinimum(1),
              hid_descriptors.UsageMaximum(3),
              hid_descriptors.LogicalMinimum(0, force_length=1),
              hid_descriptors.LogicalMaximum(1),
              hid_descriptors.ReportCount(3),
              hid_descriptors.ReportSize(1),
              hid_descriptors.Input(hid_descriptors.Data,
                                    hid_descriptors.Variable,
                                    hid_descriptors.Absolute),
              hid_descriptors.ReportCount(1),
              hid_descriptors.ReportSize(5),
              hid_descriptors.Input(hid_descriptors.Constant),
              hid_descriptors.UsagePage(0x01),  # Generic Desktop
              hid_descriptors.Usage(0x30),  # X
              hid_descriptors.Usage(0x31),  # Y
              hid_descriptors.LogicalMinimum(0x81),  # -127
              hid_descriptors.LogicalMaximum(127),
              hid_descriptors.ReportSize(8),
              hid_descriptors.ReportCount(2),
              hid_descriptors.Input(hid_descriptors.Data,
                                    hid_descriptors.Variable,
                                    hid_descriptors.Relative)
          )
      )
  )

  def __init__(self):
    super(MouseFeature, self).__init__()
    self._buttons = 0

  def ButtonDown(self, button):
    self._buttons |= button
    if self.IsConnected():
      self.SendReport(self.EncodeInputReport())

  def ButtonUp(self, button):
    self._buttons &= ~button
    if self.IsConnected():
      self.SendReport(self.EncodeInputReport())

  def Move(self, x_displacement, y_displacement):
    if self.IsConnected():
      self.SendReport(self.EncodeInputReport(x_displacement, y_displacement))

  def EncodeInputReport(self, x_displacement=0, y_displacement=0):
    return struct.pack('Bbb', self._buttons, x_displacement, y_displacement)

  def GetInputReport(self):
    """Construct an input report.

    See Device Class Definition for Human Interface Devices (HID) Version 1.11
    Appendix B.2.

    Returns:
      A packed input report.
    """
    return self.EncodeInputReport()


class MouseGadget(hid_gadget.HidGadget):
  """USB gadget implementation of a HID mouse."""

  def __init__(self):
    self._feature = MouseFeature()
    super(MouseGadget, self).__init__(
        report_desc=MouseFeature.REPORT_DESC,
        features={0: self._feature},
        packet_size=8,
        interval_ms=1,
        out_endpoint=False,
        vendor_id=usb_constants.VendorID.GOOGLE,
        product_id=usb_constants.ProductID.GOOGLE_MOUSE_GADGET,
        device_version=0x0100)
    self.AddStringDescriptor(1, 'Google Inc.')
    self.AddStringDescriptor(2, 'Mouse Gadget')

  def ButtonDown(self, button):
    self._feature.ButtonDown(button)

  def ButtonUp(self, button):
    self._feature.ButtonUp(button)

  def Move(self, x_displacement, y_displacement):
    self._feature.Move(x_displacement, y_displacement)


def RegisterHandlers():
  """Registers web request handlers with the application server."""

  from tornado import web

  class WebConfigureHandler(web.RequestHandler):

    def post(self):
      gadget = MouseGadget()
      server.SwitchGadget(gadget)

  class WebClickHandler(web.RequestHandler):

    def post(self):
      BUTTONS = {
          '1': hid_constants.Mouse.BUTTON_1,
          '2': hid_constants.Mouse.BUTTON_2,
          '3': hid_constants.Mouse.BUTTON_3,
      }

      button = BUTTONS[self.get_argument('button')]
      server.gadget.ButtonDown(button)
      server.gadget.ButtonUp(button)

  class WebMoveHandler(web.RequestHandler):

    def post(self):
      x = int(self.get_argument('x'))
      y = int(self.get_argument('y'))
      server.gadget.Move(x, y)

  import server
  server.app.add_handlers('.*$', [
      (r'/mouse/configure', WebConfigureHandler),
      (r'/mouse/move', WebMoveHandler),
      (r'/mouse/click', WebClickHandler),
  ])
