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

// @dart = 2.6
part of engine;

/// The maximum [semanticsActivationAttempts] before we give up waiting for
/// the user to enable semantics.
///
/// This number is arbitrary and can be adjusted if it doesn't work well.
const int kMaxSemanticsActivationAttempts = 20;

/// After an event related to semantics activation has been received, we consume
/// the consecutive events on the engine. Do not send them to the framework.
/// For example when a 'mousedown' targeting a placeholder received following
/// 'mouseup' is also not sent to the framework.
/// Otherwise these events can cause unintended gestures on the framework side.
const Duration _periodToConsumeEvents = const Duration(milliseconds: 300);

/// The message in the label for the placeholder element used to enable
/// accessibility.
///
/// This uses US English as the default message. Set this value prior to
/// calling `runApp` to translate to another language.
String placeholderMessage = 'Enable accessibility';

/// A helper for [EngineSemanticsOwner].
///
/// [SemanticsHelper] prepares and placeholder to enable semantics.
///
/// It decides if an event is purely semantics enabling related or a regular
/// event which should be forwarded to the framework.
///
/// It does this by using a [SemanticsEnabler]. The [SemanticsEnabler]
/// implementation is choosen using form factor type.
///
/// See [DesktopSemanticsEnabler], [MobileSemanticsEnabler].
class SemanticsHelper {
  SemanticsEnabler _semanticsEnabler =
      isDesktop ? DesktopSemanticsEnabler() : MobileSemanticsEnabler();

  @visibleForTesting
  set semanticsEnabler(SemanticsEnabler semanticsEnabler) {
    this._semanticsEnabler = semanticsEnabler;
  }

  bool shouldEnableSemantics(html.Event event) {
    return _semanticsEnabler.shouldEnableSemantics(event);
  }

  html.Element prepareAccesibilityPlaceholder() {
    return _semanticsEnabler.prepareAccesibilityPlaceholder();
  }
}

@visibleForTesting
abstract class SemanticsEnabler {
  /// Whether to enable semantics.
  ///
  /// Semantics should be enabled if the web engine is no longer waiting for
  /// extra signals from the user events. See [isWaitingToEnableSemantics].
  ///
  /// Or if the received [html.Event] is suitable/enough for enabling the
  /// semantics. See [tryEnableSemantics].
  bool shouldEnableSemantics(html.Event event) {
    if (!isWaitingToEnableSemantics) {
      // Forward to framework as normal.
      return true;
    } else {
      return tryEnableSemantics(event);
    }
  }

  /// Attempts to activate semantics.
  ///
  /// Returns true if the `event` is not related to semantics activation and
  /// should be forwarded to the framework.
  bool tryEnableSemantics(html.Event event);

  /// Creates the placeholder for accesibility.
  ///
  /// Puts it inside the glasspane.
  ///
  /// On focus the element announces that accessibility can be enabled by
  /// tapping/clicking. (Announcement depends on the assistive technology)
  html.Element prepareAccesibilityPlaceholder();

  /// Whether platform is still consisering enabling semantics.
  ///
  /// At this stage a relevant set of events are always assessed to see if
  /// they activate the semantics.
  ///
  /// If not they are sent to framework as normal events.
  bool get isWaitingToEnableSemantics;
}

@visibleForTesting
class DesktopSemanticsEnabler extends SemanticsEnabler {
  /// We do not immediately enable semantics when the user requests it, but
  /// instead wait for a short period of time before doing it. This is because
  /// the request comes as an event targeted on the [_semanticsPlaceholder].
  /// This event, depending on the browser, comes as a burst of events.
  /// For example, Safari on MacOS sends "pointerup", "pointerdown". So during a
  /// short time period we consume all events and prevent forwarding to the
  /// framework. Otherwise, the events will be interpreted twice, once as a
  /// request to activate semantics, and a second time by Flutter's gesture
  /// recognizers.
  @visibleForTesting
  Timer semanticsActivationTimer;

  /// A temporary placeholder used to capture a request to activate semantics.
  html.Element _semanticsPlaceholder;

  /// The number of events we processed that could potentially activate
  /// semantics.
  int semanticsActivationAttempts = 0;

  /// Instructs [_tryEnableSemantics] to remove [_semanticsPlaceholder].
  ///
  /// The placeholder is removed upon any next event.
  bool _schedulePlaceholderRemoval = false;

  /// Whether we are waiting for the user to enable semantics.
  @override
  bool get isWaitingToEnableSemantics => _semanticsPlaceholder != null;

