// 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 dart2js.parser.member_listener;

import '../common.dart';
import '../elements/elements.dart' show
    Element,
    ElementKind,
    Elements,
    MetadataAnnotation;
import '../elements/modelx.dart' show
    ClassElementX,
    ElementX,
    FieldElementX,
    VariableList;
import '../tokens/token.dart' show
    Token;
import '../tree/tree.dart';

import 'element_listener.dart' show
    ScannerOptions;
import 'node_listener.dart' show
    NodeListener;
import 'partial_elements.dart' show
    PartialConstructorElement,
    PartialFunctionElement,
    PartialMetadataAnnotation;

class MemberListener extends NodeListener {
  final ClassElementX enclosingClass;

  MemberListener(ScannerOptions scannerOptions,
                 DiagnosticReporter listener,
                 ClassElementX enclosingElement)
      : this.enclosingClass = enclosingElement,
        super(scannerOptions, listener, enclosingElement.compilationUnit);

  bool isConstructorName(Node nameNode) {
    if (enclosingClass == null ||
        enclosingClass.kind != ElementKind.CLASS) {
      return false;
    }
    String name;
    if (nameNode.asIdentifier() != null) {
      name = nameNode.asIdentifier().source;
    } else {
      Send send = nameNode.asSend();
      name = send.receiver.asIdentifier().source;
    }
    return enclosingClass.name == name;
  }

  // TODO(johnniwinther): Remove this method.
  String getMethodNameHack(Node methodName) {
    Send send = methodName.asSend();
    if (send == null) {
      if (isConstructorName(methodName)) return '';
      return methodName.asIdentifier().source;
    }
    Identifier receiver = send.receiver.asIdentifier();
    Identifier selector = send.selector.asIdentifier();
    Operator operator = selector.asOperator();
    if (operator != null) {
      assert(identical(receiver.source, 'operator'));
      // TODO(ahe): It is a hack to compare to ')', but it beats
      // parsing the node.
      bool isUnary = identical(operator.token.next.next.stringValue, ')');
      return Elements.constructOperatorName(operator.source, isUnary);
    } else {
      if (receiver == null || receiver.source != enclosingClass.name) {
        reporter.reportErrorMessage(
            send.receiver,
            MessageKind.INVALID_CONSTRUCTOR_NAME,
            {'name': enclosingClass.name});
      }
      return selector.source;
    }
  }

  void endMethod(Token getOrSet, Token beginToken, Token endToken) {
    super.endMethod(getOrSet, beginToken, endToken);
    FunctionExpression method = popNode();
    pushNode(null);
    bool isConstructor = isConstructorName(method.name);
    String name = getMethodNameHack(method.name);
    Element memberElement;
    if (isConstructor) {
      if (getOrSet != null) {
        recoverableError(getOrSet, 'illegal modifier');
      }
      memberElement = new PartialConstructorElement(
          name, beginToken, endToken,
          ElementKind.GENERATIVE_CONSTRUCTOR,
          method.modifiers,
          enclosingClass);
    } else {
      memberElement = new PartialFunctionElement(
          name, beginToken, getOrSet, endToken,
          method.modifiers, enclosingClass, hasBody: method.hasBody());
    }
    addMember(memberElement);
  }

  void endFactoryMethod(Token beginToken, Token endToken) {
    super.endFactoryMethod(beginToken, endToken);
    FunctionExpression method = popNode();
    pushNode(null);
    String name = getMethodNameHack(method.name);
    Identifier singleIdentifierName = method.name.asIdentifier();
    if (singleIdentifierName != null && singleIdentifierName.source == name) {
      if (name != enclosingClass.name) {
        reporter.reportErrorMessage(
            singleIdentifierName,
            MessageKind.INVALID_UNNAMED_CONSTRUCTOR_NAME,
            {'name': enclosingClass.name});
      }
    }
    Element memberElement = new PartialConstructorElement(
        name, beginToken, endToken,
        ElementKind.FACTORY_CONSTRUCTOR,
        method.modifiers,
        enclosingClass);
    addMember(memberElement);
  }

  void endFields(int count, Token beginToken, Token endToken) {
    bool hasParseError = memberErrors.head;
    super.endFields(count, beginToken, endToken);
    VariableDefinitions variableDefinitions = popNode();
    Modifiers modifiers = variableDefinitions.modifiers;
    pushNode(null);
    void buildFieldElement(Identifier name, VariableList fields) {
      Element element =
          new FieldElementX(name, enclosingClass, fields);
      addMember(element);
    }
    buildFieldElements(modifiers, variableDefinitions.definitions,
                       enclosingClass,
                       buildFieldElement, beginToken, endToken,
                       hasParseError);
  }

  void endInitializer(Token assignmentOperator) {
    pushNode(null); // Super expects an expression, but
                    // ClassElementParser just skips expressions.
    super.endInitializer(assignmentOperator);
  }

  void endInitializers(int count, Token beginToken, Token endToken) {
    pushNode(null);
  }

  void addMetadata(ElementX memberElement) {
    memberElement.metadata = metadata.toList();
  }

  void addMember(ElementX memberElement) {
    addMetadata(memberElement);
    enclosingClass.addMember(memberElement, reporter);
  }

  void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
    popNode(); // Discard arguments.
    if (periodBeforeName != null) {
      popNode(); // Discard name.
    }
    popNode(); // Discard node (Send or Identifier).
    pushMetadata(new PartialMetadataAnnotation(beginToken, endToken));
  }
}
