// Copyright (c) 2015, 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 analyzer.src.task.inputs;

import 'dart:collection';

import 'package:analyzer/task/model.dart';

/**
 * A function that converts an object of the type [B] into a [TaskInput].
 * This is used, for example, by a [ListToListTaskInput] to create task inputs
 * for each value in a list of values.
 */
typedef TaskInput<E> GenerateTaskInputs<B, E>(B object);

/**
 * A function that maps one [value] to another value.
 */
typedef R Mapper<P, R>(P value);

/**
 * An input to an [AnalysisTask] that is computed by accessing a single result
 * defined on a single target.
 */
class ConstantTaskInput<V> extends TaskInputImpl<V> {
  final V value;

  ConstantTaskInput(this.value);

  @override
  TaskInputBuilder<V> createBuilder() {
    return new ConstantTaskInputBuilder<V>(this);
  }
}

/**
 * A [TaskInputBuilder] used to build an input based on a [ConstantTaskInput].
 */
class ConstantTaskInputBuilder<V> implements TaskInputBuilder<V> {
  final ConstantTaskInput input;

  ConstantTaskInputBuilder(this.input);

  @override
  ResultDescriptor get currentResult => null;

  @override
  AnalysisTarget get currentTarget => null;

  @override
  void set currentValue(Object value) {
    throw new StateError('Only supported after moveNext() returns true');
  }

  @override
  bool get flushOnAccess => false;

  @override
  V get inputValue => input.value;

  @override
  void currentValueNotAvailable() {
    throw new StateError('Only supported after moveNext() returns true');
  }

  @override
  bool moveNext() => false;
}

/**
 * An input to an [AnalysisTask] that is computed by accessing a single result
 * defined on a single target.
 */
class ListTaskInputImpl<E> extends SimpleTaskInput<List<E>>
    with ListTaskInputMixin<E>
    implements ListTaskInput<E> {
  /**
   * Initialize a newly created task input that computes the input by accessing
   * the given [result] associated with the given [target].
   */
  ListTaskInputImpl(AnalysisTarget target, ResultDescriptor<List<E>> result)
      : super._unflushable(target, result);
}

/**
 * A mixin-ready implementation of [ListTaskInput].
 */
abstract class ListTaskInputMixin<E> implements ListTaskInput<E> {
  ListTaskInput /*<V>*/ toList(UnaryFunction<E, dynamic /*<V>*/ > mapper) {
    return new ListToListTaskInput<E, dynamic /*V*/ >(this, mapper);
  }

  ListTaskInput /*<V>*/ toListOf(ResultDescriptor /*<V>*/ valueResult) {
    return (this as ListTaskInputImpl<AnalysisTarget>).toList(valueResult.of);
  }

  MapTaskInput<E, dynamic /*V*/ > toMap(
      UnaryFunction<E, dynamic /*<V>*/ > mapper) {
    return new ListToMapTaskInput<E, dynamic /*V*/ >(this, mapper);
  }

  MapTaskInput<AnalysisTarget, dynamic /*V*/ > toMapOf(
      ResultDescriptor /*<V>*/ valueResult) {
    return (this as ListTaskInputImpl<AnalysisTarget>).toMap(valueResult.of);
  }
}

/**
 * An input to an [AnalysisTask] that is computed by the following steps. First
 * another (base) task input is used to compute a [List]-valued result. An input
 * generator function is then used to map each element of that list to a task
 * input. Finally, each of the task inputs are used to access analysis results,
 * and the list of the analysis results is used as the input to the task.
 */
class ListToListTaskInput<B, E>
    extends _ListToCollectionTaskInput<B, E, List<E>>
    with ListTaskInputMixin<E> {
  /**
   * Initialize a result accessor to use the given [baseAccessor] to access a
   * list of values that can be passed to the given [generateTaskInputs] to
   * generate a list of task inputs that can be used to access the elements of
   * the input being accessed.
   */
  ListToListTaskInput(TaskInput<List<B>> baseAccessor,
      GenerateTaskInputs<B, E> generateTaskInputs)
      : super(baseAccessor, generateTaskInputs);

  @override
  TaskInputBuilder<List<E>> createBuilder() =>
      new ListToListTaskInputBuilder<B, E>(this);
}

