// Copyright 2019 The Flutter team. 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/material.dart';
import 'package:flutter/scheduler.dart';

import 'package:gallery/feature_discovery/animation.dart';
import 'package:gallery/feature_discovery/overlay.dart';

/// [Widget] to enforce a global lock system for [FeatureDiscovery] widgets.
///
/// This widget enforces that at most one [FeatureDiscovery] widget in its
/// widget tree is shown at a time.
///
/// Users wanting to use [FeatureDiscovery] need to put this controller
/// above [FeatureDiscovery] widgets in the widget tree.
class FeatureDiscoveryController extends StatefulWidget {
  final Widget child;

  const FeatureDiscoveryController(this.child, {super.key});

  static _FeatureDiscoveryControllerState _of(BuildContext context) {
    final matchResult =
        context.findAncestorStateOfType<_FeatureDiscoveryControllerState>();
    if (matchResult != null) {
      return matchResult;
    }

    throw FlutterError(
        'FeatureDiscoveryController.of() called with a context that does not '
        'contain a FeatureDiscoveryController.\n The context used was:\n '
        '$context');
  }

  @override
  State<FeatureDiscoveryController> createState() =>
      _FeatureDiscoveryControllerState();
}

class _FeatureDiscoveryControllerState
    extends State<FeatureDiscoveryController> {
  bool _isLocked = false;

  /// Flag to indicate whether a [FeatureDiscovery] widget descendant is
  /// currently showing its overlay or not.
  ///
  /// If true, then no other [FeatureDiscovery] widget should display its
  /// overlay.
  bool get isLocked => _isLocked;

  /// Lock the controller.
  ///
  /// Note we do not [setState] here because this function will be called
  /// by the first [FeatureDiscovery] ready to show its overlay, and any
  /// additional [FeatureDiscovery] widgets wanting to show their overlays
  /// will already be scheduled to be built, so the lock change will be caught
  /// in their builds.
  void lock() => _isLocked = true;

  /// Unlock the controller.
  void unlock() => setState(() => _isLocked = false);

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    assert(
      context.findAncestorStateOfType<_FeatureDiscoveryControllerState>() ==
          null,
      'There should not be another ancestor of type '
      'FeatureDiscoveryController in the widget tree.',
    );
  }

  @override
  Widget build(BuildContext context) => widget.child;
}

/// Widget that highlights the [child] with an overlay.
///
/// This widget loosely follows the guidelines set forth in the Material Specs:
/// https://material.io/archive/guidelines/growth-communications/feature-discovery.html.
class FeatureDiscovery extends StatefulWidget {
  /// Title to be displayed in the overlay.
  final String title;

  /// Description to be displayed in the overlay.
  final String description;

  /// Icon to be promoted.
  final Icon child;

  /// Flag to indicate whether to show the overlay or not anchored to the
  /// [child].
  final bool showOverlay;

  /// Callback invoked when the user dismisses an overlay.
  final void Function()? onDismiss;

  /// Callback invoked when the user taps on the tap target of an overlay.
  final void Function()? onTap;

  /// Color with which to fill the outer circle.
  final Color? color;

  @visibleForTesting
  static const overlayKey = Key('overlay key');

  @visibleForTesting
  static const gestureDetectorKey = Key('gesture detector key');

  const FeatureDiscovery({
    super.key,
    required this.title,
    required this.description,
    required this.child,
    required this.showOverlay,
    this.onDismiss,
    this.onTap,
    this.color,
  });

  @override
  State<FeatureDiscovery> createState() => _FeatureDiscoveryState();
}

