// Copyright (c) 2017, 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.

/// Indexed entity interfaces for modeling elements derived from Kernel IR.

import '../elements/entities.dart';

abstract class _Indexed {
  int _index;
}

abstract class IndexedLibrary extends _Indexed implements LibraryEntity {
  /// Library index used for fast lookup in [KernelToElementMapBase].
  int get libraryIndex => _index;
}

abstract class IndexedClass extends _Indexed implements ClassEntity {
  /// Class index used for fast lookup in [KernelToElementMapBase].
  int get classIndex => _index;
}

abstract class IndexedMember extends _Indexed implements MemberEntity {
  /// Member index used for fast lookup in [KernelToElementMapBase].
  int get memberIndex => _index;
}

abstract class IndexedFunction extends _Indexed
    implements IndexedMember, FunctionEntity {}

abstract class IndexedConstructor
    implements IndexedFunction, ConstructorEntity {}

abstract class IndexedField implements IndexedMember, FieldEntity {}

abstract class IndexedTypeVariable extends _Indexed
    implements TypeVariableEntity {
  /// Type variable index used for fast lookup in [KernelToElementMapBase].
  int get typeVariableIndex => _index;
}

abstract class IndexedTypedef extends _Indexed implements TypedefEntity {
  /// Typedef index used for fast lookup in [KernelToElementMapBase].
  int get typedefIndex => _index;
}

/// Base implementation for an index based map of entities of type [E].
abstract class EntityMapBase<E extends _Indexed> {
  List<E> _list = <E>[];

  /// Returns the [index]th entity in the map.
  E getEntity(int index) => _list[index];

  /// Returns the number entities in the map.
  int get length => _list.length;
}

/// Index based map of entities of type [E].
class EntityMap<E extends _Indexed> extends EntityMapBase<E> {
  /// Registers a new entity.
  ///
  /// [createEntity] is called to create the entity with the given index.
  E0 register<E0 extends E>(E0 entity) {
    assert(entity != null);
    assert(entity._index == null);
    entity._index = _list.length;
    _list.add(entity);
    return entity;
  }
}

/// Base implementation of an index based map of entities of type [E] with a
/// corresponding data object of type [D].
abstract class EntityDataMapBase<E extends _Indexed, D>
    extends EntityMapBase<E> {
  List<D> _data = <D>[];

  /// Returns the data object stored for the [index]th entity.
  D getData(E entity) {
    int index = entity._index;
    if (index < length && index >= _data.length) {
      throw new StateError(
          'Data is in the process of being created for ${_list[index]}.');
    }
    return _data[index];
  }
}

/// Index based map of entities of type [E] with a corresponding data object
/// of type [D].
class EntityDataMap<E extends _Indexed, D> extends EntityDataMapBase<E, D> {
  /// Registers a new entity with an associated data object.
  ///
  /// Firstly, [createEntity] is called to create the entity with the given
  /// index. Secondly, [createData] is called with the newly created entity to
  /// create the associated data object.
  E0 register<E0 extends E, D0 extends D>(E0 entity, D0 data) {
    assert(entity != null);
    assert(entity._index == null);
    entity._index = _list.length;
    _list.add(entity);
    assert(data != null);
    _data.add(data);
    return entity;
  }
}

/// Base implementation for an index based of entities of type [E] with a
/// corresponding data object of type [D] and an environment of type [V].
abstract class EntityDataEnvMapBase<E extends _Indexed, D, V>
    extends EntityDataMapBase<E, D> {
  List<V> _env = <V>[];

  /// Returns the environment object stored for the [index]th entity.
  V getEnv(E entity) {
    int index = entity._index;
    if (index < length && index >= _env.length) {
      throw new StateError(
          'Env is in the process of being created for ${_list[index]}.');
    }
    return _env[index];
  }
}

/// Index based of entities of type [E] with a corresponding data object of
/// type [D] and an environment of type [V].
class EntityDataEnvMap<E extends _Indexed, D, V>
    extends EntityDataEnvMapBase<E, D, V> {
  /// Registers a new entity with an associated data object and environment.
  ///
  /// Firstly, [createEntity] is called to create the entity with the given
  /// index. Secondly, [createData] is called with the newly created entity to
  /// create the associated data object. Thirdly, [createEnv] is called with
  /// the newly created entity to create the associated environment object.
  E0 register<E0 extends E, D0 extends D, V0 extends V>(
      E0 entity, D0 data, V0 env) {
    assert(entity != null);
    assert(entity._index == null);
    entity._index = _list.length;
    _list.add(entity);
    assert(data != null);
    _data.add(data);
    assert(env != null);
    _env.add(env);
    return entity;
  }
}
