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

/**
 * Utilities for converting Dart entities into analysis server's protocol
 * entities.
 */
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analyzer/dart/element/element.dart' as engine;
import 'package:analyzer/src/generated/utilities_dart.dart' as engine;
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:path/path.dart' as pathos;

/**
 * Return a protocol [Element] corresponding to the given [engine.Element].
 */
Element convertElement(engine.Element element) {
  String name = getElementDisplayName(element);
  String elementTypeParameters = _getTypeParametersString(element);
  String elementParameters = _getParametersString(element);
  String elementReturnType = getReturnTypeString(element);
  ElementKind kind = convertElementToElementKind(element);
  return new Element(
      kind,
      name,
      Element.makeFlags(
          isPrivate: element.isPrivate,
          isDeprecated: element.hasDeprecated,
          isAbstract: _isAbstract(element),
          isConst: _isConst(element),
          isFinal: _isFinal(element),
          isStatic: _isStatic(element)),
      location: newLocation_fromElement(element),
      typeParameters: elementTypeParameters,
      parameters: elementParameters,
      returnType: elementReturnType);
}

/**
 * Return a protocol [ElementKind] corresponding to the given
 * [engine.ElementKind].
 *
 * This does not take into account that an instance of [ClassElement] can be an
 * enum and an instance of [FieldElement] can be an enum constant.
 * Use [convertElementToElementKind] where possible.
 */
ElementKind convertElementKind(engine.ElementKind kind) {
  if (kind == engine.ElementKind.CLASS) {
    return ElementKind.CLASS;
  }
  if (kind == engine.ElementKind.COMPILATION_UNIT) {
    return ElementKind.COMPILATION_UNIT;
  }
  if (kind == engine.ElementKind.CONSTRUCTOR) {
    return ElementKind.CONSTRUCTOR;
  }
  if (kind == engine.ElementKind.FIELD) {
    return ElementKind.FIELD;
  }
  if (kind == engine.ElementKind.FUNCTION) {
    return ElementKind.FUNCTION;
  }
  if (kind == engine.ElementKind.FUNCTION_TYPE_ALIAS) {
    return ElementKind.FUNCTION_TYPE_ALIAS;
  }
  if (kind == engine.ElementKind.GETTER) {
    return ElementKind.GETTER;
  }
  if (kind == engine.ElementKind.LABEL) {
    return ElementKind.LABEL;
  }
  if (kind == engine.ElementKind.LIBRARY) {
    return ElementKind.LIBRARY;
  }
  if (kind == engine.ElementKind.LOCAL_VARIABLE) {
    return ElementKind.LOCAL_VARIABLE;
  }
  if (kind == engine.ElementKind.METHOD) {
    return ElementKind.METHOD;
  }
  if (kind == engine.ElementKind.PARAMETER) {
    return ElementKind.PARAMETER;
  }
  if (kind == engine.ElementKind.PREFIX) {
    return ElementKind.PREFIX;
  }
  if (kind == engine.ElementKind.SETTER) {
    return ElementKind.SETTER;
  }
  if (kind == engine.ElementKind.TOP_LEVEL_VARIABLE) {
    return ElementKind.TOP_LEVEL_VARIABLE;
  }
  if (kind == engine.ElementKind.TYPE_PARAMETER) {
    return ElementKind.TYPE_PARAMETER;
  }
  return ElementKind.UNKNOWN;
}

/**
 * Return an [ElementKind] corresponding to the given [engine.Element].
 */
ElementKind convertElementToElementKind(engine.Element element) {
  if (element is engine.ClassElement) {
    if (element.isEnum) {
      return ElementKind.ENUM;
    }
    if (element.isMixin) {
      return ElementKind.MIXIN;
    }
  }
  if (element is engine.FieldElement &&
      element.isEnumConstant &&
      // MyEnum.values and MyEnum.one.index return isEnumConstant = true
      // so these additional checks are necessary.
      // TODO(danrubel) MyEnum.values is constant, but is a list
      // so should it return isEnumConstant = true?
      // MyEnum.one.index is final but *not* constant
      // so should it return isEnumConstant = true?
      // Or should we return ElementKind.ENUM_CONSTANT here
      // in either or both of these cases?
      element.type != null &&
      element.type.element == element.enclosingElement) {
    return ElementKind.ENUM_CONSTANT;
  }
  return convertElementKind(element.kind);
}

String getElementDisplayName(engine.Element element) {
  if (element is engine.CompilationUnitElement) {
    return pathos.basename(element.source.fullName);
  } else {
    return element.displayName;
  }
}

String _getParametersString(engine.Element element) {
  // TODO(scheglov) expose the corresponding feature from ExecutableElement
  List<engine.ParameterElement> parameters;
  if (element is engine.ExecutableElement) {
    // valid getters don't have parameters
    if (element.kind == engine.ElementKind.GETTER &&
        element.parameters.isEmpty) {
      return null;
    }
    parameters = element.parameters.toList();
  } else if (element is engine.FunctionTypeAliasElement) {
    parameters = element.parameters.toList();
  } else {
    return null;
  }

  parameters.sort(_preferRequiredParams);

  StringBuffer sb = new StringBuffer();
  String closeOptionalString = '';
  for (engine.ParameterElement parameter in parameters) {
    if (sb.isNotEmpty) {
      sb.write(', ');
    }
    if (closeOptionalString.isEmpty) {
      if (parameter.isNamed) {
        sb.write('{');
        closeOptionalString = '}';
      } else if (parameter.isOptionalPositional) {
        sb.write('[');
        closeOptionalString = ']';
      }
    }
    if (parameter.hasRequired) {
      sb.write('@required ');
    }
    parameter.appendToWithoutDelimiters(sb);
  }
  sb.write(closeOptionalString);
  return '(' + sb.toString() + ')';
}

String _getTypeParametersString(engine.Element element) {
  List<engine.TypeParameterElement> typeParameters;
  if (element is engine.ClassElement) {
    typeParameters = element.typeParameters;
  } else if (element is engine.FunctionTypeAliasElement) {
    typeParameters = element.typeParameters;
  }
  if (typeParameters == null || typeParameters.isEmpty) {
    return null;
  }
  return '<${typeParameters.join(', ')}>';
}

bool _isAbstract(engine.Element element) {
  // TODO(scheglov) add isAbstract to Element API
  if (element is engine.ClassElement) {
    return element.isAbstract;
  }
  if (element is engine.MethodElement) {
    return element.isAbstract;
  }
  if (element is engine.PropertyAccessorElement) {
    return element.isAbstract;
  }
  return false;
}

bool _isConst(engine.Element element) {
  // TODO(scheglov) add isConst to Element API
  if (element is engine.ConstructorElement) {
    return element.isConst;
  }
  if (element is engine.VariableElement) {
    return element.isConst;
  }
  return false;
}

bool _isFinal(engine.Element element) {
  // TODO(scheglov) add isFinal to Element API
  if (element is engine.VariableElement) {
    return element.isFinal;
  }
  return false;
}

bool _isStatic(engine.Element element) {
  // TODO(scheglov) add isStatic to Element API
  if (element is engine.ExecutableElement) {
    return element.isStatic;
  }
  if (element is engine.PropertyInducingElement) {
    return element.isStatic;
  }
  return false;
}

// Sort @required named parameters before optional ones.
int _preferRequiredParams(
    engine.ParameterElement e1, engine.ParameterElement e2) {
  int rank1 = e1.hasRequired ? 0 : !e1.isNamed ? -1 : 1;
  int rank2 = e2.hasRequired ? 0 : !e2.isNamed ? -1 : 1;
  return rank1 - rank2;
}
