// Copyright 2016 The Fuchsia 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 'package:flutter/widgets.dart';

/// Base class for classes that provide data via [InheritedWidget]s.
abstract class Model extends Listenable {
  final Set<VoidCallback> _listeners = <VoidCallback>{};
  int _version = 0;
  int _microtaskVersion = 0;

  /// [listener] will be notified when the model changes.
  @override
  void addListener(VoidCallback listener) {
    _listeners.add(listener);
  }

  /// [listener] will no longer be notified when the model changes.
  @override
  void removeListener(VoidCallback listener) {
    _listeners.remove(listener);
  }

  /// Returns the number of listeners listening to this model.
  int get listenerCount => _listeners.length;

  /// Should be called only by [Model] when the model has changed.
  void notifyListeners() {
    // We schedule a microtask as it's not uncommon for changes that trigger
    // listener notifications to occur in a build step and for listeners to
    // call setState.  Its a big no-no to setState during build so we schedule
    // for them to happen later.
    // TODO(apwilson): This is a bad-flutter-code-smell. Eliminate the need for
    // this scheduleMicrotask.
    if (_microtaskVersion == _version) {
      _microtaskVersion++;
      scheduleMicrotask(() {
        _version++;
        _microtaskVersion = _version;
        for (VoidCallback listener in _listeners) {
          listener();
        }
      });
    }
  }
}

/// Finds a [Model].  This class is necessary as templated classes are relified
/// but static templated functions are not.
class ModelFinder<T extends Model> {
  /// Returns the [Model] of type [T] of the closest ancestor [ScopedModel].
  ///
  /// [Widget]s who call [of] with a [rebuildOnChange] of true will be rebuilt
  /// whenever there's a change to the returned model.
  T of(BuildContext context, {bool rebuildOnChange = false}) {
    // ignore: prefer_const_constructors
    final Type type = _InheritedModel<T>.forRuntimeType().runtimeType;
    Widget widget = rebuildOnChange
        ? context.inheritFromWidgetOfExactType(type)
        : context.ancestorWidgetOfExactType(type);
    return (widget is _InheritedModel<T>) ? widget.model : null;
  }
}

/// Allows the given [model] to be accessed by [child] or any of its descendants
/// using [ModelFinder].
class ScopedModel<T extends Model> extends StatelessWidget {
  /// The [Model] to provide to [child] and its descendants.
  final T model;

  /// The [Widget] the [model] will be available to.
  final Widget child;

  /// Constructor.
  const ScopedModel({this.model, this.child});

  @override
  Widget build(BuildContext context) => _ModelListener(
        model: model,
        builder: (BuildContext context) => _InheritedModel<T>(
              model: model,
              child: child,
            ),
      );
}

/// Listens to [model] and calls [builder] whenever [model] changes.
class _ModelListener extends StatefulWidget {
  final Model model;
  final WidgetBuilder builder;

  const _ModelListener({this.model, this.builder});

  @override
  _ModelListenerState createState() => _ModelListenerState();
}

class _ModelListenerState extends State<_ModelListener> {
  @override
  void initState() {
    super.initState();
    widget.model.addListener(_onChange);
  }

  @override
  void didUpdateWidget(_ModelListener oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.model != oldWidget.model) {
      oldWidget.model.removeListener(_onChange);
      widget.model.addListener(_onChange);
    }
  }

  @override
  void dispose() {
    widget.model.removeListener(_onChange);
    super.dispose();
  }

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

  void _onChange() => setState(() {});
}

/// Provides [model] to its [child] [Widget] tree via [InheritedWidget].  When
/// [version] changes, all descendants who request (via
/// [BuildContext.inheritFromWidgetOfExactType]) to be rebuilt when the model
/// changes will do so.
class _InheritedModel<T extends Model> extends InheritedWidget {
  final T model;
  final int version;
  _InheritedModel({Key key, Widget child, this.model})
      : version = model._version,
        super(key: key, child: child);

  /// Used to return the runtime type.
  const _InheritedModel.forRuntimeType()
      : model = null,
        version = 0;

  @override
  bool updateShouldNotify(_InheritedModel<T> oldWidget) =>
      oldWidget.version != version;
}

/// Builds a child for a [ScopedModelDescendant].
typedef ScopedModelDescendantBuilder<T extends Model> = Widget Function(
  BuildContext context,
  Widget child,
  T model,
);

/// A [Widget] who rebuilds its child by calling [builder] whenever the [Model]
/// provided by an ancestor [ScopedModel] changes.
class ScopedModelDescendant<T extends Model> extends StatelessWidget {
  /// Called whenever the [Model] changes.
  final ScopedModelDescendantBuilder<T> builder;

  /// An optional constant child that does not depend on the model.  This will
  /// be passed as the child of [builder].
  final Widget child;

  /// Constructor.
  const ScopedModelDescendant({this.builder, this.child});

  @override
  Widget build(BuildContext context) => builder(
        context,
        child,
        ModelFinder<T>().of(context, rebuildOnChange: true),
      );
}