/**
 * A [TaskInputBuilder] used to build an input based on a [ListToListTaskInput].
 */
class ListToListTaskInputBuilder<B, E>
    extends _ListToCollectionTaskInputBuilder<B, E, List<E>> {
  /**
   * The list of values being built.
   */
  List<E> _resultValue;

  /**
   * Initialize a newly created task input builder that computes the result
   * specified by the given [input].
   */
  ListToListTaskInputBuilder(ListToListTaskInput<B, E> input) : super(input);

  @override
  void _addResultElement(B baseElement, E resultElement) {
    _resultValue.add(resultElement);
  }

  @override
  void _initResultValue() {
    _resultValue = <E>[];
  }
}

/**
 * An input to an [AnalysisTask] that is computed by the following steps. First
 * another (base) task input is used to compute a [List]-valued result. An input
 * generator function is then used to map each element of that list to a task
 * input. Finally, each of the task inputs are used to access analysis results,
 * and the map of the base elements to the analysis results is used as the
 * input to the task.
 */
class ListToMapTaskInput<B, E>
    extends _ListToCollectionTaskInput<B, E, Map<B, E>>
    with MapTaskInputMixin<B, E> {
  /**
   * Initialize a result accessor to use the given [baseAccessor] to access a
   * list of values that can be passed to the given [generateTaskInputs] to
   * generate a list of task inputs that can be used to access the elements of
   * the input being accessed.
   */
  ListToMapTaskInput(TaskInput<List<B>> baseAccessor,
      GenerateTaskInputs<B, E> generateTaskInputs)
      : super(baseAccessor, generateTaskInputs);

  @override
  TaskInputBuilder<Map<B, E>> createBuilder() =>
      new ListToMapTaskInputBuilder<B, E>(this);
}

/**
 * A [TaskInputBuilder] used to build an input based on a [ListToMapTaskInput].
 */
class ListToMapTaskInputBuilder<B, E>
    extends _ListToCollectionTaskInputBuilder<B, E, Map<B, E>> {
  /**
   * The map being built.
   */
  Map<B, E> _resultValue;

  /**
   * Initialize a newly created task input builder that computes the result
   * specified by the given [input].
   */
  ListToMapTaskInputBuilder(ListToMapTaskInput<B, E> input) : super(input);

  @override
  void _addResultElement(B baseElement, E resultElement) {
    _resultValue[baseElement] = resultElement;
  }

  @override
  void _initResultValue() {
    _resultValue = new HashMap<B, E>();
  }
}

/**
 * A mixin-ready implementation of [MapTaskInput].
 */
abstract class MapTaskInputMixin<K, V> implements MapTaskInput<K, V> {
  TaskInput<List /*<E>*/ > toFlattenList(
      BinaryFunction<K, dynamic /*element of V*/, dynamic /*<E>*/ > mapper) {
    return new MapToFlattenListTaskInput<K, dynamic /*element of V*/,
        dynamic /*E*/ >(
        this as MapTaskInput<K, List /*<element of V>*/ >, mapper);
  }
}

/**
 * A [TaskInput] that is computed by the following steps.
 *
 * First the [base] task input is used to compute a [Map]-valued result.
 * The values of the [Map] must be [List]s.
 *
 * The given [mapper] is used to transform each key / value pair of the [Map]
 * into task inputs.
 *
 * Finally, each of the task inputs are used to access analysis results,
 * and the list of the results is used as the input.
 */
class MapToFlattenListTaskInput<K, V, E> extends TaskInputImpl<List<E>> {
  final MapTaskInput<K, List<V>> base;
  final BinaryFunction<K, V, E> mapper;

  MapToFlattenListTaskInput(this.base, this.mapper);

  @override
  TaskInputBuilder<List<E>> createBuilder() {
    return new MapToFlattenListTaskInputBuilder<K, V, E>(base, mapper);
  }
}

/**
 * The [TaskInputBuilder] for [MapToFlattenListTaskInput].
 */
