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

part of analyzer2dart.element_converter;


/// Base [dart2js.Element] implementation for converted analyzer elements.
class ElementY extends dart2js.Element {
  final ElementConverter converter;
  final analyzer.Element element;

  @override
  String get name => element.name;

  ElementY(this.converter, this.element);

  @override
  dart2js.LibraryElement get implementationLibrary => library;

  @override
  dart2js.Element get origin => this;

  @override
  dart2js.Element get patch => null;

  @override
  dart2js.Element get declaration => this;

  @override
  dart2js.Element get implementation => this;

  @override
  bool get isPatch => false;

  @override
  bool get isPatched => false;

  @override
  bool get isDeclaration => true;

  @override
  bool get isImplementation => false;

  @override
  dart2js.LibraryElement get library {
    return converter.convertElement(element.library);
  }

  @override
  bool get isLocal => false;

  @override
  bool get isSynthesized => false;

  unsupported(String method) {
    throw new UnsupportedError(
        "'$method' is unsupported on $this ($runtimeType)");
  }


  @override
  bool get isFinal => unsupported('isFinal');

  @override
  bool get isStatic => unsupported('isStatic');

  @override
  bool isForeign(_) => unsupported('isForeign');

  @override
  bool get impliesType => unsupported('impliesType');

  @override
  bool get isOperator => unsupported('impliesType');

  @override
  get position => unsupported('position');

  @override
  computeType(_) => unsupported('computeType');

  @override
  get enclosingElement => unsupported('enclosingElement');

  @override
  accept(_, __) => unsupported('accept');

  @override
  void addMetadata(_) => unsupported('addMetadata');

  @override
  get analyzableElement => unsupported('analyzableElement');

  @override
  asFunctionElement() => unsupported('asFunctionElement');

  @override
  buildScope() => unsupported('buildScope');

  @override
  get compilationUnit => unsupported('compilationUnit');

  @override
  get contextClass => unsupported('contextClass');

  @override
  void diagnose(context, listener) => unsupported('diagnose');

  @override
  get enclosingClass => unsupported('enclosingClass');

  @override
  get enclosingClassOrCompilationUnit {
    return unsupported('enclosingClassOrCompilationUnit');
  }

  @override
  String get fixedBackendName => unsupported('fixedBackendName');

  @override
  bool get hasFixedBackendName => unsupported('hasFixedBackendName');

  @override
  bool get isAbstract => unsupported('isAbstract');

  @override
  bool get isAssignable => unsupported('isAssignable');

  @override
  bool get isClassMember => unsupported('isClassMember');

  @override
  bool get isClosure => unsupported('isClosure');

  @override
  bool get isConst => unsupported('isConst');

  @override
  bool get isDeferredLoaderGetter => unsupported('isDeferredLoaderGetter');

  @override
  bool get isFactoryConstructor => unsupported('isFactoryConstructor');

  @override
  bool get isInjected => unsupported('isInjected');

  @override
  bool get isInstanceMember => unsupported('isInstanceMember');

  @override
  bool get isMixinApplication => unsupported('isMixinApplication');

  @override
  bool get isNative => unsupported('isNative');

  @override
  bool get isTopLevel => unsupported('isTopLevel');

  @override
  get kind => unsupported('kind');

  @override
  get metadata => unsupported('metadata');

  @override
  get outermostEnclosingMemberOrTopLevel {
    return unsupported('outermostEnclosingMemberOrTopLevel');
  }

  @override
  void setNative(String name) => unsupported('setNative');

  String toString() => '$kind($name)';
}

abstract class AnalyzableElementY
    implements ElementY, dart2js.AnalyzableElement {
  @override
  bool get hasTreeElements => unsupported('hasTreeElements');

  @override
  get treeElements => unsupported('treeElements');
}

abstract class AstElementY implements ElementY, dart2js.AstElement {
  @override
  bool get hasNode => unsupported('hasNode');

  @override
  get node => unsupported('node');

  @override
  bool get hasResolvedAst => unsupported('hasResolvedAst');

  @override
  get resolvedAst => unsupported('resolvedAst');
}

