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

import 'dart:async';
import 'dart:developer';
import 'dart:ui' as ui;

import 'package:fidl_fuchsia_ui_input/fidl.dart';
import 'package:fidl_fuchsia_ui_policy/fidl.dart';

/// Listens for pointer events and injects them into Flutter input pipeline.
class PointerEventsListener implements PointerCaptureListenerHack {
  // Holds the fidl binding to receive pointer events.
  final PointerCaptureListenerHackBinding _pointerCaptureListenerBinding =
      PointerCaptureListenerHackBinding();

  // Holds the last [PointerEvent] mapped to its pointer id. This is used to
  // determine the correct [PointerDataPacket] to generate at boundary condition
  // of the screen rect.
  final Map<int, PointerEvent> _lastPointerEvent = <int, PointerEvent>{};

  // Flag to remember that a down event was seen before a move event.
  // TODO(sanjayc): Should really convert to a FSM for PointerEvent.
  final Map<int, bool> _downEvent = <int, bool>{};

  // Holds the [onPointerDataCallback] assigned to [ui.window] at
  // the start of the program.
  ui.PointerDataPacketCallback _originalCallback;

  /// Starts listening to pointer events. Also overrides the original
  /// [ui.window.onPointerDataPacket] callback to a NOP since we
  /// inject the pointer events received from the [Presentation] service.
  void listen(PresentationProxy presentation) {
    _originalCallback = ui.window.onPointerDataPacket;
    ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {};

    presentation
        .capturePointerEventsHack(_pointerCaptureListenerBinding.wrap(this));
  }

  /// Stops listening to pointer events. Also restores the
  /// [ui.window.onPointerDataPacket] callback.
  void stop() {
    if (_originalCallback != null) {
      _cleanupPointerEvents();
      _pointerCaptureListenerBinding.close();

      // Restore the original pointer events callback on the window.
      ui.window.onPointerDataPacket = _originalCallback;
      _originalCallback = null;
      _lastPointerEvent.clear();
      _downEvent.clear();
    }
  }

  void _cleanupPointerEvents() {
    for (PointerEvent lastEvent in _lastPointerEvent.values.toList()) {
      if (lastEvent.phase != PointerEventPhase.remove &&
          lastEvent.type != PointerEventType.mouse) {
        onPointerEvent(_clone(lastEvent, PointerEventPhase.remove));
      }
    }
  }

  PointerEvent _clone(PointerEvent event, [PointerEventPhase phase]) {
    return PointerEvent(
        buttons: event.buttons,
        deviceId: event.deviceId,
        eventTime: event.eventTime,
        phase: phase ?? event.phase,
        pointerId: event.pointerId,
        radiusMajor: event.radiusMajor,
        radiusMinor: event.radiusMinor,
        type: event.type,
        x: event.x,
        y: event.y);
  }

  /// |PointerCaptureListener|.
  @override
  Future<void> onPointerEvent(PointerEvent event) async {
    _onPointerEvent(event);
  }

  void _onPointerEvent(PointerEvent event) {
    if (_originalCallback == null) {
      return;
    }

    Timeline.startSync('PointerEventsListener.onPointerEvent');
    final packet = _getPacket(event);
    if (packet != null) {
      _originalCallback(ui.PointerDataPacket(data: [packet]));
    }
    Timeline.finishSync();
  }

  ui.PointerChange _changeFromPointerEvent(PointerEvent event) {
    PointerEvent lastEvent = _lastPointerEvent[event.pointerId] ?? event;

    switch (event.phase) {
      case PointerEventPhase.add:
        return ui.PointerChange.add;
      case PointerEventPhase.hover:
        return ui.PointerChange.hover;
      case PointerEventPhase.down:
        _downEvent[event.pointerId] = true;
        return ui.PointerChange.down;
      case PointerEventPhase.move:
        // If move is the first event, convert to `add` event. Otherwise,
        // flutter pointer state machine throws an exception.
        if (event.type != PointerEventType.mouse &&
            _lastPointerEvent[event.pointerId] == null) {
          return ui.PointerChange.add;
        }

        // If move event was seen before down event, convert to `down` event.
        if (event.type != PointerEventType.mouse &&
            _downEvent[event.pointerId] != true) {
          _downEvent[event.pointerId] = true;
          return ui.PointerChange.down;
        }

        // For mouse, return a hover event if no buttons were pressed.
        if (event.type == PointerEventType.mouse && event.buttons == 0) {
          return ui.PointerChange.hover;
        }

        // Check if this is a boundary condition and convert to up/down event.
        if (lastEvent?.phase == PointerEventPhase.move) {
          if (_outside(lastEvent) && _inside(event)) {
            return ui.PointerChange.down;
          }
          if (_inside(lastEvent) && _outside(event)) {
            return ui.PointerChange.cancel;
          }
        }

        return ui.PointerChange.move;
      case PointerEventPhase.up:
        _downEvent[event.pointerId] = false;
        return ui.PointerChange.up;
      case PointerEventPhase.remove:
        return ui.PointerChange.remove;
      case PointerEventPhase.cancel:
      default:
        return ui.PointerChange.cancel;
    }
  }

  ui.PointerDeviceKind _kindFromPointerEvent(PointerEvent event) {
    switch (event.type) {
      case PointerEventType.mouse:
        return ui.PointerDeviceKind.mouse;
      case PointerEventType.stylus:
        return ui.PointerDeviceKind.stylus;
      case PointerEventType.invertedStylus:
        return ui.PointerDeviceKind.invertedStylus;
      case PointerEventType.touch:
      default:
        return ui.PointerDeviceKind.touch;
    }
  }

  ui.PointerData _getPacket(PointerEvent event) {
    PointerEvent lastEvent = _lastPointerEvent[event.pointerId] ?? event;

    // Only allow add and remove pointer events from outside the window bounds.
    // For other events, we drop them if the last two were outside the window
    // bounds. If any of current event or last event lies inside the window,
    // we generate a synthetic down or up event.
    if (event.phase != PointerEventPhase.add &&
        event.phase != PointerEventPhase.remove &&
        _outside(event) &&
        _outside(lastEvent)) {
      _lastPointerEvent[event.pointerId] = event;
      return null;
    }

    // Convert from PointerEvent to PointerData.
    final data = ui.PointerData(
      buttons: event.buttons,
      device: event.pointerId,
      timeStamp: Duration(microseconds: event.eventTime ~/ 1000),
      change: _changeFromPointerEvent(event),
      kind: _kindFromPointerEvent(event),
      physicalX: event.x * ui.window.devicePixelRatio,
      physicalY: event.y * ui.window.devicePixelRatio,
    );

    // Remember this event for checking boundary condition on the next event.
    _lastPointerEvent[event.pointerId] = event;

    return data;
  }

  bool _inside(PointerEvent event) {
    return event != null &&
        event.x * ui.window.devicePixelRatio >= 0 &&
        event.x * ui.window.devicePixelRatio < ui.window.physicalSize.width &&
        event.y * ui.window.devicePixelRatio >= 0 &&
        event.y * ui.window.devicePixelRatio < ui.window.physicalSize.height;
  }

  bool _outside(PointerEvent event) => !_inside(event);
}