class _FeatureDiscoveryState extends State<FeatureDiscovery>
    with TickerProviderStateMixin {
  bool showOverlay = false;
  FeatureDiscoveryStatus status = FeatureDiscoveryStatus.closed;

  late AnimationController openController;
  late AnimationController rippleController;
  late AnimationController tapController;
  late AnimationController dismissController;

  late Animations animations;
  OverlayEntry? overlay;

  Widget buildOverlay(BuildContext ctx, Offset center) {
    debugCheckHasMediaQuery(ctx);
    debugCheckHasDirectionality(ctx);

    final deviceSize = MediaQuery.of(ctx).size;
    final color = widget.color ?? Theme.of(ctx).colorScheme.primary;

    // Wrap in transparent [Material] to enable widgets that require one.
    return Material(
      key: FeatureDiscovery.overlayKey,
      type: MaterialType.transparency,
      child: Stack(
        children: [
          MouseRegion(
            cursor: SystemMouseCursors.click,
            child: GestureDetector(
              key: FeatureDiscovery.gestureDetectorKey,
              onTap: dismiss,
              child: Container(
                width: double.infinity,
                height: double.infinity,
                color: Colors.transparent,
              ),
            ),
          ),
          Background(
            animations: animations,
            status: status,
            color: color,
            center: center,
            deviceSize: deviceSize,
            textDirection: Directionality.of(ctx),
          ),
          Content(
            animations: animations,
            status: status,
            center: center,
            deviceSize: deviceSize,
            title: widget.title,
            description: widget.description,
            textTheme: Theme.of(ctx).textTheme,
          ),
          Ripple(
            animations: animations,
            status: status,
            center: center,
          ),
          TapTarget(
            animations: animations,
            status: status,
            center: center,
            onTap: tap,
            child: widget.child,
          ),
        ],
      ),
    );
  }

  /// Method to handle user tap on [TapTarget].
  ///
  /// Tapping will stop any active controller and start the [tapController].
  void tap() {
    openController.stop();
    rippleController.stop();
    dismissController.stop();
    tapController.forward(from: 0.0);
  }

  /// Method to handle user dismissal.
  ///
  /// Dismissal will stop any active controller and start the
  /// [dismissController].
  void dismiss() {
    openController.stop();
    rippleController.stop();
    tapController.stop();
    dismissController.forward(from: 0.0);
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (ctx, _) {
      if (overlay != null) {
        SchedulerBinding.instance.addPostFrameCallback((_) {
          // [OverlayEntry] needs to be explicitly rebuilt when necessary.
          overlay!.markNeedsBuild();
        });
      } else {
        if (showOverlay && !FeatureDiscoveryController._of(ctx).isLocked) {
          final entry = OverlayEntry(
            builder: (_) => buildOverlay(ctx, getOverlayCenter(ctx)),
          );

          // Lock [FeatureDiscoveryController] early in order to prevent
          // another [FeatureDiscovery] widget from trying to show its
          // overlay while the post frame callback and set state are not
          // complete.
          FeatureDiscoveryController._of(ctx).lock();

          SchedulerBinding.instance.addPostFrameCallback((_) {
            setState(() {
              overlay = entry;
              status = FeatureDiscoveryStatus.closed;
              openController.forward(from: 0.0);
            });
            Overlay.of(context).insert(entry);
          });
        }
      }
      return widget.child;
    });
  }

  /// Compute the center position of the overlay.
  Offset getOverlayCenter(BuildContext parentCtx) {
    final box = parentCtx.findRenderObject() as RenderBox;
    final size = box.size;
    final topLeftPosition = box.localToGlobal(Offset.zero);
    final centerPosition = Offset(
      topLeftPosition.dx + size.width / 2,
      topLeftPosition.dy + size.height / 2,
    );
    return centerPosition;
  }

  @override
  void initState() {
    super.initState();

    initAnimationControllers();
    initAnimations();
    showOverlay = widget.showOverlay;
  }

  void initAnimationControllers() {
    openController = AnimationController(
      duration: const Duration(milliseconds: 500),
      vsync: this,
    )
      ..addListener(() {
        setState(() {});
      })
      ..addStatusListener((animationStatus) {
        if (animationStatus == AnimationStatus.forward) {
          setState(() => status = FeatureDiscoveryStatus.open);
        } else if (animationStatus == AnimationStatus.completed) {
          rippleController.forward(from: 0.0);
        }
      });

    rippleController = AnimationController(
      duration: const Duration(milliseconds: 1000),
      vsync: this,
    )
      ..addListener(() {
        setState(() {});
      })
      ..addStatusListener((animationStatus) {
        if (animationStatus == AnimationStatus.forward) {
          setState(() => status = FeatureDiscoveryStatus.ripple);
        } else if (animationStatus == AnimationStatus.completed) {
          rippleController.forward(from: 0.0);
        }
      });

    tapController = AnimationController(
      duration: const Duration(milliseconds: 250),
      vsync: this,
    )
      ..addListener(() {
        setState(() {});
      })
      ..addStatusListener((animationStatus) {
        if (animationStatus == AnimationStatus.forward) {
          setState(() => status = FeatureDiscoveryStatus.tap);
        } else if (animationStatus == AnimationStatus.completed) {
          widget.onTap?.call();
          cleanUponOverlayClose();
        }
      });

    dismissController = AnimationController(
      duration: const Duration(milliseconds: 250),
      vsync: this,
    )
      ..addListener(() {
        setState(() {});
      })
      ..addStatusListener((animationStatus) {
        if (animationStatus == AnimationStatus.forward) {
          setState(() => status = FeatureDiscoveryStatus.dismiss);
        } else if (animationStatus == AnimationStatus.completed) {
          widget.onDismiss?.call();
          cleanUponOverlayClose();
        }
      });
  }

  void initAnimations() {
    animations = Animations(
      openController,
      tapController,
      rippleController,
      dismissController,
    );
  }

  /// Clean up once overlay has been dismissed or tap target has been tapped.
  ///
  /// This is called upon [tapController] and [dismissController] end.
  void cleanUponOverlayClose() {
    FeatureDiscoveryController._of(context).unlock();
    setState(() {
      status = FeatureDiscoveryStatus.closed;
      showOverlay = false;
      overlay?.remove();
      overlay = null;
    });
  }

  @override
  void didUpdateWidget(FeatureDiscovery oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.showOverlay != oldWidget.showOverlay) {
      showOverlay = widget.showOverlay;
    }
  }

  @override
  void dispose() {
    overlay?.remove();
    openController.dispose();
    rippleController.dispose();
    tapController.dispose();
    dismissController.dispose();
    super.dispose();
  }
}
