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

/// Analysis to determine how to generate code for typed JavaScript interop.
library compiler.src.js_backend.js_interop_analysis;

import '../common.dart';
import '../constants/values.dart'
    show ConstantValue, ConstructedConstantValue, StringConstantValue;
import '../elements/resolution_types.dart'
    show ResolutionDartType, ResolutionDynamicType, ResolutionFunctionType;
import '../diagnostics/messages.dart' show MessageKind;
import '../elements/elements.dart'
    show
        ClassElement,
        Element,
        FieldElement,
        FunctionElement,
        LibraryElement,
        ParameterElement,
        MetadataAnnotation;
import '../js/js.dart' as jsAst;
import '../js/js.dart' show js;
import '../universe/selector.dart' show Selector;
import '../universe/world_builder.dart' show SelectorConstraints;
import 'backend_helpers.dart' show BackendHelpers;
import 'js_backend.dart' show JavaScriptBackend;

class JsInteropAnalysis {
  final JavaScriptBackend backend;

  /// The resolved [FieldElement] for `Js.name`.
  FieldElement nameField;
  bool enabledJsInterop = false;

  /// Whether the backend is currently processing the codegen queue.
  bool _inCodegen = false;

  JsInteropAnalysis(this.backend);

  BackendHelpers get helpers => backend.helpers;

  void onQueueClosed() {
    if (_inCodegen) return;

    if (helpers.jsAnnotationClass != null) {
      nameField = helpers.jsAnnotationClass.lookupMember('name');
      backend.compiler.libraryLoader.libraries
          .forEach(processJsInteropAnnotationsInLibrary);
    }
  }

  void onCodegenStart() {
    _inCodegen = true;
  }

  void processJsInteropAnnotation(Element e) {
    for (MetadataAnnotation annotation in e.implementation.metadata) {
      // TODO(johnniwinther): Avoid processing unresolved elements.
      if (annotation.constant == null) continue;
      ConstantValue constant =
          backend.compiler.constants.getConstantValue(annotation.constant);
      if (constant == null || constant is! ConstructedConstantValue) continue;
      ConstructedConstantValue constructedConstant = constant;
      if (constructedConstant.type.element == helpers.jsAnnotationClass) {
        ConstantValue value = constructedConstant.fields[nameField];
        if (value.isString) {
          StringConstantValue stringValue = value;
          backend.nativeData
              .setJsInteropName(e, stringValue.primitiveValue.slowToString());
        } else {
          // TODO(jacobr): report a warning if the value is not a String.
          backend.nativeData.setJsInteropName(e, '');
        }
        enabledJsInterop = true;
        return;
      }
    }
  }

  bool hasAnonymousAnnotation(Element element) {
    if (backend.helpers.jsAnonymousClass == null) return false;
    return element.metadata.any((MetadataAnnotation annotation) {
      ConstantValue constant =
          backend.compiler.constants.getConstantValue(annotation.constant);
      if (constant == null || constant is! ConstructedConstantValue)
        return false;
      ConstructedConstantValue constructedConstant = constant;
      return constructedConstant.type.element ==
          backend.helpers.jsAnonymousClass;
    });
  }

  void _checkFunctionParameters(FunctionElement fn) {
    if (fn.hasFunctionSignature &&
        fn.functionSignature.optionalParametersAreNamed) {
      backend.reporter.reportErrorMessage(
          fn,
          MessageKind.JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS,
          {'method': fn.name});
    }
  }

  void processJsInteropAnnotationsInLibrary(LibraryElement library) {
    processJsInteropAnnotation(library);
    library.implementation.forEachLocalMember((Element element) {
      processJsInteropAnnotation(element);
      if (!backend.isJsInterop(element)) return;
      if (element is FunctionElement) {
        _checkFunctionParameters(element);
      }

      if (!element.isClass) return;

      ClassElement classElement = element;

      // Skip classes that are completely unreachable. This should only happen
      // when all of jsinterop types are unreachable from main.
      if (!backend.compiler.resolverWorld.isImplemented(classElement)) return;

      if (!classElement.implementsInterface(helpers.jsJavaScriptObjectClass)) {
        backend.reporter.reportErrorMessage(classElement,
            MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, {
          'cls': classElement.name,
          'superclass': classElement.superclass.name
        });
      }

      classElement.forEachMember((ClassElement classElement, Element member) {
        processJsInteropAnnotation(member);

        if (!member.isSynthesized &&
            backend.isJsInterop(classElement) &&
            member is FunctionElement) {
          FunctionElement fn = member;
          if (!fn.isExternal &&
              !fn.isAbstract &&
              !fn.isConstructor &&
              !fn.isStatic) {
            backend.reporter.reportErrorMessage(
                fn,
                MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER,
                {'cls': classElement.name, 'member': member.name});
          }

          if (fn.isFactoryConstructor && hasAnonymousAnnotation(classElement)) {
            fn.functionSignature
                .orderedForEachParameter((ParameterElement parameter) {
              if (!parameter.isNamed) {
                backend.reporter.reportErrorMessage(
                    parameter,
                    MessageKind
                        .JS_OBJECT_LITERAL_CONSTRUCTOR_WITH_POSITIONAL_ARGUMENTS,
                    {'parameter': parameter.name, 'cls': classElement.name});
              }
            });
          } else {
            _checkFunctionParameters(fn);
          }
        }
      });
    });
  }

  jsAst.Statement buildJsInteropBootstrap() {
    if (!enabledJsInterop) return null;
    List<jsAst.Statement> statements = <jsAst.Statement>[];
    backend.compiler.codegenWorld.forEachInvokedName(
        (String name, Map<Selector, SelectorConstraints> selectors) {
      selectors.forEach((Selector selector, SelectorConstraints constraints) {
        if (selector.isClosureCall) {
          // TODO(jacobr): support named arguments.
          if (selector.namedArgumentCount > 0) return;
          int argumentCount = selector.argumentCount;
          var candidateParameterNames =
              'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
          var parameters = new List<String>.generate(
              argumentCount, (i) => candidateParameterNames[i]);

          var name = backend.namer.invocationName(selector);
          statements.add(js.statement(
              'Function.prototype.# = function(#) { return this(#) }',
              [name, parameters, parameters]));
        }
      });
    });
    return new jsAst.Block(statements);
  }

  ResolutionFunctionType buildJsFunctionType() {
    // TODO(jacobr): consider using codegenWorld.isChecks to determine the
    // range of positional arguments that need to be supported by JavaScript
    // function types.
    return new ResolutionFunctionType.synthesized(
        const ResolutionDynamicType(),
        [],
        new List<ResolutionDartType>.filled(16, const ResolutionDynamicType()));
  }
}
