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

/// Convertion of elements between the analyzer element model and the dart2js
/// element model.

library analyzer2dart.element_converter;

import 'package:compiler/src/elements/elements.dart' as dart2js;
import 'package:compiler/src/elements/modelx.dart' as modelx;
import 'package:compiler/src/util/util.dart' as util;
import 'package:compiler/src/dart_types.dart' as dart2js;
import 'package:analyzer/src/generated/element.dart' as analyzer;

part 'modely.dart';

class ElementConverter {
  /// Map from analyzer elements to their equivalent dart2js elements.
  Map<analyzer.Element, dart2js.Element> conversionMap =
      <analyzer.Element, dart2js.Element>{};

  /// Map from dart2js elements to their equivalent analyzer elements.
  Map<dart2js.Element, analyzer.Element> inversionMap =
      <dart2js.Element, analyzer.Element>{};

  ElementConverterVisitor visitor;

  ElementConverter() {
    visitor = new ElementConverterVisitor(this);
  }

  dart2js.Element convertElement(analyzer.Element input) {
    return conversionMap.putIfAbsent(input, () {
      dart2js.Element output = convertElementInternal(input);
      inversionMap[output] = input;
      return output;
    });
  }

  dart2js.FunctionType convertFunctionType(analyzer.FunctionType input) {
    dart2js.DartType returnType = convertType(input.returnType);
    List<dart2js.DartType> requiredParameterTypes =
        input.normalParameterTypes.map(convertType).toList();
    List<dart2js.DartType> positionalParameterTypes =
            input.optionalParameterTypes.map(convertType).toList();
    List<String> namedParameters =
        input.namedParameterTypes.keys.toList()..sort();
    List<dart2js.DartType> namedParameterTypes =
        namedParameters.map((String name) {
      return convertType(input.namedParameterTypes[name]);
    }).toList();
    return new dart2js.FunctionType.synthesized(
        returnType,
        requiredParameterTypes,
        positionalParameterTypes,
        namedParameters,
        namedParameterTypes);
  }

  dart2js.DartType convertType(analyzer.DartType input) {
    if (input.isVoid) {
      return const dart2js.VoidType();
    } else if (input.isDynamic) {
      return const dart2js.DynamicType();
    } else if (input is analyzer.TypeParameterType) {
      return new dart2js.TypeVariableType(convertElement(input.element));
    } else if (input is analyzer.InterfaceType) {
      List<dart2js.DartType> typeArguments =
          input.typeArguments.map(convertType).toList();
      return new dart2js.InterfaceType(
          convertElement(input.element), typeArguments);
    } else if (input is analyzer.FunctionType) {
      if (input.element is analyzer.FunctionTypeAliasElement) {
        List<dart2js.DartType> typeArguments =
            input.typeArguments.map(convertType).toList();
        return new dart2js.ResolvedTypedefType(
            convertElement(input.element),
            typeArguments,
            convertFunctionType(input));
      } else {
        assert(input.typeArguments.isEmpty);
        return convertFunctionType(input);
      }
    }
    throw new UnsupportedError(
        "Conversion of $input (${input.runtimeType}) is not supported.");
  }

  analyzer.Element invertElement(dart2js.Element input) {
    return inversionMap[input];
  }

  dart2js.Element convertElementInternal(analyzer.Element input) {
    dart2js.Element output = input.accept(visitor);
    if (output != null) return output;
    throw new UnsupportedError(
        "Conversion of $input (${input.runtimeType}) is not supported.");
  }
}

/// Visitor that converts analyzer elements to dart2js elements.
class ElementConverterVisitor
    extends analyzer.SimpleElementVisitor<dart2js.Element> {
  final ElementConverter converter;

  ElementConverterVisitor(this.converter);

  @override
  dart2js.LibraryElement visitLibraryElement(analyzer.LibraryElement input) {
    return new LibraryElementY(converter, input);
  }

  @override
  dart2js.FunctionElement visitFunctionElement(analyzer.FunctionElement input) {
    if (input.isStatic) {
      return new TopLevelFunctionElementY(converter, input);
    } else {
      return new LocalFunctionElementY(converter, input);
    }
  }

  @override
  dart2js.ParameterElement visitParameterElement(
      analyzer.ParameterElement input) {
    return new ParameterElementY(converter, input);
  }

  @override
  dart2js.ClassElement visitClassElement(analyzer.ClassElement input) {
    return new ClassElementY(converter, input);
  }

  @override
  dart2js.TypedefElement visitFunctionTypeAliasElement(
      analyzer.FunctionTypeAliasElement input) {
    return new TypedefElementY(converter, input);
  }

  @override
  dart2js.FieldElement visitTopLevelVariableElement(
      analyzer.TopLevelVariableElement input) {
    return new TopLevelVariableElementY(converter, input);
  }

  @override
  dart2js.Element visitPropertyAccessorElement(
      analyzer.PropertyAccessorElement input) {
    if (input.isSynthetic) {
      return input.variable.accept(this);
    }
    return null;
  }

  @override
  dart2js.Element visitLocalVariableElement(
      analyzer.LocalVariableElement input) {
    return new LocalVariableElementY(converter, input);
  }

  @override
  dart2js.ConstructorElement visitConstructorElement(
      analyzer.ConstructorElement input) {
    return new ConstructorElementY(converter, input);
  }
}