class LibraryElementY extends ElementY with AnalyzableElementY
    implements dart2js.LibraryElement {
  analyzer.LibraryElement get element => super.element;

  @override
  dart2js.ElementKind get kind => dart2js.ElementKind.LIBRARY;

  // TODO(johnniwinther): Ensure the correct semantics of this.
  @override
  bool get isInternalLibrary => isPlatformLibrary && element.isPrivate;

  // TODO(johnniwinther): Ensure the correct semantics of this.
  @override
  bool get isPlatformLibrary => element.isInSdk;

  @override
  bool get isDartCore => element.isDartCore;

  LibraryElementY(ElementConverter converter, analyzer.LibraryElement element)
      : super(converter, element);

  @override
  void addCompilationUnit(_) => unsupported('addCompilationUnit');

  @override
  void addImport(element, import, listener) => unsupported('addImport');

  @override
  void addMember(element, listener) => unsupported('addMember');

  @override
  void addTag(tag, listener) => unsupported('addTag');

  @override
  void addToScope(element, listener) => unsupported('addToScope');

  @override
  bool get canUseNative => unsupported('canUseNative');

  @override
  Uri get canonicalUri => unsupported('canonicalUri');

  @override
  int compareTo(other) => unsupported('compareTo');

  @override
  get compilationUnits => unsupported('compilationUnits');

  @override
  get entryCompilationUnit => unsupported('entryCompilationUnit');

  @override
  get exports => unsupported('exports');

  @override
  bool get exportsHandled => unsupported('exportsHandled');

  @override
  find(String elementName) => unsupported('find');

  @override
  findExported(String elementName) => unsupported('findExported');

  @override
  findLocal(String elementName) => unsupported('findLocal');

  @override
  void forEachExport(_) => unsupported('forEachExport');

  @override
  void forEachLocalMember(_) => unsupported('forEachLocalMember');

  @override
  getImportsFor(element) => unsupported('getImportsFor');

  @override
  getLibraryFromTag(tag) => unsupported('getLibraryFromTag');

  @override
  String getLibraryName() => unsupported('getLibraryName');

  @override
  String getLibraryOrScriptName() => unsupported('getLibraryOrScriptName');

  @override
  getNonPrivateElementsInScope() => unsupported('getNonPrivateElementsInScope');

  @override
  bool hasLibraryName() => unsupported('hasLibraryName');

  @override
  bool get isPackageLibrary => unsupported('isPackageLibrary');

  @override
  get libraryTag => unsupported('libraryTag');

  @override
  void set libraryTag(value) => unsupported('libraryTag');

  @override
  localLookup(elementName) => unsupported('localLookup');

  @override
  void recordResolvedTag(tag, library) => unsupported('recordResolvedTag');

  @override
  void setExports(exportedElements) => unsupported('setExports');

  @override
  get tags => unsupported('tags');
}

abstract class TopLevelElementMixin implements ElementY {
  @override
  bool get isClassMember => false;

  @override
  bool get isInstanceMember => false;

  @override
  bool get isTopLevel => true;

  // TODO(johnniwinther): Ensure the correct semantics of this.
  @override
  bool get isFactoryConstructor => false;

  @override
  bool get isStatic {
    // Semantic difference: Analyzer considers top-level and static class
    // members to be static, dart2js only considers static class members to be
    // static.
    return false;
  }

  // TODO(johnniwinther): Ensure the correct semantics of this.
  @override
  bool get isAbstract => false;

  @override
  dart2js.ClassElement get enclosingClass => null;
}

abstract class FunctionElementMixin
    implements ElementY, dart2js.FunctionElement {
  analyzer.ExecutableElement get element;

  // TODO(johnniwinther): Ensure the correct semantics of this.
  @override
  bool get isExternal => false;

  @override
  bool get isConst => false;

  @override
  get abstractField => unsupported('abstractField');

  @override
  computeSignature(_) => unsupported('computeSignature');

  @override
  get memberContext => unsupported('memberContext');

  @override
  get functionSignature => unsupported('functionSignature');

  @override
  bool get hasFunctionSignature => unsupported('hasFunctionSignature');

  @override
  get asyncMarker => unsupported('asyncMarker');

  @override
  List<dart2js.ParameterElement> get parameters {
    return element.parameters.map(converter.convertElement).toList();
  }

  @override
  dart2js.FunctionType get type => converter.convertType(element.type);
}