class MapToFlattenListTaskInputBuilder<K, V, E>
    implements TaskInputBuilder<List<E>> {
  final MapTaskInput<K, List<V>> base;
  final BinaryFunction<K, V, E> mapper;

  TaskInputBuilder currentBuilder;
  Map<K, List<V>> baseMap;
  Iterator<K> keyIterator;
  Iterator<V> valueIterator;

  final List<E> inputValue = <E>[];

  MapToFlattenListTaskInputBuilder(this.base, this.mapper) {
    currentBuilder = base.createBuilder();
  }

  @override
  ResultDescriptor get currentResult {
    if (currentBuilder == null) {
      return null;
    }
    return currentBuilder.currentResult;
  }

  AnalysisTarget get currentTarget {
    if (currentBuilder == null) {
      return null;
    }
    return currentBuilder.currentTarget;
  }

  @override
  void set currentValue(Object value) {
    if (currentBuilder == null) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    currentBuilder.currentValue = value;
  }

  @override
  bool get flushOnAccess => currentBuilder.flushOnAccess;

  @override
  void currentValueNotAvailable() {
    if (currentBuilder == null) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    currentBuilder.currentValueNotAvailable();
  }

  @override
  bool moveNext() {
    // Prepare base Map.
    if (baseMap == null) {
      if (currentBuilder.moveNext()) {
        return true;
      }
      baseMap = currentBuilder.inputValue;
      if (baseMap == null) {
        // No base map could be computed due to a circular dependency.  Use an
        // empty map so that no further results will be computed.
        baseMap = {};
      }
      keyIterator = baseMap.keys.iterator;
      // Done with this builder.
      currentBuilder = null;
    }
    // Prepare the next result value.
    if (currentBuilder != null) {
      if (currentBuilder.moveNext()) {
        return true;
      }
      // Add the result value for the current Map key/value.
      E resultValue = currentBuilder.inputValue;
      if (resultValue != null) {
        inputValue.add(resultValue);
      }
      // Done with this builder.
      currentBuilder = null;
    }
    // Move to the next Map value.
    if (valueIterator != null && valueIterator.moveNext()) {
      K key = keyIterator.current;
      V value = valueIterator.current;
      currentBuilder = mapper(key, value).createBuilder();
      return moveNext();
    }
    // Move to the next Map key.
    if (keyIterator.moveNext()) {
      K key = keyIterator.current;
      valueIterator = baseMap[key].iterator;
      return moveNext();
    }
    // No more Map values/keys to transform.
    return false;
  }
}

/**
 * An input to an [AnalysisTask] that is computed by mapping the value of
 * another task input to a list of values.
 */
class ObjectToListTaskInput<E> extends TaskInputImpl<List<E>>
    with ListTaskInputMixin<E>
    implements ListTaskInput<E> {
  /**
   * The input used to compute the value to be mapped.
   */
  final TaskInput baseInput;

  /**
   * The function used to map the value of the base input to the list of values.
   */
  final Mapper<Object, List<E>> mapper;

  /**
   * Initialize a newly created task input that computes the input by accessing
   * the given [result] associated with the given [target].
   */
  ObjectToListTaskInput(this.baseInput, this.mapper);

  @override
  TaskInputBuilder<List<E>> createBuilder() =>
      new ObjectToListTaskInputBuilder<E>(this);

  @override
  ListTaskInput /*<V>*/ toListOf(ResultDescriptor /*<V>*/ valueResult) {
    return new ListToListTaskInput<E, dynamic /*V*/ >(
        this, valueResult.of as dynamic);
  }

  @override
  MapTaskInput<AnalysisTarget, dynamic /*V*/ > toMapOf(
      ResultDescriptor /*<V>*/ valueResult) {
    return new ListToMapTaskInput<AnalysisTarget, dynamic /*V*/ >(
        this as dynamic, valueResult.of);
  }
}

/**
 * A [TaskInputBuilder] used to build an input based on a [SimpleTaskInput].
 */
class ObjectToListTaskInputBuilder<E> implements TaskInputBuilder<List<E>> {
  /**
   * The input being built.
   */
  final ObjectToListTaskInput<E> input;

  /**
   * The builder created by the input.
   */
  TaskInputBuilder builder;

