// Copyright (c) 2012, 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 native;

import 'dart:uri';
import 'dart2jslib.dart' hide SourceString;
import 'elements/elements.dart';
import 'js_backend/js_backend.dart';
import 'scanner/scannerlib.dart';
import 'ssa/ssa.dart';
import 'tree/tree.dart';
import 'util/util.dart';

void processNativeClasses(Enqueuer world,
                          CodeEmitterTask emitter,
                          Collection<LibraryElement> libraries) {
  for (LibraryElement library in libraries) {
    processNativeClassesInLibrary(world, emitter, library);
  }
}

void addSubtypes(ClassElement cls,
                 NativeEmitter emitter) {
  for (DartType type in cls.allSupertypes) {
    List<Element> subtypes = emitter.subtypes.putIfAbsent(
        type.element,
        () => <ClassElement>[]);
    subtypes.add(cls);
  }

  List<Element> directSubtypes = emitter.directSubtypes.putIfAbsent(
      cls.superclass,
      () => <ClassElement>[]);
  directSubtypes.add(cls);
}

void processNativeClassesInLibrary(Enqueuer world,
                                   CodeEmitterTask emitter,
                                   LibraryElement library) {
  bool hasNativeClass = false;
  final compiler = emitter.compiler;
  // Use implementation to ensure the inclusion of injected members.
  library.implementation.forEachLocalMember((Element element) {
    if (element.kind == ElementKind.CLASS) {
      ClassElement classElement = element;
      if (classElement.isNative()) {
        hasNativeClass = true;
        world.registerInstantiatedClass(classElement);
        // Also parse the node to know all its methods because
        // otherwise it will only be parsed if there is a call to
        // one of its constructor.
        classElement.parseNode(compiler);
        // Resolve to setup the inheritance.
        classElement.ensureResolved(compiler);
        // Add the information that this class is a subtype of
        // its supertypes. The code emitter and the ssa builder use that
        // information.
        addSubtypes(classElement, emitter.nativeEmitter);
      }
    }
  });
  if (hasNativeClass) {
    world.registerStaticUse(compiler.findHelper(
        const SourceString('dynamicFunction')));
    world.registerStaticUse(compiler.findHelper(
        const SourceString('dynamicSetMetadata')));
    world.registerStaticUse(compiler.findHelper(
        const SourceString('defineProperty')));
    world.registerStaticUse(compiler.findHelper(
        const SourceString('toStringForNativeObject')));
    world.registerStaticUse(compiler.findHelper(
        const SourceString('hashCodeForNativeObject')));
  }
}

void maybeEnableNative(Compiler compiler,
                       LibraryElement library,
                       Uri uri) {
  String libraryName = uri.toString();
  if (library.entryCompilationUnit.script.name.contains(
          'dart/tests/compiler/dart2js_native')
      || libraryName == 'dart:isolate'
      || libraryName == 'dart:html') {
    library.canUseNative = true;
  }
}

void checkAllowedLibrary(ElementListener listener, Token token) {
  LibraryElement currentLibrary = listener.compilationUnitElement.getLibrary();
  if (!currentLibrary.canUseNative) {
    listener.recoverableError("Unexpected token", token: token);
  }
}

Token handleNativeBlockToSkip(Listener listener, Token token) {
  checkAllowedLibrary(listener, token);
  token = token.next;
  if (identical(token.kind, STRING_TOKEN)) {
    token = token.next;
  }
  if (identical(token.stringValue, '{')) {
    BeginGroupToken beginGroupToken = token;
    token = beginGroupToken.endGroup;
  }
  return token;
}

Token handleNativeClassBodyToSkip(Listener listener, Token token) {
  checkAllowedLibrary(listener, token);
  listener.handleIdentifier(token);
  token = token.next;
  if (!identical(token.kind, STRING_TOKEN)) {
    return listener.unexpected(token);
  }
  token = token.next;
  if (!identical(token.stringValue, '{')) {
    return listener.unexpected(token);
  }
  BeginGroupToken beginGroupToken = token;
  token = beginGroupToken.endGroup;
  return token;
}

