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

#include "third_party/blink/renderer/modules/xr/xr_input_source.h"

#include "base/time/time.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatcher.h"
#include "third_party/blink/renderer/core/dom/events/event_path.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/html_frame_element_base.h"
#include "third_party/blink/renderer/core/input/event_handling_util.h"
#include "third_party/blink/renderer/core/layout/hit_test_location.h"
#include "third_party/blink/renderer/modules/xr/xr_grip_space.h"
#include "third_party/blink/renderer/modules/xr/xr_hand.h"
#include "third_party/blink/renderer/modules/xr/xr_input_source_event.h"
#include "third_party/blink/renderer/modules/xr/xr_session.h"
#include "third_party/blink/renderer/modules/xr/xr_session_event.h"
#include "third_party/blink/renderer/modules/xr/xr_space.h"
#include "third_party/blink/renderer/modules/xr/xr_system.h"
#include "third_party/blink/renderer/modules/xr/xr_target_ray_space.h"
#include "third_party/blink/renderer/modules/xr/xr_utils.h"

namespace blink {

namespace {
std::unique_ptr<TransformationMatrix> TryGetTransformationMatrix(
    const base::Optional<gfx::Transform>& transform) {
  if (transform) {
    return std::make_unique<TransformationMatrix>(transform->matrix());
  }

  return nullptr;
}

std::unique_ptr<TransformationMatrix> TryGetTransformationMatrix(
    const TransformationMatrix* other) {
  if (other) {
    return std::make_unique<TransformationMatrix>(*other);
  }

  return nullptr;
}
}  // namespace

XRInputSource::InternalState::InternalState(
    uint32_t source_id,
    device::mojom::XRTargetRayMode target_ray_mode,
    base::TimeTicks base_timestamp)
    : source_id(source_id),
      target_ray_mode(target_ray_mode),
      base_timestamp(base_timestamp) {}

XRInputSource::InternalState::InternalState(const InternalState& other) =
    default;

XRInputSource::InternalState::~InternalState() = default;

XRInputSource* XRInputSource::CreateOrUpdateFrom(
    XRInputSource* other,
    XRSession* session,
    const device::mojom::blink::XRInputSourceStatePtr& state) {
  if (!state)
    return other;

  XRInputSource* updated_source = other;

  // Check if we have an existing object, and if we do, if it can be re-used.
  if (!other) {
    auto source_id = state->source_id;
    updated_source = MakeGarbageCollected<XRInputSource>(session, source_id);
  } else if (other->InvalidatesSameObject(state)) {
    // Something in the state has changed which requires us to re-create the
    // object.  Create a copy now, and we will blindly update any state later,
    // knowing that we now have a new object if needed.
    updated_source = MakeGarbageCollected<XRInputSource>(*other);
  }

  if (updated_source->state_.is_visible) {
    updated_source->UpdateGamepad(state->gamepad);
  }

  // Update the input source's description if this state update includes them.
  if (state->description) {
    const device::mojom::blink::XRInputSourceDescriptionPtr& desc =
        state->description;

    updated_source->state_.target_ray_mode = desc->target_ray_mode;
    updated_source->state_.handedness = desc->handedness;

    if (updated_source->state_.is_visible) {
      updated_source->input_from_pointer_ =
          TryGetTransformationMatrix(desc->input_from_pointer);
    }

    updated_source->state_.profiles.clear();
    for (const auto& name : state->description->profiles) {
      updated_source->state_.profiles.push_back(name);
    }
  }

  if (updated_source->state_.is_visible) {
    updated_source->mojo_from_input_ =
        TryGetTransformationMatrix(state->mojo_from_input);
  }

  if (updated_source->state_.is_visible) {
    if (state->hand_tracking_data.get()) {
      updated_source->hand_ = MakeGarbageCollected<XRHand>(
          state->hand_tracking_data.get(), updated_source);
    }
  }

  updated_source->state_.emulated_position = state->emulated_position;

  return updated_source;
}

XRInputSource::XRInputSource(XRSession* session,
                             uint32_t source_id,
                             device::mojom::XRTargetRayMode target_ray_mode)
    : state_(source_id, target_ray_mode, session->xr()->NavigationStart()),
      session_(session),
      target_ray_space_(MakeGarbageCollected<XRTargetRaySpace>(session, this)),
      grip_space_(MakeGarbageCollected<XRGripSpace>(session, this)) {}

// Must make new target_ray_space_ and grip_space_ to ensure that they point to
// the correct XRInputSource object. Otherwise, the controller position gets
// stuck when an XRInputSource gets re-created. Also need to make a deep copy of
// the matrices since they use unique_ptrs.
XRInputSource::XRInputSource(const XRInputSource& other)
    : state_(other.state_),
      session_(other.session_),
      target_ray_space_(
          MakeGarbageCollected<XRTargetRaySpace>(other.session_, this)),
      grip_space_(MakeGarbageCollected<XRGripSpace>(other.session_, this)),
      gamepad_(other.gamepad_),
      hand_(other.hand_),
      mojo_from_input_(
          TryGetTransformationMatrix(other.mojo_from_input_.get())),
      input_from_pointer_(
          TryGetTransformationMatrix(other.input_from_pointer_.get())) {}

const String XRInputSource::handedness() const {
  switch (state_.handedness) {
    case device::mojom::XRHandedness::NONE:
      return "none";
    case device::mojom::XRHandedness::LEFT:
      return "left";
    case device::mojom::XRHandedness::RIGHT:
      return "right";
  }

  NOTREACHED() << "Unknown handedness: " << state_.handedness;
}

const String XRInputSource::targetRayMode() const {
  switch (state_.target_ray_mode) {
    case device::mojom::XRTargetRayMode::GAZING:
      return "gaze";
    case device::mojom::XRTargetRayMode::POINTING:
      return "tracked-pointer";
    case device::mojom::XRTargetRayMode::TAPPING:
      return "screen";
  }

  NOTREACHED() << "Unknown target ray mode: " << state_.target_ray_mode;
}

XRSpace* XRInputSource::targetRaySpace() const {
  return target_ray_space_;
}

XRSpace* XRInputSource::gripSpace() const {
  if (!state_.is_visible)
    return nullptr;

  if (state_.target_ray_mode == device::mojom::XRTargetRayMode::POINTING) {
    return grip_space_;
  }

  return nullptr;
}

bool XRInputSource::InvalidatesSameObject(
    const device::mojom::blink::XRInputSourceStatePtr& state) {
  if ((state->gamepad && !gamepad_) || (!state->gamepad && gamepad_)) {
    return true;
  }

  if (state->description) {
    if (state->description->handedness != state_.handedness) {
      return true;
    }

    if (state->description->target_ray_mode != state_.target_ray_mode) {
      return true;
    }

    if (state->description->profiles.size() != state_.profiles.size()) {
      return true;
    }

    for (wtf_size_t i = 0; i < state_.profiles.size(); ++i) {
      if (state->description->profiles[i] != state_.profiles[i]) {
        return true;
      }
    }
  }

  return false;
}

void XRInputSource::SetInputFromPointer(
    const TransformationMatrix* input_from_pointer) {
  if (state_.is_visible) {
    input_from_pointer_ = TryGetTransformationMatrix(input_from_pointer);
  }
}

void XRInputSource::SetGamepadConnected(bool state) {
  if (gamepad_)
    gamepad_->SetConnected(state);
}

void XRInputSource::UpdateGamepad(
    const base::Optional<device::Gamepad>& gamepad) {
  if (gamepad) {
    if (!gamepad_) {
      gamepad_ = MakeGarbageCollected<Gamepad>(this, -1, state_.base_timestamp,
                                               base::TimeTicks::Now());
    }

    gamepad_->UpdateFromDeviceState(*gamepad);
  } else {
    gamepad_ = nullptr;
  }
}

base::Optional<TransformationMatrix> XRInputSource::MojoFromInput() const {
  if (!mojo_from_input_.get()) {
    return base::nullopt;
  }
  return *(mojo_from_input_.get());
}

base::Optional<TransformationMatrix> XRInputSource::InputFromPointer() const {
  if (!input_from_pointer_.get()) {
    return base::nullopt;
  }
  return *(input_from_pointer_.get());
}

base::Optional<device::mojom::blink::XRNativeOriginInformation>
XRInputSource::nativeOrigin() const {
  return XRNativeOriginInformation::Create(this);
}

void XRInputSource::OnSelectStart() {
  DVLOG(3) << __func__;
  // Discard duplicate events and ones after the session has ended.
  if (state_.primary_input_pressed || session_->ended())
    return;

  state_.primary_input_pressed = true;
  state_.selection_cancelled = false;

  DVLOG(3) << __func__ << ": dispatch selectstart event";
  XRInputSourceEvent* event =
      CreateInputSourceEvent(event_type_names::kSelectstart);
  session_->DispatchEvent(*event);

  if (event->defaultPrevented())
    state_.selection_cancelled = true;

  // Ensure the frame cannot be used outside of the event handler.
  event->frame()->Deactivate();
}

void XRInputSource::OnSelectEnd() {
  DVLOG(3) << __func__;
  // Discard duplicate events and ones after the session has ended.
  if (!state_.primary_input_pressed || session_->ended())
    return;

  state_.primary_input_pressed = false;

  if (!session_->xr()->DomWindow())
    return;

  DVLOG(3) << __func__ << ": dispatch selectend event";
  XRInputSourceEvent* event =
      CreateInputSourceEvent(event_type_names::kSelectend);
  session_->DispatchEvent(*event);

  if (event->defaultPrevented())
    state_.selection_cancelled = true;

  // Ensure the frame cannot be used outside of the event handler.
  event->frame()->Deactivate();
}

void XRInputSource::OnSelect() {
  DVLOG(3) << __func__;
  // If a select was fired but we had not previously started the selection it
  // indicates a sub-frame or instantaneous select event, and we should fire a
  // selectstart prior to the selectend.
  if (!state_.primary_input_pressed) {
    OnSelectStart();
  }

  // If SelectStart caused the session to end, we shouldn't try to fire the
  // select event.
  LocalDOMWindow* window = session_->xr()->DomWindow();
  if (!window)
    return;
  LocalFrame::NotifyUserActivation(
      window->GetFrame(),
      mojom::blink::UserActivationNotificationType::kInteraction);

  if (!state_.selection_cancelled && !session_->ended()) {
    DVLOG(3) << __func__ << ": dispatch select event";
    XRInputSourceEvent* event =
        CreateInputSourceEvent(event_type_names::kSelect);
    session_->DispatchEvent(*event);

    // Ensure the frame cannot be used outside of the event handler.
    event->frame()->Deactivate();
  }

  OnSelectEnd();
}

void XRInputSource::OnSqueezeStart() {
  DVLOG(3) << __func__;
  // Discard duplicate events and ones after the session has ended.
  if (state_.primary_squeeze_pressed || session_->ended())
    return;

  state_.primary_squeeze_pressed = true;
  state_.squeezing_cancelled = false;

  XRInputSourceEvent* event =
      CreateInputSourceEvent(event_type_names::kSqueezestart);
  session_->DispatchEvent(*event);

  if (event->defaultPrevented())
    state_.squeezing_cancelled = true;

  // Ensure the frame cannot be used outside of the event handler.
  event->frame()->Deactivate();
}

void XRInputSource::OnSqueezeEnd() {
  DVLOG(3) << __func__;
  // Discard duplicate events and ones after the session has ended.
  if (!state_.primary_squeeze_pressed || session_->ended())
    return;

  state_.primary_squeeze_pressed = false;

  if (!session_->xr()->DomWindow())
    return;

  DVLOG(3) << __func__ << ": dispatch squeezeend event";
  XRInputSourceEvent* event =
      CreateInputSourceEvent(event_type_names::kSqueezeend);
  session_->DispatchEvent(*event);

  if (event->defaultPrevented())
    state_.squeezing_cancelled = true;

  // Ensure the frame cannot be used outside of the event handler.
  event->frame()->Deactivate();
}

void XRInputSource::OnSqueeze() {
  DVLOG(3) << __func__;
  // If a squeeze was fired but we had not previously started the squeezing it
  // indicates a sub-frame or instantaneous squeeze event, and we should fire a
  // squeezestart prior to the squeezeend.
  if (!state_.primary_squeeze_pressed) {
    OnSqueezeStart();
  }

  // If SelectStart caused the session to end, we shouldn't try to fire the
  // select event.
  LocalDOMWindow* window = session_->xr()->DomWindow();
  if (!window)
    return;
  LocalFrame::NotifyUserActivation(
      window->GetFrame(),
      mojom::blink::UserActivationNotificationType::kInteraction);

  // If SelectStart caused the session to end, we shouldn't try to fire the
  // select event.
  if (!state_.squeezing_cancelled && !session_->ended()) {
    DVLOG(3) << __func__ << ": dispatch squeeze event";
    XRInputSourceEvent* event =
        CreateInputSourceEvent(event_type_names::kSqueeze);
    session_->DispatchEvent(*event);

    // Ensure the frame cannot be used outside of the event handler.
    event->frame()->Deactivate();
  }

  OnSqueezeEnd();
}

void XRInputSource::UpdateButtonStates(
    const device::mojom::blink::XRInputSourceStatePtr& new_state) {
  if (!new_state)
    return;

  DVLOG(3) << __func__ << ": state_.is_visible=" << state_.is_visible
           << ", state_.xr_select_events_suppressed="
           << state_.xr_select_events_suppressed
           << ", new_state->primary_input_clicked="
           << new_state->primary_input_clicked;

  if (!state_.is_visible) {
    DVLOG(3) << __func__ << ": input NOT VISIBLE";
    if (new_state->primary_input_clicked) {
      DVLOG(3) << __func__ << ": got click while invisible, SUPPRESS end";
      state_.xr_select_events_suppressed = false;
    }
    return;
  }
  if (state_.xr_select_events_suppressed) {
    if (new_state->primary_input_clicked) {
      DVLOG(3) << __func__ << ": got click, SUPPRESS end";
      state_.xr_select_events_suppressed = false;
    }
    DVLOG(3) << __func__ << ": overlay input select SUPPRESSED";
    return;
  }

  DCHECK(!state_.xr_select_events_suppressed);

  // Handle state change of the primary input, which may fire events
  if (new_state->primary_input_clicked)
    OnSelect();

  if (new_state->primary_input_pressed) {
    OnSelectStart();
  } else if (state_.primary_input_pressed) {
    // May get here if the input source was previously pressed but now isn't,
    // but the input source did not set primary_input_clicked to true. We will
    // treat this as a cancelled selection, firing the selectend event so the
    // page stays in sync with the controller state but won't fire the
    // usual select event.
    OnSelectEnd();
  }

  // Handle state change of the primary input, which may fire events
  if (new_state->primary_squeeze_clicked)
    OnSqueeze();

  if (new_state->primary_squeeze_pressed) {
    OnSqueezeStart();
  } else if (state_.primary_squeeze_pressed) {
    // May get here if the input source was previously pressed but now isn't,
    // but the input source did not set primary_squeeze_clicked to true. We will
    // treat this as a cancelled squeezeing, firing the squeezeend event so the
    // page stays in sync with the controller state but won't fire the
    // usual squeeze event.
    OnSqueezeEnd();
  }
}

void XRInputSource::ProcessOverlayHitTest(
    Element* overlay_element,
    const device::mojom::blink::XRInputSourceStatePtr& new_state) {
  DVLOG(3) << __func__ << ": state_.xr_select_events_suppressed="
           << state_.xr_select_events_suppressed;

  DCHECK(overlay_element);
  DCHECK(new_state->overlay_pointer_position);

  // Do a hit test at the overlay pointer position to see if the pointer
  // intersects a cross origin iframe. If yes, set the visibility to false which
  // causes targetRaySpace and gripSpace to return null poses.
  FloatPoint point(new_state->overlay_pointer_position->x(),
                   new_state->overlay_pointer_position->y());
  DVLOG(3) << __func__ << ": hit test point=" << point;

  HitTestRequest::HitTestRequestType hit_type = HitTestRequest::kTouchEvent |
                                                HitTestRequest::kReadOnly |
                                                HitTestRequest::kActive;

  HitTestResult result = event_handling_util::HitTestResultInFrame(
      overlay_element->GetDocument().GetFrame(), HitTestLocation(point),
      hit_type);
  DVLOG(3) << __func__ << ": hit test InnerElement=" << result.InnerElement();

  Element* hit_element = result.InnerElement();
  if (!hit_element) {
    return;
  }

  // Check if the hit element is cross-origin content. In addition to an iframe,
  // this could potentially be an old-style frame in a frameset, so check for
  // the common base class to cover both. (There's no intention to actively
  // support framesets for DOM Overlay, but this helps prevent them from
  // being used as a mechanism for information leaks.)
  HTMLFrameElementBase* frame = DynamicTo<HTMLFrameElementBase>(hit_element);
  if (frame) {
    Document* hit_document = frame->contentDocument();
    if (hit_document) {
      Frame* hit_frame = hit_document->GetFrame();
      DCHECK(hit_frame);
      if (hit_frame->IsCrossOriginToMainFrame()) {
        // Mark the input source as invisible until the primary button is
        // released.
        state_.is_visible = false;

        // If this is the first touch, also suppress events, even if it
        // ends up being released outside the frame later.
        if (!state_.primary_input_pressed) {
          state_.xr_select_events_suppressed = true;
        }

        DVLOG(3)
            << __func__
            << ": input source overlaps with cross origin content, is_visible="
            << state_.is_visible << ", xr_select_events_suppressed="
            << state_.xr_select_events_suppressed;
        return;
      }
    }
  }

  // If we get here, the touch didn't hit a cross origin frame. Set the
  // controller spaces visible.
  state_.is_visible = true;

  // Now that the visibility check has finished, mark non-primary input sources
  // as suppressed.
  if (new_state->is_auxiliary) {
    state_.xr_select_events_suppressed = true;
  }

  // Now check if this is a new primary button press. If yes, send a
  // beforexrselect event to give the application an opportunity to cancel the
  // XR input "select" sequence that would normally be caused by this.

  if (state_.xr_select_events_suppressed) {
    DVLOG(3) << __func__ << ": using overlay input provider: SUPPRESS ongoing";
    return;
  }

  if (state_.primary_input_pressed) {
    DVLOG(3) << __func__ << ": ongoing press, not checking again";
    return;
  }

  bool is_primary_press =
      new_state->primary_input_pressed || new_state->primary_input_clicked;
  if (!is_primary_press) {
    DVLOG(3) << __func__ << ": no button press, ignoring";
    return;
  }

  // The event needs to be cancelable (obviously), bubble (so that parent
  // elements can handle it), and composed (so that it crosses shadow DOM
  // boundaries, including UA-added shadow DOM).
  Event* event = MakeGarbageCollected<XRSessionEvent>(
      event_type_names::kBeforexrselect, session_, Event::Bubbles::kYes,
      Event::Cancelable::kYes, Event::ComposedMode::kComposed);

  hit_element->DispatchEvent(*event);
  bool default_prevented = event->defaultPrevented();

  // Keep the input source visible, so it's exposed in the input sources array,
  // but don't generate XR select events for the current button sequence.
  state_.xr_select_events_suppressed = default_prevented;
  DVLOG(3) << __func__ << ": state_.xr_select_events_suppressed="
           << state_.xr_select_events_suppressed;
}

void XRInputSource::OnRemoved() {
  if (state_.primary_input_pressed) {
    state_.primary_input_pressed = false;

    XRInputSourceEvent* event =
        CreateInputSourceEvent(event_type_names::kSelectend);
    session_->DispatchEvent(*event);

    if (event->defaultPrevented())
      state_.selection_cancelled = true;

    // Ensure the frame cannot be used outside of the event handler.
    event->frame()->Deactivate();
  }

  if (state_.primary_squeeze_pressed) {
    state_.primary_squeeze_pressed = false;

    XRInputSourceEvent* event =
        CreateInputSourceEvent(event_type_names::kSqueezeend);
    session_->DispatchEvent(*event);

    if (event->defaultPrevented())
      state_.squeezing_cancelled = true;

    // Ensure the frame cannot be used outside of the event handler.
    event->frame()->Deactivate();
  }

  SetGamepadConnected(false);
}

XRInputSourceEvent* XRInputSource::CreateInputSourceEvent(
    const AtomicString& type) {
  XRFrame* presentation_frame = session_->CreatePresentationFrame();
  return XRInputSourceEvent::Create(type, presentation_frame, this);
}

void XRInputSource::Trace(Visitor* visitor) const {
  visitor->Trace(session_);
  visitor->Trace(target_ray_space_);
  visitor->Trace(grip_space_);
  visitor->Trace(gamepad_);
  visitor->Trace(hand_);
  ScriptWrappable::Trace(visitor);
}

}  // namespace blink