  /**
   * The value of the input being built, or `null` if the value hasn't been set
   * yet or if no result is available ([currentValueNotAvailable] was called).
   */
  List<E> _inputValue = null;

  /**
   * Initialize a newly created task input builder that computes the result
   * specified by the given [input].
   */
  ObjectToListTaskInputBuilder(this.input) {
    builder = input.baseInput.createBuilder();
  }

  @override
  ResultDescriptor get currentResult {
    if (builder == null) {
      return null;
    }
    return builder.currentResult;
  }

  @override
  AnalysisTarget get currentTarget {
    if (builder == null) {
      return null;
    }
    return builder.currentTarget;
  }

  @override
  void set currentValue(Object value) {
    if (builder == null) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    builder.currentValue = value;
  }

  @override
  bool get flushOnAccess => builder.flushOnAccess;

  @override
  List<E> get inputValue {
    if (builder != null) {
      throw new StateError('Result value has not been created');
    }
    return _inputValue;
  }

  @override
  void currentValueNotAvailable() {
    if (builder == null) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    builder.currentValueNotAvailable();
  }

  @override
  bool moveNext() {
    if (builder == null) {
      return false;
    } else if (builder.moveNext()) {
      return true;
    } else {
      // This might not be the right semantics. If the value could not be
      // computed then we pass the resulting `null` in to the mapper function.
      // Unfortunately, we cannot tell the difference between a `null` that's
      // there because no value could be computed and a `null` that's there
      // because that's what *was* computed.
      _inputValue = input.mapper(builder.inputValue);
      builder = null;
      return false;
    }
  }
}

/**
 * An input to an [AnalysisTask] that is computed by accessing a single result
 * defined on a single target.
 */
class SimpleTaskInput<V> extends TaskInputImpl<V> {
  /**
   * The target on which the result is defined.
   */
  final AnalysisTarget target;

  /**
   * The result to be accessed.
   */
  final ResultDescriptor<V> result;

  /**
   * Return `true` if the value accessed by this input builder should be flushed
   * from the cache at the time it is retrieved.
   */
  final bool flushOnAccess;

  /**
   * Initialize a newly created task input that computes the input by accessing
   * the given [result] associated with the given [target].
   */
  SimpleTaskInput(this.target, this.result, {this.flushOnAccess: false});

  /**
   * Initialize a newly created task input that computes the input by accessing
   * the given [result] associated with the given [target].
   */
  SimpleTaskInput._unflushable(this.target, this.result)
      : flushOnAccess = false;

  @override
  TaskInputBuilder<V> createBuilder() => new SimpleTaskInputBuilder<V>(this);
}

/**
 * A [TaskInputBuilder] used to build an input based on a [SimpleTaskInput].
 */
class SimpleTaskInputBuilder<V> implements TaskInputBuilder<V> {
  /**
   * The state value indicating that the builder is positioned before the single
   * result.
   */
  static const _BEFORE = -1;

  /**
   * The state value indicating that the builder is positioned at the single
   * result.
   */
  static const _AT = 0;

  /**
   * The state value indicating that the builder is positioned after the single
   * result.
   */
  static const _AFTER = 1;

  /**
   * The input being built.
   */
  final SimpleTaskInput<V> input;

  /**
   * The value of the input being built.  `null` if the value hasn't been set
   * yet, or if no result is available ([currentValueNotAvailable] was called).
   */
  V _resultValue = null;

  /**
   * The state of the builder.
   */
  int _state = _BEFORE;

  /**
   * A flag indicating whether the result value was explicitly set.
   */
  bool _resultSet = false;

  /**
   * Initialize a newly created task input builder that computes the result
   * specified by the given [input].
   */
  SimpleTaskInputBuilder(this.input);

  @override
  ResultDescriptor get currentResult => _state == _AT ? input.result : null;

  @override
  AnalysisTarget get currentTarget => _state == _AT ? input.target : null;

  @override
  void set currentValue(Object value) {
    if (_state != _AT) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    _resultValue = value as V;
    _resultSet = true;
  }

  @override
  bool get flushOnAccess => input.flushOnAccess;

  @override
  V get inputValue {
    if (_state != _AFTER) {
      throw new StateError('Result value has not been created');
    }
    return _resultValue;
  }