class TopLevelFunctionElementY extends ElementY
    with AnalyzableElementY,
         AstElementY,
         TopLevelElementMixin,
         FunctionElementMixin,
         MemberElementMixin
    implements dart2js.MethodElement {
  analyzer.FunctionElement get element => super.element;

  @override
  dart2js.ElementKind get kind => dart2js.ElementKind.FUNCTION;

  TopLevelFunctionElementY(ElementConverter converter,
                           analyzer.FunctionElement element)
      : super(converter, element);

  @override
  get nestedClosures => unsupported('nestedClosures');
}

class LocalFunctionElementY extends ElementY
    with AnalyzableElementY,
         AstElementY,
         LocalElementMixin,
         FunctionElementMixin
    implements dart2js.LocalFunctionElement {
  analyzer.FunctionElement get element => super.element;

  @override
  dart2js.ElementKind get kind => dart2js.ElementKind.FUNCTION;

  @override
  bool get isAbstract => false;

  @override
  bool get isConst => false;

  LocalFunctionElementY(ElementConverter converter,
                        analyzer.FunctionElement element)
      : super(converter, element);
}

class ParameterElementY extends ElementY
    with AnalyzableElementY, AstElementY
    implements dart2js.ParameterElement {

  analyzer.ParameterElement get element => super.element;

  @override
  dart2js.ElementKind get kind => dart2js.ElementKind.PARAMETER;

  @override
  dart2js.DartType get type => converter.convertType(element.type);

  @override
  bool get isLocal => true;

  @override
  bool get isStatic => false;

  @override
  bool get isConst => false;

  @override
  bool get isNamed => element.parameterKind == ParameterKind.NAMED;

  @override
  bool get isOptional => element.parameterKind.isOptional;

  ParameterElementY(ElementConverter converter,
                    analyzer.ParameterElement element)
      : super(converter, element) {
    assert(!element.isInitializingFormal);
  }

  @override
  get executableContext => unsupported('executableContext');

  @override
  get functionDeclaration => unsupported('functionDeclaration');

  @override
  get initializer => unsupported('initializer');

  @override
  get memberContext => unsupported('memberContext');

  @override
  get functionSignature => unsupported('functionSignature');
}

class TypeDeclarationElementY extends ElementY
    with AnalyzableElementY, AstElementY
    implements dart2js.TypeDeclarationElement {

  TypeDeclarationElementY(ElementConverter converter,
                          analyzer.Element element)
      : super(converter, element);

  @override
  void ensureResolved(compiler) => unsupported('ensureResolved');

  @override
  bool get isResolved => unsupported('isResolved');

  @override
  get rawType => null;//unsupported('rawType');

  @override
  int get resolutionState => unsupported('resolutionState');

  @override
  get thisType => unsupported('thisType');

  @override
  get typeVariables => unsupported('typeVariables');
}

