// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'union_set.dart';

/// A controller that exposes a view of the union of a collection of sets.
///
/// This is a convenience class for creating a [UnionSet] whose contents change
/// over the lifetime of a class. For example:
///
/// ```dart
/// class Engine {
///   Set<Test> get activeTests => _activeTestsGroup.set;
///   final _activeTestsGroup = new UnionSetController<Test>();
///
///   void addSuite(Suite suite) {
///     _activeTestsGroup.add(suite.tests);
///     _runSuite(suite);
///     _activeTestsGroup.remove(suite.tests);
///   }
/// }
/// ```
class UnionSetController<E> {
  /// The [UnionSet] that provides a view of the union of sets in [this].
  UnionSet<E> get set => _set;
  UnionSet<E> _set;

  /// The sets whose union is exposed through [set].
  final _sets = new Set<Set<E>>();

  /// Creates a set of sets that provides a view of the union of those sets.
  ///
  /// If [disjoint] is `true`, this assumes that all component sets are
  /// disjoint—that is, that they contain no elements in common. This makes
  /// many operations including [length] more efficient.
  UnionSetController({bool disjoint: false}) {
    _set = new UnionSet<E>(_sets, disjoint: disjoint);
  }

  /// Adds the contents of [component] to [set].
  ///
  /// If the contents of [component] change over time, [set] will change
  /// accordingly.
  void add(Set<E> component) {
    _sets.add(component);
  }

  /// Removes the contents of [component] to [set].
  ///
  /// If another set in [this] has overlapping elements with [component], those
  /// elements will remain in [set].
  bool remove(Set<E> component) => _sets.remove(component);
}
