// 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 src.services.index;

import 'dart:collection';

import 'package:analysis_server/plugin/index/index_core.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_general.dart';

/**
 * A wrapper around an [Element] that implements the [IndexableObject] interface.
 */
class IndexableElement implements IndexableObject {
  /**
   * The element being wrapped.
   */
  final Element element;

  /**
   * Initialize a newly created wrapper to wrap the given [element].
   */
  IndexableElement(this.element) {
    if (element == null) {
      throw new ArgumentError.notNull('element');
    }
  }

  @override
  String get filePath {
    return element.source?.fullName;
  }

  @override
  int get hashCode => element.hashCode;

  @override
  IndexableElementKind get kind => IndexableElementKind.forElement(element);

  @override
  int get offset {
    if (element is ConstructorElement) {
      return element.enclosingElement.nameOffset;
    }
    return element.nameOffset;
  }

  @override
  bool operator ==(Object object) =>
      object is IndexableElement && element == object.element;

  @override
  String toString() => element.toString();
}

/**
 * The kind associated with an [IndexableElement].
 */
class IndexableElementKind implements IndexableObjectKind<IndexableElement> {
  /**
   * A table mapping element kinds to the corresponding indexable element kind.
   */
  static final Map<ElementKind, IndexableElementKind> _kindMap =
      new HashMap<ElementKind, IndexableElementKind>();

  /**
   * A table mapping the index of a constructor (in the lexically-ordered list
   * of constructors associated with a class) to the indexable element kind used
   * to represent it.
   */
  static final Map<int, IndexableElementKind> _constructorKinds =
      new HashMap<int, IndexableElementKind>();

  @override
  final int index = IndexableObjectKind.nextIndex;

  /**
   * The element kind represented by this index element kind.
   */
  final ElementKind elementKind;

  /**
   * Initialize a newly created kind to have the given [index] and be associated
   * with the given [elementKind].
   */
  IndexableElementKind._(this.elementKind) {
    IndexableObjectKind.register(this);
  }

  /**
   * Return the index of the constructor with this indexable element kind.
   */
  int get constructorIndex {
    for (int index in _constructorKinds.keys) {
      if (_constructorKinds[index] == this) {
        return index;
      }
    }
    return -1;
  }

  @override
  IndexableElement decode(
      AnalysisContext context, String filePath, int offset) {
    List<Source> unitSources = context.getSourcesWithFullName(filePath);
    for (Source unitSource in unitSources) {
      List<Source> libSources = context.getLibrariesContaining(unitSource);
      for (Source libSource in libSources) {
        CompilationUnitElement unitElement =
            context.getCompilationUnitElement(unitSource, libSource);
        if (unitElement == null) {
          return null;
        }
        if (elementKind == ElementKind.LIBRARY) {
          return new IndexableElement(unitElement.library);
        } else if (elementKind == ElementKind.COMPILATION_UNIT) {
          return new IndexableElement(unitElement);
        } else {
          Element element = unitElement.getElementAt(offset);
          if (element == null) {
            return null;
          }
          if (element is ClassElement &&
              elementKind == ElementKind.CONSTRUCTOR) {
            return new IndexableElement(element.constructors[constructorIndex]);
          }
          if (element is PropertyInducingElement) {
            if (elementKind == ElementKind.GETTER) {
              return new IndexableElement(element.getter);
            }
            if (elementKind == ElementKind.SETTER) {
              return new IndexableElement(element.setter);
            }
          }
          return new IndexableElement(element);
        }
      }
    }
    return null;
  }

  @override
  int encodeHash(StringToInt stringToInt, IndexableElement indexable) {
    Element element = indexable.element;
    String elementName = element.displayName;
    int elementNameId = stringToInt(elementName);
    LibraryElement libraryElement = element.library;
    if (libraryElement != null) {
      String libraryPath = libraryElement.source.fullName;
      int libraryPathId = stringToInt(libraryPath);
      return JenkinsSmiHash.combine(libraryPathId, elementNameId);
    }
    return elementNameId;
  }

  /**
   * Return the indexable element kind representing the given [element].
   */
  static IndexableElementKind forElement(Element element) {
    if (element is ConstructorElement) {
      ClassElement classElement = element.enclosingElement;
      int constructorIndex = classElement.constructors.indexOf(element);
      return _constructorKinds.putIfAbsent(constructorIndex,
          () => new IndexableElementKind._(ElementKind.CONSTRUCTOR));
    }
    ElementKind elementKind = element.kind;
    return _kindMap.putIfAbsent(
        elementKind, () => new IndexableElementKind._(elementKind));
  }
}
