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

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';

import 'basic.dart';
import 'debug.dart';
import 'framework.dart';
import 'gesture_detector.dart';
import 'navigator.dart';
import 'transitions.dart';

/// A widget that modifies the size of the [SemanticsNode.rect] created by its
/// child widget.
///
/// It clips the focus in potentially four directions based on the
/// specified [EdgeInsets].
///
/// The size of the accessibility focus is adjusted based on value changes
/// inside the given [ValueNotifier].
///
/// See also:
///
///  * [ModalBarrier], which utilizes this widget to adjust the barrier focus
/// size based on the size of the content layer rendered on top of it.
class _SemanticsClipper extends SingleChildRenderObjectWidget{
  /// creates a [SemanticsClipper] that updates the size of the
  /// [SemanticsNode.rect] of its child based on the value inside the provided
  /// [ValueNotifier], or a default value of [EdgeInsets.zero].
  const _SemanticsClipper({
    super.child,
    required this.clipDetailsNotifier,
  });

  /// The [ValueNotifier] whose value determines how the child's
  /// [SemanticsNode.rect] should be clipped in four directions.
  final ValueNotifier<EdgeInsets> clipDetailsNotifier;

  @override
  _RenderSemanticsClipper createRenderObject(BuildContext context) {
    return _RenderSemanticsClipper(clipDetailsNotifier: clipDetailsNotifier,);
  }

  @override
  void updateRenderObject(BuildContext context, _RenderSemanticsClipper renderObject) {
    renderObject.clipDetailsNotifier = clipDetailsNotifier;
  }
}
/// Updates the [SemanticsNode.rect] of its child based on the value inside
/// provided [ValueNotifier].
class _RenderSemanticsClipper extends RenderProxyBox {
  /// Creates a [RenderProxyBox] that Updates the [SemanticsNode.rect] of its child
  /// based on the value inside provided [ValueNotifier].
  _RenderSemanticsClipper({
    required ValueNotifier<EdgeInsets> clipDetailsNotifier,
    RenderBox? child,
  }) : _clipDetailsNotifier = clipDetailsNotifier,
      super(child);

  ValueNotifier<EdgeInsets> _clipDetailsNotifier;

  /// The getter and setter retrieves / updates the [ValueNotifier] associated
  /// with this clipper.
  ValueNotifier<EdgeInsets> get clipDetailsNotifier => _clipDetailsNotifier;
  set clipDetailsNotifier (ValueNotifier<EdgeInsets> newNotifier) {
    if (_clipDetailsNotifier == newNotifier) {
      return;
    }
    if(attached) {
      _clipDetailsNotifier.removeListener(markNeedsSemanticsUpdate);
    }
    _clipDetailsNotifier = newNotifier;
    _clipDetailsNotifier.addListener(markNeedsSemanticsUpdate);
    markNeedsSemanticsUpdate();
  }

  @override
  Rect get semanticBounds {
    final EdgeInsets clipDetails = _clipDetailsNotifier.value;
    final Rect originalRect = super.semanticBounds;
    final Rect clippedRect = Rect.fromLTRB(
      originalRect.left + clipDetails.left,
      originalRect.top + clipDetails.top,
      originalRect.right - clipDetails.right,
      originalRect.bottom - clipDetails.bottom,
    );
    return clippedRect;
  }

  @override
  void attach(PipelineOwner owner) {
    super.attach(owner);
    clipDetailsNotifier.addListener(markNeedsSemanticsUpdate);
  }

  @override
  void detach() {
    clipDetailsNotifier.removeListener(markNeedsSemanticsUpdate);
    super.detach();
  }

  @override
  void describeSemanticsConfiguration(SemanticsConfiguration config) {
    super.describeSemanticsConfiguration(config);
    config.isSemanticBoundary = true;
  }
}