  @override
  bool tryEnableSemantics(html.Event event) {
    if (_schedulePlaceholderRemoval) {
      _semanticsPlaceholder.remove();
      _semanticsPlaceholder = null;
      semanticsActivationTimer = null;
      return true;
    }

    if (EngineSemanticsOwner.instance.semanticsEnabled) {
      // Semantics already enabled, forward to framework as normal.
      return true;
    }

    // In touch screen laptops, the touch is received as a mouse click
    const Set<String> kInterestingEventTypes = <String>{
      'click',
      'keyup',
      'keydown',
      'mouseup',
      'mousedown',
      'pointerdown',
      'pointerup',
    };

    if (!kInterestingEventTypes.contains(event.type)) {
      // The event is not relevant, forward to framework as normal.
      return true;
    }

    semanticsActivationAttempts += 1;
    if (semanticsActivationAttempts >= kMaxSemanticsActivationAttempts) {
      // We have received multiple user events, none of which resulted in
      // semantics activation. This is a signal that the user is not interested
      // in semantics, and so we will stop waiting for it.
      _schedulePlaceholderRemoval = true;
      return true;
    }

    if (semanticsActivationTimer != null) {
      // We are in a waiting period to activate a timer. While the timer is
      // active we should consume events pertaining to semantics activation.
      // Otherwise the event will also be interpreted by the framework and
      // potentially result in activating a gesture in the app.
      return false;
    }

    // Check for the event target.
    final bool enableConditionPassed = (event.target == _semanticsPlaceholder);

    if (enableConditionPassed) {
      assert(semanticsActivationTimer == null);
      semanticsActivationTimer = Timer(_periodToConsumeEvents, () {
        EngineSemanticsOwner.instance.semanticsEnabled = true;
        _schedulePlaceholderRemoval = true;
      });
      return false;
    }

    // This was not a semantics activating event; forward as normal.
    return true;
  }

  @override
  html.Element prepareAccesibilityPlaceholder() {
    _semanticsPlaceholder = html.Element.tag('flt-semantics-placeholder');

    // Only listen to "click" because other kinds of events are reported via
    // PointerBinding.
    _semanticsPlaceholder.addEventListener('click', (html.Event event) {
      tryEnableSemantics(event);
    }, true);

    // Adding roles to semantics placeholder. 'aria-live' will make sure that
    // the content is announced to the assistive technology user as soon as the
    // page receives focus. 'tab-index' makes sure the button is the first
    // target of tab. 'aria-label' is used to define the placeholder message
    // to the assistive technology user.
    _semanticsPlaceholder
      ..setAttribute('role', 'button')
      ..setAttribute('aria-live', 'true')
      ..setAttribute('tabindex', '0')
      ..setAttribute('aria-label', placeholderMessage);
    _semanticsPlaceholder.style
      ..position = 'absolute'
      ..left = '-1px'
      ..top = '-1px'
      ..width = '1px'
      ..height = '1px';
    return _semanticsPlaceholder;
  }
}

@visibleForTesting
class MobileSemanticsEnabler extends SemanticsEnabler {
  /// We do not immediately enable semantics when the user requests it, but
  /// instead wait for a short period of time before doing it. This is because
  /// the request comes as an event targeted on the [_semanticsPlaceholder].
  /// This event, depending on the browser, comes as a burst of events.
  /// For example, Safari on IOS sends "touchstart", "touchend", and "click".
  /// So during a short time period we consume all events and prevent forwarding
  /// to the framework. Otherwise, the events will be interpreted twice, once as
  /// a request to activate semantics, and a second time by Flutter's gesture
  /// recognizers.
  @visibleForTesting
  Timer semanticsActivationTimer;

  /// A temporary placeholder used to capture a request to activate semantics.
  html.Element _semanticsPlaceholder;

  /// The number of events we processed that could potentially activate
  /// semantics.
  int semanticsActivationAttempts = 0;

  /// Instructs [_tryEnableSemantics] to remove [_semanticsPlaceholder].
  ///
  /// For Blink browser engine the placeholder is removed upon any next event.
  ///
  /// For Webkit browser engine the placeholder is removed upon the next
  /// "touchend" event. This is to prevent Safari from swallowing the event
  /// that happens on an element that's being removed. Blink doesn't have
  /// this issue.
  bool _schedulePlaceholderRemoval = false;

  /// Whether we are waiting for the user to enable semantics.
  @override
  bool get isWaitingToEnableSemantics => _semanticsPlaceholder != null;

