// 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 '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();
}