class ClassElementY extends TypeDeclarationElementY
    implements dart2js.ClassElement {

  analyzer.ClassElement get element => super.element;

  dart2js.ElementKind get kind => dart2js.ElementKind.CLASS;

  @override
  bool get isObject => element.type.isObject;

  // TODO(johnniwinther): Ensure the correct semantics.
  // TODO(paulberry,brianwilkerson): [ClassElement.isTypedef] should probably
  // be renamed to [ClassElement.isNamedMixinApplication].
  @override
  bool get isMixinApplication => element.isTypedef;

  @override
  bool get isUnnamedMixinApplication => false;

  @override
  bool get isEnumClass => element.isEnum;

  @override
  bool get isAbstract => element.isAbstract;

  // TODO(johnniwinther): Semantic difference: Dart2js points to unnamed
  // mixin applications, analyzer points to the type in the extends clause or
  // Object if omitted.
  @override
  dart2js.DartType get supertype {
    return element.supertype != null
        ? converter.convertType(element.supertype)
        : null;
  }

  @override
  util.Link<dart2js.DartType> get interfaces {
    // TODO(johnniwinther): Support interfaces.
    return const util.Link<dart2js.DartType>();
  }

  // TODO(johnniwinther): Support generic classes.
  @override
  List<dart2js.DartType> get typeVariables => const [];

  @override
  bool get isStatic => false;

  @override
  bool get isTopLevel => true;

  @override
  dart2js.ClassElement get enclosingClass => this;

  ClassElementY(ElementConverter converter, analyzer.ClassElement element)
      : super(converter, element);

  @override
  void addBackendMember(element) => unsupported('addBackendMember');

  @override
  void addMember(element, listener) => unsupported('addMember');

  @override
  void addToScope(element, listener) => unsupported('addToScope');

  @override
  get allSupertypes => unsupported('allSupertypes');

  @override
  get allSupertypesAndSelf => unsupported('allSupertypesAndSelf');

  @override
  asInstanceOf(cls) => unsupported('asInstanceOf');

  @override
  get callType => unsupported('callType');

  @override
  computeTypeParameters(compiler) => unsupported('computeTypeParameters');

  @override
  get constructors => unsupported('constructors');

  @override
  void forEachBackendMember(f) => unsupported('forEachBackendMember');

  @override
  void forEachClassMember(f) => unsupported('forEachClassMember');

  @override
  void forEachInstanceField(f, {includeSuperAndInjectedMembers: false}) {
    unsupported('forEachInstanceField');
  }

  @override
  void forEachInterfaceMember(f) => unsupported('forEachInterfaceMember');

  @override
  void forEachLocalMember(f) => unsupported('forEachLocalMember');

  @override
  void forEachMember(f,
                     {includeBackendMembers: false,
                      includeSuperAndInjectedMembers: false}) {
    unsupported('forEachMember');
  }

  @override
  void forEachStaticField(f) => unsupported('forEachStaticField');

  @override
  bool get hasBackendMembers => unsupported('hasBackendMembers');

  @override
  bool get hasConstructor => unsupported('hasConstructor');

  @override
  bool hasFieldShadowedBy(fieldMember) => unsupported('hasFieldShadowedBy');

  @override
  bool get hasIncompleteHierarchy => unsupported('hasIncompleteHierarchy');

  @override
  bool get hasLocalScopeMembers => unsupported('hasLocalScopeMembers');

  @override
  int get hierarchyDepth => unsupported('hierarchyDepth');

  @override
  int get id => unsupported('id');

  @override
  bool implementsFunction(compiler) => unsupported('implementsFunction');

  @override
  bool implementsInterface(intrface) => unsupported('implementsInterface');

  @override
  bool get isProxy => unsupported('isProxy');

  @override
  bool isSubclassOf(cls) => unsupported('isSubclassOf');

  @override
  localLookup(String elementName) => unsupported('localLookup');

  @override
  lookupBackendMember(String memberName) => unsupported('lookupBackendMember');

  @override
  lookupClassMember(name) => unsupported('lookupClassMember');

  @override
  lookupConstructor(selector, [noMatch]) => unsupported('lookupConstructor');

  @override
  lookupInterfaceMember(name) => unsupported('lookupInterfaceMember');

  @override
  lookupLocalMember(String memberName) => unsupported('lookupLocalMember');

  @override
  lookupMember(String memberName) => unsupported('lookupMember');

  @override
  lookupSelector(selector) => unsupported('lookupSelector');

  @override
  lookupSuperMember(String memberName) => unsupported('lookupSuperMember');

  @override
  lookupSuperMemberInLibrary(memberName, library) {
    unsupported('lookupSuperMemberInLibrary');
  }

  @override
  lookupSuperSelector(selector) => unsupported('lookupSuperSelector');

  @override
  String get nativeTagInfo => unsupported('nativeTagInfo');

  @override
  void reverseBackendMembers() => unsupported('reverseBackendMembers');

  @override
  dart2js.ClassElement get superclass => unsupported('superclass');

  @override
  int get supertypeLoadState => unsupported('supertypeLoadState');

  @override
  dart2js.ConstructorElement lookupDefaultConstructor() => unsupported('lookupDefaultConstructor');
}

class TypedefElementY extends TypeDeclarationElementY
    implements dart2js.TypedefElement {

  analyzer.FunctionTypeAliasElement get element => super.element;

  dart2js.ElementKind get kind => dart2js.ElementKind.TYPEDEF;

  TypedefElementY(ElementConverter converter,
                  analyzer.FunctionTypeAliasElement element)
      : super(converter, element);

  @override
  dart2js.DartType get alias => unsupported('alias');

  @override
  void checkCyclicReference(compiler) => unsupported('checkCyclicReference');

  @override
  get functionSignature => unsupported('functionSignature');
}

abstract class VariableElementMixin
    implements ElementY, dart2js.VariableElement {
  @override
  get initializer => unsupported('initializer');

  @override
  get memberContext => unsupported('memberContext');
}

