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

library dart2js.util.enumset;

import 'dart:collection';

/// A set of enum values based on a bit mask of the shifted enum indices.
abstract class EnumSet<E> {
  /// Creates an empty mutable set.
  factory EnumSet() = _EnumSet<E>;

  /// Creates a mutable set from the bit mask [value].
  factory EnumSet.fromValue(int value) = _EnumSet<E>.fromValue;

  /// Creates an immutable set from the bit mask [value].
  const factory EnumSet.fixed(int value) = _ConstEnumSet<E>;

  /// Create a set containing the [values]. If [fixed] is `true` the set is
  /// immutable.
  factory EnumSet.fromValues(Iterable<E> values, {bool fixed: false}) {
    if (fixed) {
      return new _ConstEnumSet<E>.fromValues(values);
    } else {
      return new _EnumSet<E>.fromValues(values);
    }
  }

  const EnumSet._();

  /// The bit mask of the shifted indices for the enum values in this set.
  int get value;

  /// Adds [enumValue] to this set.
  void add(E enumValue);

  /// Removes [enumValue] from this set.
  void remove(E enumValue);

  /// Clears this set.
  void clear();

  /// Returns `true` if [enumValue] is in this set.
  bool contains(E enumValue) {
    return (value & (1 << (enumValue as dynamic).index)) != 0;
  }

  /// Returns an [Iterable] of the values is in this set using [values] to
  /// convert the stored indices to enum values.
  ///
  /// The method is typically called with the `values` property of the enum
  /// class as argument:
  ///
  ///     EnumSet<EnumClass> set = ...
  ///     Iterable<EnumClass> iterable = set.iterable(EnumClass.values);
  ///
  Iterable<E> iterable(List<E> values) {
    return new _EnumSetIterable(this, values);
  }

  /// Returns `true` if this and [other] have any elements in common.
  bool intersects(EnumSet<E> other) {
    return (value & other.value) != 0;
  }

  /// Returns `true` if this set is empty.
  bool get isEmpty => value == 0;

  int get hashCode => value.hashCode * 19;

  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! EnumSet<E>) return false;
    return value == other.value;
  }

  String toString() {
    if (value == 0) return '0';
    int index = value.bitLength - 1;
    StringBuffer sb = new StringBuffer();
    int mask = 1 << index;
    while (index >= 0) {
      sb.write((value & mask) != 0 ? '1' : '0');
      index--;
      mask >>= 1;
    }
    return sb.toString();
  }
}

/// Mutable implementation of [EnumSet].
class _EnumSet<E> extends EnumSet<E> {
  int _value;

  _EnumSet() : this.fromValue(0);

  _EnumSet.fromValue(this._value) : super._();

  _EnumSet.fromValues(Iterable<E> values)
      : this._value = 0,
        super._() {
    values.forEach(add);
  }

  int get value => _value;

  void add(E enumValue) {
    _value |= 1 << (enumValue as dynamic).index;
  }

  void remove(E enumValue) {
    _value &= ~(1 << (enumValue as dynamic).index);
  }

  void clear() {
    _value = 0;
  }
}

/// Immutable implementation of [EnumSet].
class _ConstEnumSet<E> extends EnumSet<E> {
  final int value;

  const _ConstEnumSet(this.value) : super._();

  factory _ConstEnumSet.fromValues(Iterable<E> values) {
    int value = 0;
    void add(E enumValue) {
      if (enumValue != null) {
        value |= 1 << (enumValue as dynamic).index;
      }
    }

    values.forEach(add);
    return new _ConstEnumSet(value);
  }

  @override
  void add(E enumValue) {
    throw new UnsupportedError('EnumSet.add');
  }

  @override
  void clear() {
    throw new UnsupportedError('EnumSet.clear');
  }

  @override
  void remove(E enumValue) {
    throw new UnsupportedError('EnumSet.remove');
  }
}

class _EnumSetIterable<E> extends IterableBase<E> {
  final EnumSet<E> _enumSet;
  final List<E> _values;

  _EnumSetIterable(this._enumSet, this._values);

  @override
  Iterator<E> get iterator => new _EnumSetIterator(_enumSet.value, _values);
}

class _EnumSetIterator<E> implements Iterator<E> {
  int _value;
  int _index;
  int _mask;
  final List<E> _values;
  E _current;

  _EnumSetIterator(this._value, this._values);

  @override
  E get current => _current;

  @override
  bool moveNext() {
    if (_value == 0) {
      return false;
    } else {
      if (_mask == null) {
        _index = _value.bitLength - 1;
        _mask = 1 << _index;
      }
      _current = null;
      while (_index >= 0) {
        if (_mask & _value != 0) {
          _current = _values[_index];
        }
        _mask >>= 1;
        _index--;
        if (_current != null) {
          break;
        }
      }
      return _current != null;
    }
  }
}
