// Copyright 2013 The Flutter 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 FLUTTER_SHELL_PLATFORM_FUCHSIA_POINTER_DELEGATE_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_POINTER_DELEGATE_H_

#include <fuchsia/ui/pointer/cpp/fidl.h>

#include <array>
#include <functional>
#include <optional>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "flutter/lib/ui/window/pointer_data.h"

namespace flutter_runner {

// Helper class for keying into a map.
struct IxnHasher {
  std::size_t operator()(
      const fuchsia::ui::pointer::TouchInteractionId& ixn) const {
    return std::hash<uint32_t>()(ixn.device_id) ^
           std::hash<uint32_t>()(ixn.pointer_id) ^
           std::hash<uint32_t>()(ixn.interaction_id);
  }
};

// Channel processors for fuchsia.ui.pointer.TouchSource and MouseSource
// protocols. It manages the channel state, collects touch and mouse events, and
// surfaces them to PlatformView as flutter::PointerData events for further
// processing and dispatch.
class PointerDelegate {
 public:
  PointerDelegate(fuchsia::ui::pointer::TouchSourceHandle touch_source,
                  fuchsia::ui::pointer::MouseSourceHandle mouse_source);

  // This function collects Fuchsia's TouchPointerSample and MousePointerSample
  // data and transforms them into flutter::PointerData structs. It then calls
  // the supplied callback with a vector of flutter::PointerData, which (1) does
  // last processing (applies metrics), and (2) packs these flutter::PointerData
  // in a flutter::PointerDataPacket for transport to the Engine.
  void WatchLoop(
      std::function<void(std::vector<flutter::PointerData>)> callback);

 private:
  /***** TOUCH STATE *****/

  // Channel for touch events from Scenic.
  fuchsia::ui::pointer::TouchSourcePtr touch_source_;

  // Receive touch events from Scenic. Must be copyable.
  std::function<void(std::vector<fuchsia::ui::pointer::TouchEvent>)>
      touch_responder_;

  // Per-interaction buffer of touch events from Scenic. When an interaction
  // starts with event.pointer_sample.phase == ADD, we allocate a buffer and
  // store samples. When interaction ownership becomes
  // event.interaction_result.status == GRANTED, we flush the buffer to client,
  // delete the buffer, and all future events in this interaction are flushed
  // direct to client. When interaction ownership becomes DENIED, we delete the
  // buffer, and the client does not get any previous or future events in this
  // interaction.
  //
  // There are three basic interaction forms that we need to handle, and the API
  // guarantees we see only these three forms. S=sample, R(g)=result-granted,
  // R(d)=result-denied, and + means packaged in the same table. Time flows from
  // left to right. Samples start with ADD, and end in REMOVE or CANCEL. Each
  // interaction receives just one ownership result.
  //   (1) Late grant. S S S R(g) S S S
  //   (1-a) Combo.    S S S+R(g) S S S
  //   (2) Early grant. S+R(g) S S S S S
  //   (3) Late deny. S S S R(d)
  //   (3-a) Combo.   S S S+R(d)
  //
  // This results in the following high-level algorithm to correctly deal with
  // buffer allocation and deletion, and event flushing or event dropping based
  // on ownership.
  //   if event.sample.phase == ADD && !event.result
  //     allocate buffer[event.sample.interaction]
  //   if buffer[event.sample.interaction]
  //     buffer[event.sample.interaction].push(event.sample)
  //   else
  //     flush_to_client(event.sample)
  //   if event.result
  //     if event.result == GRANTED
  //       flush_to_client(buffer[event.result.interaction])
  //     delete buffer[event.result.interaction]
  std::unordered_map<fuchsia::ui::pointer::TouchInteractionId,
                     std::vector<flutter::PointerData>,
                     IxnHasher>
      touch_buffer_;

  // The fuchsia.ui.pointer.TouchSource protocol allows one in-flight
  // hanging-get Watch() call to gather touch events, and the client is expected
  // to respond with consumption intent on the following hanging-get Watch()
  // call. Store responses here for the next call.
  std::vector<fuchsia::ui::pointer::TouchResponse> touch_responses_;

  // The fuchsia.ui.pointer.TouchSource protocol issues channel-global view
  // parameters on connection and on change. Events must apply these view
  // parameters to correctly map to logical view coordinates. The "nullopt"
  // state represents the absence of view parameters, early in the protocol
  // lifecycle.
  std::optional<fuchsia::ui::pointer::ViewParameters> touch_view_parameters_;

  /***** MOUSE STATE *****/

  // Channel for mouse events from Scenic.
  fuchsia::ui::pointer::MouseSourcePtr mouse_source_;

  // Receive mouse events from Scenic. Must be copyable.
  std::function<void(std::vector<fuchsia::ui::pointer::MouseEvent>)>
      mouse_responder_;

  // The set of mouse devices that are currently interacting with the UI.
  // A mouse is considered flutter::PointerData::Change::kDown if any button is
  // pressed. This set is used to correctly set the phase in
  // flutter::PointerData.change, with this high-level algorithm:
  //   if !mouse_down[id] && !button then: change = kHover
  //   if !mouse_down[id] &&  button then: change = kDown; mouse_down.add(id)
  //   if  mouse_down[id] &&  button then: change = kMove
  //   if  mouse_down[id] && !button then: change = kUp; mouse_down.remove(id)
  std::unordered_set</*mouse device ID*/ uint32_t> mouse_down_;

  // For each mouse device, its device-specific information, such as mouse
  // button priority order.
  std::unordered_map</*mouse device ID*/ uint32_t,
                     fuchsia::ui::pointer::MouseDeviceInfo>
      mouse_device_info_;

  // The fuchsia.ui.pointer.MouseSource protocol issues channel-global view
  // parameters on connection and on change. Events must apply these view
  // parameters to correctly map to logical view coordinates. The "nullopt"
  // state represents the absence of view parameters, early in the protocol
  // lifecycle.
  std::optional<fuchsia::ui::pointer::ViewParameters> mouse_view_parameters_;
};

}  // namespace flutter_runner
#endif  // FLUTTER_SHELL_PLATFORM_FUCHSIA_POINTER_DELEGATE_H_
