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

import 'dart:async';
import 'dart:collection';

import 'package:meta/meta.dart';

/// Generates an [AppContext] value.
///
/// Generators are allowed to return `null`, in which case the context will
/// store the `null` value as the value for that type.
typedef Generator = dynamic Function();

/// An exception thrown by [AppContext] when you try to get a [Type] value from
/// the context, and the instantiation of the value results in a dependency
/// cycle.
class ContextDependencyCycleException implements Exception {
  ContextDependencyCycleException._(this.cycle);

  /// The dependency cycle (last item depends on first item).
  final List<Type> cycle;

  @override
  String toString() => 'Dependency cycle detected: ${cycle.join(' -> ')}';
}

/// The Zone key used to look up the [AppContext].
@visibleForTesting
const Object contextKey = _Key.key;

/// The current [AppContext], as determined by the [Zone] hierarchy.
///
/// This will be the first context found as we scan up the zone hierarchy, or
/// the "root" context if a context cannot be found in the hierarchy. The root
/// context will not have any values associated with it.
///
/// This is guaranteed to never return `null`.
AppContext get context =>
    Zone.current[contextKey] as AppContext? ?? AppContext._root;

/// A lookup table (mapping types to values) and an implied scope, in which
/// code is run.
///
/// [AppContext] is used to define a singleton injection context for code that
/// is run within it. Each time you call [run], a child context (and a new
/// scope) is created.
///
/// Child contexts are created and run using zones. To read more about how
/// zones work, see https://api.dart.dev/stable/dart-async/Zone-class.html.
class AppContext {
  AppContext._(
    this._parent,
    this.name, [
    this._overrides = const <Type, Generator>{},
    this._fallbacks = const <Type, Generator>{},
  ]);

  final String? name;
  final AppContext? _parent;
  final Map<Type, Generator> _overrides;
  final Map<Type, Generator> _fallbacks;
  final Map<Type, dynamic> _values = <Type, dynamic>{};

  List<Type>? _reentrantChecks;

  /// Bootstrap context.
  static final AppContext _root = AppContext._(null, 'ROOT');

  dynamic _boxNull(dynamic value) => value ?? _BoxedNull.instance;

  dynamic _unboxNull(dynamic value) =>
      value == _BoxedNull.instance ? null : value;

  /// Returns the generated value for [type] if such a generator exists.
  ///
  /// If [generators] does not contain a mapping for the specified [type], this
  /// returns `null`.
  ///
  /// If a generator existed and generated a `null` value, this will return a
  /// boxed value indicating null.
  ///
  /// If a value for [type] has already been generated by this context, the
  /// existing value will be returned, and the generator will not be invoked.
  ///
  /// If the generator ends up triggering a reentrant call, it signals a
  /// dependency cycle, and a [ContextDependencyCycleException] will be thrown.
  dynamic _generateIfNecessary(Type type, Map<Type, Generator> generators) {
    if (!generators.containsKey(type)) {
      return null;
    }

    return _values.putIfAbsent(type, () {
      _reentrantChecks ??= <Type>[];

      final int index = _reentrantChecks!.indexOf(type);
      if (index >= 0) {
        // We're already in the process of trying to generate this type.
        throw ContextDependencyCycleException._(
            UnmodifiableListView<Type>(_reentrantChecks!.sublist(index)));
      }

      _reentrantChecks!.add(type);
      try {
        return _boxNull(generators[type]!());
      } finally {
        _reentrantChecks!.removeLast();
        if (_reentrantChecks!.isEmpty) {
          _reentrantChecks = null;
        }
      }
    });
  }

  /// Gets the value associated with the specified [type], or `null` if no
  /// such value has been associated.
  T? get<T>() {
    dynamic value = _generateIfNecessary(T, _overrides);
    if (value == null && _parent != null) {
      value = _parent!.get<T>();
    }
    return _unboxNull(value ?? _generateIfNecessary(T, _fallbacks)) as T?;
  }

  /// Runs [body] in a child context and returns the value returned by [body].
  ///
  /// If [overrides] is specified, the child context will return corresponding
  /// values when consulted via [operator[]].
  ///
  /// If [fallbacks] is specified, the child context will return corresponding
  /// values when consulted via [operator[]] only if its parent context didn't
  /// return such a value.
  ///
  /// If [name] is specified, the child context will be assigned the given
  /// name. This is useful for debugging purposes and is analogous to naming a
  /// thread in Java.
  Future<V> run<V>({
    required FutureOr<V> Function() body,
    String? name,
    Map<Type, Generator>? overrides,
    Map<Type, Generator>? fallbacks,
    ZoneSpecification? zoneSpecification,
  }) async {
    final AppContext child = AppContext._(
      this,
      name,
      Map<Type, Generator>.unmodifiable(overrides ?? const <Type, Generator>{}),
      Map<Type, Generator>.unmodifiable(fallbacks ?? const <Type, Generator>{}),
    );
    return runZoned<Future<V>>(
      () async => await body(),
      zoneValues: <_Key, AppContext>{_Key.key: child},
      zoneSpecification: zoneSpecification,
    );
  }

  @override
  String toString() {
    final StringBuffer buf = StringBuffer();
    String indent = '';
    AppContext? ctx = this;
    while (ctx != null) {
      buf.write('AppContext');
      if (ctx.name != null) {
        buf.write('[${ctx.name}]');
      }
      if (ctx._overrides.isNotEmpty) {
        buf.write('\n$indent  overrides: [${ctx._overrides.keys.join(', ')}]');
      }
      if (ctx._fallbacks.isNotEmpty) {
        buf.write('\n$indent  fallbacks: [${ctx._fallbacks.keys.join(', ')}]');
      }
      if (ctx._parent != null) {
        buf.write('\n$indent  parent: ');
      }
      ctx = ctx._parent;
      indent += '  ';
    }
    return buf.toString();
  }
}

/// Private key used to store the [AppContext] in the [Zone].
class _Key {
  const _Key();

  static const _Key key = _Key();

  @override
  String toString() => 'context';
}

/// Private object that denotes a generated `null` value.
class _BoxedNull {
  const _BoxedNull();

  static const _BoxedNull instance = _BoxedNull();
}