class TopLevelVariableElementY extends ElementY
    with AnalyzableElementY,
         AstElementY,
         TopLevelElementMixin,
         VariableElementMixin,
         MemberElementMixin
    implements dart2js.FieldElement {

  analyzer.TopLevelVariableElement get element => super.element;

  dart2js.ElementKind get kind => dart2js.ElementKind.FIELD;

  @override
  dart2js.DartType get type => converter.convertType(element.type);

  @override
  bool get isFinal => element.isFinal;

  @override
  bool get isConst => element.isConst;

  TopLevelVariableElementY(ElementConverter converter,
                           analyzer.TopLevelVariableElement element)
      : super(converter, element);

  @override
  get nestedClosures => unsupported('nestedClosures');
}

abstract class LocalElementMixin implements ElementY, dart2js.LocalElement {

  @override
  bool get isLocal => true;

  @override
  bool get isInstanceMember => false;

  @override
  bool get isStatic => false;

  @override
  bool get isTopLevel => false;

  @override
  get executableContext => unsupported('executableContext');

  // TODO(johnniwinther): Ensure the correct semantics of this.
  @override
  bool get isFactoryConstructor => false;
}

class LocalVariableElementY extends ElementY
    with AnalyzableElementY,
         AstElementY,
         LocalElementMixin,
         VariableElementMixin
    implements dart2js.LocalVariableElement {

  analyzer.LocalVariableElement get element => super.element;

  dart2js.ElementKind get kind => dart2js.ElementKind.VARIABLE;

  @override
  bool get isConst => element.isConst;

  LocalVariableElementY(ElementConverter converter,
                        analyzer.LocalVariableElement element)
      : super(converter, element);

  @override
  dart2js.DartType get type => unsupported('type');
}

abstract class ClassMemberMixin implements ElementY {
  analyzer.ClassMemberElement get element;

  @override
  dart2js.ClassElement get contextClass => enclosingClass;

  @override
  dart2js.ClassElement get enclosingClass {
    return converter.convertElement(element.enclosingElement);
  }

  @override
  bool get isClassMember => true;

  @override
  bool get isTopLevel => false;
}

class ConstructorElementY extends ElementY
    with AnalyzableElementY,
         AstElementY,
         FunctionElementMixin,
         ClassMemberMixin,
         MemberElementMixin
    implements dart2js.ConstructorElement {

  analyzer.ConstructorElement get element => super.element;

  // TODO(johnniwinther): Support redirecting/factory constructors.
  @override
  dart2js.ElementKind get kind => dart2js.ElementKind.GENERATIVE_CONSTRUCTOR;

  // TODO(johnniwinther): Support factory constructors.
  @override
  bool get isFactoryConstructor => false;

  // TODO(johnniwinther): Support redirecting factory constructors.
  @override
  bool get isRedirectingFactory => false;

  // TODO(johnniwinther): Support redirecting generative constructors.
  @override
  bool get isRedirectingGenerative => false;

  @override
  bool get isStatic => false;

  @override
  bool get isSynthesized => element.isSynthetic;

  ConstructorElementY(ElementConverter converter,
                      analyzer.ConstructorElement element)
      : super(converter, element);

  @override
  computeEffectiveTargetType(_) => unsupported('computeEffectiveTargetType');

  @override
  get definingConstructor => unsupported('definingConstructor');

  @override
  get effectiveTarget => unsupported('effectiveTarget');

  @override
  get immediateRedirectionTarget => unsupported('immediateRedirectionTarget');

  @override
  get nestedClosures => unsupported('nestedClosures');
}

class InstanceMethodElementY extends ElementY
    with AnalyzableElementY,
         AstElementY,
         FunctionElementMixin,
         ClassMemberMixin,
         MemberElementMixin
    implements dart2js.MethodElement {

  analyzer.MethodElement get element => super.element;

  @override
  dart2js.ElementKind get kind => dart2js.ElementKind.FUNCTION;

  @override
  bool get isStatic => element.isStatic;

  @override
  bool get isAbstract => element.isAbstract;

  @override
  bool get isFactoryConstructor => false;

  @override
  bool get isInstanceMember => true;

  InstanceMethodElementY(ElementConverter converter,
                         analyzer.MethodElement element)
      : super(converter, element);

  @override
  get nestedClosures => unsupported('nestedClosures');
}

abstract class MemberElementMixin implements dart2js.MemberElement {
  dart2js.Name get memberName => new dart2js.Name(name, library);
}