Token handleNativeClassBody(Listener listener, Token token) {
  checkAllowedLibrary(listener, token);
  token = token.next;
  if (!identical(token.kind, STRING_TOKEN)) {
    listener.unexpected(token);
  } else {
    token = token.next;
  }
  return token;
}

Token handleNativeFunctionBody(ElementListener listener, Token token) {
  checkAllowedLibrary(listener, token);
  Token begin = token;
  listener.beginReturnStatement(token);
  token = token.next;
  bool hasExpression = false;
  if (identical(token.kind, STRING_TOKEN)) {
    hasExpression = true;
    listener.beginLiteralString(token);
    listener.endLiteralString(0);
    token = token.next;
  }
  listener.endReturnStatement(hasExpression, begin, token);
  // TODO(ngeoffray): expect a ';'.
  // Currently there are method with both native marker and Dart body.
  return token.next;
}

SourceString checkForNativeClass(ElementListener listener) {
  SourceString nativeName;
  Node node = listener.nodes.head;
  if (node != null
      && node.asIdentifier() != null
      && node.asIdentifier().source.stringValue == 'native') {
    nativeName = node.asIdentifier().token.next.value;
    listener.popNode();
  }
  return nativeName;
}

bool isOverriddenMethod(FunctionElement element,
                        ClassElement cls,
                        NativeEmitter nativeEmitter) {
  List<ClassElement> subtypes = nativeEmitter.subtypes[cls];
  if (subtypes == null) return false;
  for (ClassElement subtype in subtypes) {
    if (subtype.lookupLocalMember(element.name) != null) return true;
  }
  return false;
}

void handleSsaNative(SsaBuilder builder, Expression nativeBody) {
  Compiler compiler = builder.compiler;
  FunctionElement element = builder.work.element;
  element.setNative();
  NativeEmitter nativeEmitter = builder.emitter.nativeEmitter;
  // If what we're compiling is a getter named 'typeName' and the native
  // class is named 'DOMType', we generate a call to the typeNameOf
  // function attached on the isolate.
  // The DOM classes assume that their 'typeName' property, which is
  // not a JS property on the DOM types, returns the type name.
  if (element.name == const SourceString('typeName')
      && element.isGetter()
      && nativeEmitter.toNativeName(element.getEnclosingClass()) == 'DOMType') {
    Element helper =
        compiler.findHelper(const SourceString('getTypeNameOf'));
    builder.pushInvokeHelper1(helper, builder.localsHandler.readThis());
    builder.close(new HReturn(builder.pop())).addSuccessor(builder.graph.exit);
  }

  HInstruction convertDartClosure(Element parameter, FunctionType type) {
    HInstruction local = builder.localsHandler.readLocal(parameter);
    Constant arityConstant =
        builder.constantSystem.createInt(type.computeArity());
    HInstruction arity = builder.graph.addConstant(arityConstant);
    // TODO(ngeoffray): For static methods, we could pass a method with a
    // defined arity.
    Element helper = builder.interceptors.getClosureConverter();
    builder.pushInvokeHelper2(helper, local, arity);
    HInstruction closure = builder.pop();
    return closure;
  }

  // Check which pattern this native method follows:
  // 1) foo() native; hasBody = false, isRedirecting = false
  // 2) foo() native "bar"; hasBody = false, isRedirecting = true
  // 3) foo() native "return 42"; hasBody = true, isRedirecting = false
  RegExp nativeRedirectionRegExp = const RegExp(r'^[a-zA-Z][a-zA-Z_$0-9]*$');
  bool hasBody = false;
  bool isRedirecting = false;
  String nativeMethodName = element.name.slowToString();
  if (nativeBody != null) {
    LiteralString jsCode = nativeBody.asLiteralString();
    String str = jsCode.dartString.slowToString();
    if (nativeRedirectionRegExp.hasMatch(str)) {
      nativeMethodName = str;
      isRedirecting = true;
      nativeEmitter.addRedirectingMethod(element, nativeMethodName);
    } else {
      hasBody = true;
    }
  }

  if (!hasBody) {
    nativeEmitter.nativeMethods.add(element);
  }

  FunctionSignature parameters = element.computeSignature(builder.compiler);
  if (!hasBody) {
    List<String> arguments = <String>[];
    List<HInstruction> inputs = <HInstruction>[];
    String receiver = '';
    if (element.isInstanceMember()) {
      receiver = '#.';
      inputs.add(builder.localsHandler.readThis());
    }
    parameters.forEachParameter((Element parameter) {
      DartType type = parameter.computeType(compiler).unalias(compiler);
      HInstruction input = builder.localsHandler.readLocal(parameter);
      if (type is FunctionType) {
        // The parameter type is a function type either directly or through
        // typedef(s).
        input = convertDartClosure(parameter, type);
      }
      inputs.add(input);
      arguments.add('#');
    });

    String foreignParameters = Strings.join(arguments, ',');
    String nativeMethodCall;
    if (element.kind == ElementKind.FUNCTION) {
      nativeMethodCall = '$receiver$nativeMethodName($foreignParameters)';
    } else if (element.kind == ElementKind.GETTER) {
      nativeMethodCall = '$receiver$nativeMethodName';
    } else if (element.kind == ElementKind.SETTER) {
      nativeMethodCall = '$receiver$nativeMethodName = $foreignParameters';
    } else {
      builder.compiler.internalError('unexpected kind: "${element.kind}"',
                                     element: element);
    }

    DartString jsCode = new DartString.literal(nativeMethodCall);
    builder.push(
        new HForeign(jsCode, const LiteralDartString('Object'), inputs));
    builder.close(new HReturn(builder.pop())).addSuccessor(builder.graph.exit);
  } else {
    // This is JS code written in a Dart file with the construct
    // native """ ... """;. It does not work well with mangling,
    // but there should currently be no clash between leg mangling
    // and the library where this construct is being used. This
    // mangling problem will go away once we switch these libraries
    // to use Leg's 'JS' function.
    parameters.forEachParameter((Element parameter) {
      DartType type = parameter.computeType(compiler).unalias(compiler);
      if (type is FunctionType) {
        // The parameter type is a function type either directly or through
        // typedef(s).
        HInstruction jsClosure = convertDartClosure(parameter, type);
        // Because the JS code references the argument name directly,
        // we must keep the name and assign the JS closure to it.
        builder.add(new HForeign(
            new DartString.literal('${parameter.name.slowToString()} = #'),
            const LiteralDartString('void'),
            <HInstruction>[jsClosure]));
      }
    });
    LiteralString jsCode = nativeBody.asLiteralString();
    builder.push(new HForeign.statement(jsCode.dartString, <HInstruction>[]));
  }
}