/// A widget that prevents the user from interacting with widgets behind itself.
///
/// The modal barrier is the scrim that is rendered behind each route, which
/// generally prevents the user from interacting with the route below the
/// current route, and normally partially obscures such routes.
///
/// For example, when a dialog is on the screen, the page below the dialog is
/// usually darkened by the modal barrier.
///
/// See also:
///
///  * [ModalRoute], which indirectly uses this widget.
///  * [AnimatedModalBarrier], which is similar but takes an animated [color]
///    instead of a single color value.
class ModalBarrier extends StatelessWidget {
  /// Creates a widget that blocks user interaction.
  const ModalBarrier({
    super.key,
    this.color,
    this.dismissible = true,
    this.onDismiss,
    this.semanticsLabel,
    this.barrierSemanticsDismissible = true,
    this.clipDetailsNotifier,
    this.semanticsOnTapHint,
  });

  /// If non-null, fill the barrier with this color.
  ///
  /// See also:
  ///
  ///  * [ModalRoute.barrierColor], which controls this property for the
  ///    [ModalBarrier] built by [ModalRoute] pages.
  final Color? color;

  /// Specifies if the barrier will be dismissed when the user taps on it.
  ///
  /// If true, and [onDismiss] is non-null, [onDismiss] will be called,
  /// otherwise the current route will be popped from the ambient [Navigator].
  ///
  /// If false, tapping on the barrier will do nothing.
  ///
  /// See also:
  ///
  ///  * [ModalRoute.barrierDismissible], which controls this property for the
  ///    [ModalBarrier] built by [ModalRoute] pages.
  final bool dismissible;

  /// {@template flutter.widgets.ModalBarrier.onDismiss}
  /// Called when the barrier is being dismissed.
  ///
  /// If non-null [onDismiss] will be called in place of popping the current
  /// route. It is up to the callback to handle dismissing the barrier.
  ///
  /// If null, the ambient [Navigator]'s current route will be popped.
  ///
  /// This field is ignored if [dismissible] is false.
  /// {@endtemplate}
  final VoidCallback? onDismiss;

  /// Whether the modal barrier semantics are included in the semantics tree.
  ///
  /// See also:
  ///
  ///  * [ModalRoute.semanticsDismissible], which controls this property for
  ///    the [ModalBarrier] built by [ModalRoute] pages.
  final bool? barrierSemanticsDismissible;

  /// Semantics label used for the barrier if it is [dismissible].
  ///
  /// The semantics label is read out by accessibility tools (e.g. TalkBack
  /// on Android and VoiceOver on iOS) when the barrier is focused.
  ///
  /// See also:
  ///
  ///  * [ModalRoute.barrierLabel], which controls this property for the
  ///    [ModalBarrier] built by [ModalRoute] pages.
  final String? semanticsLabel;

  /// {@template flutter.widgets.ModalBarrier.clipDetailsNotifier}
  /// Contains a value of type [EdgeInsets] that specifies how the
  /// [SemanticsNode.rect] of the widget should be clipped.
  ///
  /// See also:
  ///
  ///  * [_SemanticsClipper], which utilizes the value inside to update the
  /// [SemanticsNode.rect] for its child.
  /// {@endtemplate}
  final ValueNotifier<EdgeInsets>? clipDetailsNotifier;

  /// {@macro flutter.material.ModalBottomSheetRoute.barrierOnTapHint}
  final String? semanticsOnTapHint;