  @override
  bool tryEnableSemantics(html.Event event) {
    if (_schedulePlaceholderRemoval) {
      final bool removeNow =
          (browserEngine != BrowserEngine.webkit || event.type == 'touchend');
      if (removeNow) {
        _semanticsPlaceholder.remove();
        _semanticsPlaceholder = null;
        semanticsActivationTimer = null;
      }
      return true;
    }

    if (EngineSemanticsOwner.instance.semanticsEnabled) {
      // Semantics already enabled, forward to framework as normal.
      return true;
    }

    semanticsActivationAttempts += 1;
    if (semanticsActivationAttempts >= kMaxSemanticsActivationAttempts) {
      // We have received multiple user events, none of which resulted in
      // semantics activation. This is a signal that the user is not interested
      // in semantics, and so we will stop waiting for it.
      _schedulePlaceholderRemoval = true;
      return true;
    }

    const Set<String> kInterestingEventTypes = <String>{
      'click',
      'touchstart',
      'touchend',
    };

    if (!kInterestingEventTypes.contains(event.type)) {
      // The event is not relevant, forward to framework as normal.
      return true;
    }

    if (semanticsActivationTimer != null) {
      // We are in a waiting period to activate a timer. While the timer is
      // active we should consume events pertaining to semantics activation.
      // Otherwise the event will also be interpreted by the framework and
      // potentially result in activating a gesture in the app.
      return false;
    }

    // In Chrome the debouncing works well enough to detect accessibility
    // request.
    final bool blinkEnableConditionPassed =
        browserEngine == BrowserEngine.blink &&
            EngineSemanticsOwner.instance.gestureMode ==
                GestureMode.browserGestures;

    // In Safari debouncing doesn't work. Instead we look at where exactly
    // (within 1 pixel) the event landed. If it landed exactly in the middle of
    // the placeholder we interpret it as a signal to enable accessibility. This
    // is because when VoiceOver generates a tap it lands it in the middle of
    // the focused element. This method is a bit flawed in that a user's finger
    // could theoretically land in the middle of the element too. However, the
    // chance of that happening is very small. Even low-end phones typically
    // have >2 million pixels (e.g. Moto G4). It is very unlikely that a user
    // will land their finger exactly in the middle. In the worst case an
    // unlucky user would accidentally enable accessibility and the app will be
    // slightly slower than normal, but the app will continue functioning as
    // normal. Our semantics tree is designed to not interfere with Flutter's
    // gesture detection.
    bool safariEnableConditionPassed = false;
    if (browserEngine == BrowserEngine.webkit) {
      html.Point<num> activationPoint;

      switch (event.type) {
        case 'click':
          final html.MouseEvent click = event;
          activationPoint = click.offset;
          break;
        case 'touchstart':
        case 'touchend':
          final html.TouchEvent touch = event;
          activationPoint = touch.changedTouches.first.client;
          break;
        default:
          // The event is not relevant, forward to framework as normal.
          return true;
      }

      assert(activationPoint != null);

      final html.Rectangle<num> activatingElementRect =
          domRenderer.glassPaneElement.getBoundingClientRect();
      final double midX = activatingElementRect.left +
          (activatingElementRect.right - activatingElementRect.left) / 2;
      final double midY = activatingElementRect.top +
          (activatingElementRect.bottom - activatingElementRect.top) / 2;
      final double deltaX = activationPoint.x - midX;
      final double deltaY = activationPoint.y - midY;
      final double deltaSquared = deltaX * deltaX + deltaY * deltaY;
      if (deltaSquared < 1.0) {
        safariEnableConditionPassed = true;
      }
    }

    if (blinkEnableConditionPassed || safariEnableConditionPassed) {
      assert(semanticsActivationTimer == null);
      semanticsActivationTimer = Timer(_periodToConsumeEvents, () {
        EngineSemanticsOwner.instance.semanticsEnabled = true;
        _schedulePlaceholderRemoval = true;
      });
      return false;
    }

    // This was not a semantics activating event; forward as normal.
    return true;
  }

  @override
  html.Element prepareAccesibilityPlaceholder() {
    _semanticsPlaceholder = html.Element.tag('flt-semantics-placeholder');

    // Only listen to "click" because other kinds of events are reported via
    // PointerBinding.
    _semanticsPlaceholder.addEventListener('click', (html.Event event) {
      tryEnableSemantics(event);
    }, true);

    _semanticsPlaceholder
      ..setAttribute('role', 'button')
      ..setAttribute('aria-label', placeholderMessage);
    _semanticsPlaceholder.style
      ..position = 'absolute'
      ..left = '0'
      ..top = '0'
      ..right = '0'
      ..bottom = '0';

    return _semanticsPlaceholder;
  }
}