void generateMethodWithPrototypeCheckForElement(Compiler compiler,
                                                StringBuffer buffer,
                                                FunctionElement element,
                                                String code,
                                                String parameters) {
  String methodName;
  JavaScriptBackend backend = compiler.backend;
  Namer namer = backend.namer;
  if (element.kind == ElementKind.FUNCTION) {
    methodName = namer.instanceMethodName(element);
  } else if (element.kind == ElementKind.GETTER) {
    methodName = namer.getterName(element.getLibrary(), element.name);
  } else if (element.kind == ElementKind.SETTER) {
    methodName = namer.setterName(element.getLibrary(), element.name);
  } else {
    compiler.internalError('unexpected kind: "${element.kind}"',
                           element: element);
  }

  generateMethodWithPrototypeCheck(
      compiler, buffer, methodName, code, parameters);
}


// If a method is overridden, we must check if the prototype of
// 'this' has the method available. Otherwise, we may end up
// calling the method from the super class. If the method is not
// available, we make a direct call to Object.prototype.$methodName.
// This method will patch the prototype of 'this' to the real method.
void generateMethodWithPrototypeCheck(Compiler compiler,
                                      StringBuffer buffer,
                                      String methodName,
                                      String code,
                                      String parameters) {
  buffer.add("  if (Object.getPrototypeOf(this).hasOwnProperty");
  buffer.add("('$methodName')) {\n");
  buffer.add("  $code");
  buffer.add("  } else {\n");
  buffer.add("    return Object.prototype.$methodName.call(this");
  buffer.add(parameters == '' ? '' : ', $parameters');
  buffer.add(");\n");
  buffer.add("  }\n");
}