  @override
  Widget build(BuildContext context) {
    assert(!dismissible || semanticsLabel == null || debugCheckHasDirectionality(context));
    final bool platformSupportsDismissingBarrier;
    switch (defaultTargetPlatform) {
      case TargetPlatform.fuchsia:
      case TargetPlatform.linux:
      case TargetPlatform.windows:
        platformSupportsDismissingBarrier = false;
      case TargetPlatform.android:
      case TargetPlatform.iOS:
      case TargetPlatform.macOS:
        platformSupportsDismissingBarrier = true;
    }
    final bool semanticsDismissible = dismissible && platformSupportsDismissingBarrier;
    final bool modalBarrierSemanticsDismissible = barrierSemanticsDismissible ?? semanticsDismissible;

    void handleDismiss() {
      if (dismissible) {
        if (onDismiss != null) {
          onDismiss!();
        } else {
          Navigator.maybePop(context);
        }
      } else {
        SystemSound.play(SystemSoundType.alert);
      }
    }

    Widget barrier = Semantics(
      onTapHint: semanticsOnTapHint,
      onTap: semanticsDismissible && semanticsLabel != null ? handleDismiss : null,
      onDismiss: semanticsDismissible && semanticsLabel != null ? handleDismiss : null,
      label: semanticsDismissible ? semanticsLabel : null,
      textDirection: semanticsDismissible && semanticsLabel != null ? Directionality.of(context) : null,
      child: MouseRegion(
        cursor: SystemMouseCursors.basic,
        child: ConstrainedBox(
        constraints: const BoxConstraints.expand(),
        child: color == null ? null : ColoredBox(
          color: color!,
          ),
        ),
      ),
    );

    // Developers can set [dismissible: true] and [barrierSemanticsDismissible: true]
    // to allow assistive technology users to dismiss a modal BottomSheet by
    // tapping on the Scrim focus.
    // On iOS, some modal barriers are not dismissible in accessibility mode.
    final bool excluding = !semanticsDismissible || !modalBarrierSemanticsDismissible;

    if (!excluding && clipDetailsNotifier != null) {
      barrier = _SemanticsClipper(
        clipDetailsNotifier: clipDetailsNotifier!,
        child: barrier,
      );
    }

    return BlockSemantics(
      child: ExcludeSemantics(
        excluding: excluding,
        child: _ModalBarrierGestureDetector(
          onDismiss: handleDismiss,
          child: barrier,
        ),
      ),
    );
  }
}

/// A widget that prevents the user from interacting with widgets behind itself,
/// and can be configured with an animated color value.
///
/// The modal barrier is the scrim that is rendered behind each route, which
/// generally prevents the user from interacting with the route below the
/// current route, and normally partially obscures such routes.
///
/// For example, when a dialog is on the screen, the page below the dialog is
/// usually darkened by the modal barrier.
///
/// This widget is similar to [ModalBarrier] except that it takes an animated
/// [color] instead of a single color.
///
/// See also:
///
///  * [ModalRoute], which uses this widget.
class AnimatedModalBarrier extends AnimatedWidget {
  /// Creates a widget that blocks user interaction.
  const AnimatedModalBarrier({
    super.key,
    required Animation<Color?> color,
    this.dismissible = true,
    this.semanticsLabel,
    this.barrierSemanticsDismissible,
    this.onDismiss,
    this.clipDetailsNotifier,
    this.semanticsOnTapHint,
  }) : super(listenable: color);

  /// If non-null, fill the barrier with this color.
  ///
  /// See also:
  ///
  ///  * [ModalRoute.barrierColor], which controls this property for the
  ///    [AnimatedModalBarrier] built by [ModalRoute] pages.
  Animation<Color?> get color => listenable as Animation<Color?>;

  /// Whether touching the barrier will pop the current route off the [Navigator].
  ///
  /// See also:
  ///
  ///  * [ModalRoute.barrierDismissible], which controls this property for the
  ///    [AnimatedModalBarrier] built by [ModalRoute] pages.
  final bool dismissible;

  /// Semantics label used for the barrier if it is [dismissible].
  ///
  /// The semantics label is read out by accessibility tools (e.g. TalkBack
  /// on Android and VoiceOver on iOS) when the barrier is focused.
  /// See also:
  ///
  ///  * [ModalRoute.barrierLabel], which controls this property for the
  ///    [ModalBarrier] built by [ModalRoute] pages.
  final String? semanticsLabel;