  @override
  void currentValueNotAvailable() {
    if (_state != _AT) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    _resultValue = null;
    _resultSet = true;
  }

  @override
  bool moveNext() {
    if (_state == _BEFORE) {
      _state = _AT;
      return true;
    } else {
      if (!_resultSet) {
        throw new StateError(
            'The value of the current result must be set before moving to the next result.');
      }
      _state = _AFTER;
      return false;
    }
  }
}

abstract class TaskInputImpl<V> implements TaskInput<V> {
  @override
  ListTaskInput /*<E>*/ mappedToList(List /*<E>*/ mapper(V value)) {
    return new ObjectToListTaskInput(this, mapper);
  }
}

/**
 * A [TaskInputBuilder] used to build an input based on one or more other task
 * inputs. The task inputs to be built are specified by a table mapping the name
 * of the input to the task used to access the input's value.
 */
class TopLevelTaskInputBuilder
    implements TaskInputBuilder<Map<String, Object>> {
  /**
   * The descriptors describing the inputs to be built.
   */
  final Map<String, TaskInput> inputDescriptors;

  /**
   * The names of the inputs. There are the keys from the [inputDescriptors] in
   * an indexable form.
   */
  List<String> inputNames;

  /**
   * The index of the input name associated with the current result and target.
   */
  int nameIndex = -1;

  /**
   * The builder used to build the current result.
   */
  TaskInputBuilder currentBuilder;

  /**
   * The inputs that are being or have been built. The map will be incomplete
   * unless the method [moveNext] returns `false`.
   */
  final Map<String, Object> inputs = new HashMap<String, Object>();

  /**
   * Initialize a newly created task input builder to build the inputs described
   * by the given [inputDescriptors].
   */
  TopLevelTaskInputBuilder(this.inputDescriptors) {
    inputNames = inputDescriptors.keys.toList();
  }

  @override
  ResultDescriptor get currentResult {
    if (currentBuilder == null) {
      return null;
    }
    return currentBuilder.currentResult;
  }

  @override
  AnalysisTarget get currentTarget {
    if (currentBuilder == null) {
      return null;
    }
    return currentBuilder.currentTarget;
  }

  @override
  void set currentValue(Object value) {
    if (currentBuilder == null) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    currentBuilder.currentValue = value;
  }

  @override
  bool get flushOnAccess => currentBuilder.flushOnAccess;

  @override
  Map<String, Object> get inputValue {
    if (nameIndex < inputNames.length) {
      throw new StateError('Result value has not been created');
    }
    return inputs;
  }

  /**
   * Assuming that there is a current input, return its name.
   */
  String get _currentName => inputNames[nameIndex];

  @override
  void currentValueNotAvailable() {
    if (currentBuilder == null) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    currentBuilder.currentValueNotAvailable();
  }

  @override
  bool moveNext() {
    if (nameIndex >= inputNames.length) {
      // We have already computed all of the results, so just return false.
      return false;
    }
    if (nameIndex < 0) {
      // This is the first time moveNext has been invoked, so we just determine
      // whether there are any results to be computed.
      nameIndex = 0;
    } else {
      if (currentBuilder.moveNext()) {
        // We are still working on building the value associated with the
        // current name.
        return true;
      }
      if (currentBuilder.inputValue != null) {
        inputs[_currentName] = currentBuilder.inputValue;
      }
      nameIndex++;
    }
    if (nameIndex >= inputNames.length) {
      // There is no next value, so we're done.
      return false;
    }
    currentBuilder = inputDescriptors[_currentName].createBuilder();
    while (!currentBuilder.moveNext()) {
      if (currentBuilder.inputValue != null) {
        inputs[_currentName] = currentBuilder.inputValue;
      }
      nameIndex++;
      if (nameIndex >= inputNames.length) {
        // There is no next value, so we're done.
        return false;
      }
      currentBuilder = inputDescriptors[_currentName].createBuilder();
    }
    return true;
  }
}

