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

#ifndef SRC_UI_SCENIC_LIB_INPUT_POINTER_EVENT_BUFFER_H_
#define SRC_UI_SCENIC_LIB_INPUT_POINTER_EVENT_BUFFER_H_

#include <fuchsia/ui/input/accessibility/cpp/fidl.h>

#include <deque>
#include <unordered_map>
#include <vector>

#include "src/ui/lib/escher/geometry/types.h"
#include "src/ui/scenic/lib/input/internal_pointer_event.h"

namespace scenic_impl {
namespace input {

// A buffer to store pointer events.
//
// This buffer is used when an accessibility listener is intercepting pointer events.
// It sends each event to the accessibility listener, buffering streams of them until
// accessibility decides to either reject or consume a stream.
// If rejected, the events of the stream (past and future) are sent directly to the views that would
// normally receive them. If consumed, all events for the stream are sent only to accessibility.
class PointerEventBuffer {
 public:
  // Captures the deferred parallel dispatch of a pointer event.
  struct DeferredPointerEvent {
    InternalPointerEvent event;

    // Position 0 of the vector holds the top-most view. The vector may be empty.
    std::vector</*view_ref_koid*/ zx_koid_t> parallel_event_receivers;
  };
  // Represents a stream of pointer events. A stream is a sequence of pointer events with phase
  // ADD -> * -> REMOVE.
  struct PointerIdStream {
    // The temporally-ordered pointer events of this stream. Each element of this vector (indexed
    // by time) contains another vector (indexed by view); one touch event may be dispatched
    // multiple times, to multiple views, in parallel (simultaneously).
    std::vector<DeferredPointerEvent> serial_events;
  };
  // Possible states of a stream.
  enum PointerIdStreamStatus {
    WAITING_RESPONSE = 0,  // accessibility listener hasn't responded yet.
    CONSUMED = 1,
    REJECTED = 2,
  };

  using ReportAccessibilityEventFunction =
      std::function<void(fuchsia::ui::input::accessibility::PointerEvent)>;
  using DispatchEventFunction = fit::function<void(PointerEventBuffer::DeferredPointerEvent)>;

  PointerEventBuffer(DispatchEventFunction dispatch_events,
                     ReportAccessibilityEventFunction report_to_accessibility);
  ~PointerEventBuffer();

  // Adds a parallel dispatch event list |views_and_event| to the latest
  // stream associated with |pointer_id|. It also takes
  // |accessibility_pointer_event|, which is sent to the listener depending on
  // the current stream status.
  void AddEvent(uint32_t pointer_id, DeferredPointerEvent views_and_event,
                fuchsia::ui::input::accessibility::PointerEvent accessibility_pointer_event);

  // Adds a new stream associated with |pointer_id|.
  void AddStream(uint32_t pointer_id);

  // Updates the oldest stream associated with |pointer_id|, triggering an
  // appropriate action depending on |handled|.
  // If |handled| == CONSUMED, continues sending events to the listener.
  // If |handled| == REJECTED, dispatches buffered pointer events to views.
  void UpdateStream(uint32_t pointer_id, fuchsia::ui::input::accessibility::EventHandling handled);

  // Sets the status of view of the active stream for a pointer ID.
  void SetActiveStreamInfo(uint32_t pointer_id, PointerIdStreamStatus status) {
    active_stream_info_[pointer_id] = {status};
  }

 private:
  // NOTE: We assume there is one touch screen, and hence unique pointer IDs.
  // key = pointer ID, value = a list of pointer streams. Every new stream is
  // added to the end of the list, where a consume / reject response from the
  // listener always removes the first element.
  std::unordered_map<uint32_t, std::deque<PointerIdStream>> buffer_;

  // Key = pointer ID, value = the status of the current active stream.
  //
  // This is kept separate from the map above because this must outlive
  // the stream itself. When the accessibility listener responds, the first
  // non-processed stream is consumed / rejected and gets removed from the
  // buffer. It may not be finished (we haven't seen a pointer event with
  // phase == REMOVE), so it is necessary to still keep track of where the
  // incoming pointer events should go, although they don't need to be
  // buffered anymore.
  //
  // Whenever a pointer ID is added, its default value is WAITING_RESPONSE.
  std::unordered_map</*pointer ID*/ uint32_t, PointerIdStreamStatus> active_stream_info_;

  DispatchEventFunction dispatch_events_;
  ReportAccessibilityEventFunction report_to_accessibility_;
};

}  // namespace input
}  // namespace scenic_impl

#endif  // SRC_UI_SCENIC_LIB_INPUT_POINTER_EVENT_BUFFER_H_