  /// Whether the modal barrier semantics are included in the semantics tree.
  ///
  /// See also:
  ///
  ///  * [ModalRoute.semanticsDismissible], which controls this property for
  ///    the [ModalBarrier] built by [ModalRoute] pages.
  final bool? barrierSemanticsDismissible;

  /// {@macro flutter.widgets.ModalBarrier.onDismiss}
  final VoidCallback? onDismiss;

  /// {@macro flutter.widgets.ModalBarrier.clipDetailsNotifier}
  final ValueNotifier<EdgeInsets>? clipDetailsNotifier;

  /// This hint text instructs users what they are able to do when they tap on
  /// the [ModalBarrier]
  ///
  /// E.g. If the hint text is 'close bottom sheet", it will be announced as
  /// "Double tap to close bottom sheet".
  ///
  /// If this value is null, the default onTapHint will be applied, resulting
  /// in the announcement of 'Double tap to activate'.
  final String? semanticsOnTapHint;

  @override
  Widget build(BuildContext context) {
    return ModalBarrier(
      color: color.value,
      dismissible: dismissible,
      semanticsLabel: semanticsLabel,
      barrierSemanticsDismissible: barrierSemanticsDismissible,
      onDismiss: onDismiss,
      clipDetailsNotifier: clipDetailsNotifier,
      semanticsOnTapHint: semanticsOnTapHint,
    );
  }
}

// Recognizes tap down by any pointer button.
//
// It is similar to [TapGestureRecognizer.onTapDown], but accepts any single
// button, which means the gesture also takes parts in gesture arenas.
class _AnyTapGestureRecognizer extends BaseTapGestureRecognizer {
  _AnyTapGestureRecognizer();

  VoidCallback? onAnyTapUp;

  @protected
  @override
  bool isPointerAllowed(PointerDownEvent event) {
    if (onAnyTapUp == null) {
      return false;
    }
    return super.isPointerAllowed(event);
  }

  @protected
  @override
  void handleTapDown({PointerDownEvent? down}) {
    // Do nothing.
  }

  @protected
  @override
  void handleTapUp({PointerDownEvent? down, PointerUpEvent? up}) {
    onAnyTapUp?.call();
  }

  @protected
  @override
  void handleTapCancel({PointerDownEvent? down, PointerCancelEvent? cancel, String? reason}) {
    // Do nothing.
  }

  @override
  String get debugDescription => 'any tap';
}

class _AnyTapGestureRecognizerFactory extends GestureRecognizerFactory<_AnyTapGestureRecognizer> {
  const _AnyTapGestureRecognizerFactory({this.onAnyTapUp});

  final VoidCallback? onAnyTapUp;

  @override
  _AnyTapGestureRecognizer constructor() => _AnyTapGestureRecognizer();

  @override
  void initializer(_AnyTapGestureRecognizer instance) {
    instance.onAnyTapUp = onAnyTapUp;
  }
}

// A GestureDetector used by ModalBarrier. It only has one callback,
// [onAnyTapDown], which recognizes tap down unconditionally.
class _ModalBarrierGestureDetector extends StatelessWidget {
  const _ModalBarrierGestureDetector({
    required this.child,
    required this.onDismiss,
  });

  /// The widget below this widget in the tree.
  /// See [RawGestureDetector.child].
  final Widget child;

  /// Immediately called when an event that should dismiss the modal barrier
  /// has happened.
  final VoidCallback onDismiss;

  @override
  Widget build(BuildContext context) {
    final Map<Type, GestureRecognizerFactory> gestures = <Type, GestureRecognizerFactory>{
      _AnyTapGestureRecognizer: _AnyTapGestureRecognizerFactory(onAnyTapUp: onDismiss),
    };

    return RawGestureDetector(
      gestures: gestures,
      behavior: HitTestBehavior.opaque,
      child: child,
    );
  }
}