/**
 * An input to an [AnalysisTask] that is computed by the following steps. First
 * another (base) task input is used to compute a [List]-valued result. An input
 * generator function is then used to map each element of that list to a task
 * input. Finally, each of the task inputs are used to access analysis results,
 * and a collection of the analysis results is used as the input to the task.
 */
abstract class _ListToCollectionTaskInput<B, E, C> extends TaskInputImpl<C> {
  /**
   * The accessor used to access the list of elements being mapped.
   */
  final TaskInput<List<B>> baseAccessor;

  /**
   * The function used to convert an element in the list returned by the
   * [baseAccessor] to a task input.
   */
  final GenerateTaskInputs<B, E> generateTaskInputs;

  /**
   * Initialize a result accessor to use the given [baseAccessor] to access a
   * list of values that can be passed to the given [generateTaskInputs] to
   * generate a list of task inputs that can be used to access the elements of
   * the input being accessed.
   */
  _ListToCollectionTaskInput(this.baseAccessor, this.generateTaskInputs);
}

/**
 * A [TaskInputBuilder] used to build an [_ListToCollectionTaskInput].
 */
abstract class _ListToCollectionTaskInputBuilder<B, E, C>
    implements TaskInputBuilder<C> {
  /**
   * The input being built.
   */
  final _ListToCollectionTaskInput<B, E, C> input;

  /**
   * The builder used to build the current result.
   */
  TaskInputBuilder currentBuilder;

  /**
   * The list of values computed by the [input]'s base accessor.
   */
  List<B> _baseList = null;

  /**
   * The index in the [_baseList] of the value for which a value is currently
   * being built.
   */
  int _baseListIndex = -1;

  /**
   * The element of the [_baseList] for which a value is currently being built.
   */
  B _baseListElement;

  /**
   * Initialize a newly created task input builder that computes the result
   * specified by the given [input].
   */
  _ListToCollectionTaskInputBuilder(this.input);

  @override
  ResultDescriptor get currentResult {
    if (currentBuilder == null) {
      return null;
    }
    return currentBuilder.currentResult;
  }

  @override
  AnalysisTarget get currentTarget {
    if (currentBuilder == null) {
      return null;
    }
    return currentBuilder.currentTarget;
  }

  @override
  void set currentValue(Object value) {
    if (currentBuilder == null) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    currentBuilder.currentValue = value;
  }

  @override
  bool get flushOnAccess => currentBuilder.flushOnAccess;

  @override
  C get inputValue {
    if (currentBuilder != null || _resultValue == null) {
      throw new StateError('Result value has not been created');
    }
    return _resultValue;
  }

  /**
   * The list of values being built.
   */
  C get _resultValue;

  @override
  void currentValueNotAvailable() {
    if (currentBuilder == null) {
      throw new StateError(
          'Cannot set the result value when there is no current result');
    }
    currentBuilder.currentValueNotAvailable();
  }

  @override
  bool moveNext() {
    if (currentBuilder == null) {
      if (_resultValue == null) {
        // This is the first time moveNext has been invoked, so start by
        // computing the list of values from which the results will be derived.
        currentBuilder = input.baseAccessor.createBuilder();
        return currentBuilder.moveNext();
      } else {
        // We have already computed all of the results, so just return false.
        return false;
      }
    }
    if (currentBuilder.moveNext()) {
      return true;
    }
    if (_resultValue == null) {
      // We have finished computing the list of values from which the results
      // will be derived.
      _baseList = currentBuilder.inputValue;
      if (_baseList == null) {
        // No base list could be computed due to a circular dependency.  Use an
        // empty list so that no further results will be computed.
        _baseList = [];
      }
      _baseListIndex = 0;
      _initResultValue();
    } else {
      // We have finished computing one of the elements in the result list.
      if (currentBuilder.inputValue != null) {
        _addResultElement(_baseListElement, currentBuilder.inputValue);
      }
      _baseListIndex++;
    }
    if (_baseListIndex >= _baseList.length) {
      currentBuilder = null;
      return false;
    }
    _baseListElement = _baseList[_baseListIndex];
    currentBuilder = input.generateTaskInputs(_baseListElement).createBuilder();
    return currentBuilder.moveNext();
  }

  void _addResultElement(B baseElement, E resultElement);
  void _initResultValue();
}
