// Copyright (c) 2013, 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 dart2js.js_emitter.full_emitter;

class NsmEmitter extends CodeEmitterHelper {
  final ClosedWorld closedWorld;
  final List<Selector> trivialNsmHandlers = <Selector>[];

  NsmEmitter(this.closedWorld);

  /// If this is true then we can generate the noSuchMethod handlers at startup
  /// time, instead of them being emitted as part of the Object class.
  bool get generateTrivialNsmHandlers => true;

  // If we need fewer than this many noSuchMethod handlers we can save space by
  // just emitting them in JS, rather than emitting the JS needed to generate
  // them at run time.
  static const VERY_FEW_NO_SUCH_METHOD_HANDLERS = 10;

  static const MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING = 4;

  void emitNoSuchMethodHandlers(AddPropertyFunction addProperty) {
    ClassStubGenerator generator = new ClassStubGenerator(
        namer, backend, codegenWorld, closedWorld,
        enableMinification: compiler.options.enableMinification);

    // Keep track of the JavaScript names we've already added so we
    // do not introduce duplicates (bad for code size).
    Map<jsAst.Name, Selector> addedJsNames =
        generator.computeSelectorsForNsmHandlers();

    // Set flag used by generateMethod helper below.  If we have very few
    // handlers we use addProperty for them all, rather than try to generate
    // them at runtime.
    bool haveVeryFewNoSuchMemberHandlers =
        (addedJsNames.length < VERY_FEW_NO_SUCH_METHOD_HANDLERS);
    List<jsAst.Name> names = addedJsNames.keys.toList()..sort();
    for (jsAst.Name jsName in names) {
      Selector selector = addedJsNames[jsName];
      String reflectionName = emitter.getReflectionName(selector, jsName);

      if (reflectionName != null) {
        emitter.mangledFieldNames[jsName] = reflectionName;
      }

      List<jsAst.Expression> argNames = selector.callStructure
          .getOrderedNamedArguments()
          .map((String name) => js.string(name))
          .toList();
      int type = selector.invocationMirrorKind;
      if (!haveVeryFewNoSuchMemberHandlers &&
          isTrivialNsmHandler(type, argNames, selector, jsName) &&
          reflectionName == null) {
        trivialNsmHandlers.add(selector);
      } else {
        StubMethod method =
            generator.generateStubForNoSuchMethod(jsName, selector);
        addProperty(method.name, method.code);
        if (reflectionName != null) {
          bool accessible = closedWorld.allFunctions
              .filter(selector, null)
              .any((Element e) => backend.isAccessibleByReflection(e));
          addProperty(
              namer.asName('+$reflectionName'), js(accessible ? '2' : '0'));
        }
      }
    }
  }

  // Identify the noSuchMethod handlers that are so simple that we can
  // generate them programatically.
  bool isTrivialNsmHandler(
      int type, List argNames, Selector selector, jsAst.Name internalName) {
    if (!generateTrivialNsmHandlers) return false;
    // Check for named arguments.
    if (argNames.length != 0) return false;
    // Check for unexpected name (this doesn't really happen).
    if (internalName is GetterName) return type == 1;
    if (internalName is SetterName) return type == 2;
    return type == 0;
  }

  /**
   * Adds (at runtime) the handlers to the Object class which catch calls to
   * methods that the object does not have.  The handlers create an invocation
   * mirror object.
   *
   * The current version only gives you the minified name when minifying (when
   * not minifying this method is not called).
   *
   * In order to generate the noSuchMethod handlers we only need the minified
   * name of the method.  We test the first character of the minified name to
   * determine if it is a getter or a setter, and we use the arguments array at
   * runtime to get the number of arguments and their values.  If the method
   * involves named arguments etc. then we don't handle it here, but emit the
   * handler method directly on the Object class.
   *
   * The minified names are mostly 1-4 character names, which we emit in sorted
   * order (primary key is length, secondary ordering is lexicographic).  This
   * gives an order like ... dD dI dX da ...
   *
   * Gzip is good with repeated text, but it can't diff-encode, so we do that
   * for it.  We encode the minified names in a comma-separated string, but all
   * the 1-4 character names are encoded before the first comma as a series of
   * base 26 numbers.  The last digit of each number is lower case, the others
   * are upper case, so 1 is "b" and 26 is "Ba".
   *
   * We think of the minified names as base 88 numbers using the ASCII
   * characters from # to z.  The base 26 numbers each encode the delta from
   * the previous minified name to the next.  So if there is a minified name
   * called Df and the next is Dh, then they are 2971 and 2973 when thought of
   * as base 88 numbers.  The difference is 2, which is "c" in lower-case-
   * terminated base 26.
   *
   * The reason we don't encode long minified names with this method is that
   * decoding the base 88 numbers would overflow JavaScript's puny integers.
   *
   * There are some selectors that have a special calling convention (because
   * they are called with the receiver as the first argument).  They need a
   * slightly different noSuchMethod handler, so we handle these first.
   */
  List<jsAst.Statement> buildTrivialNsmHandlers() {
    List<jsAst.Statement> statements = <jsAst.Statement>[];
    if (trivialNsmHandlers.length == 0) return statements;

    bool minify = compiler.options.enableMinification;
    bool useDiffEncoding = minify && trivialNsmHandlers.length > 30;

    // Find out how many selectors there are with the special calling
    // convention.
    Iterable<Selector> interceptedSelectors = trivialNsmHandlers
        .where((Selector s) => backend.isInterceptedName(s.name));
    Iterable<Selector> ordinarySelectors = trivialNsmHandlers
        .where((Selector s) => !backend.isInterceptedName(s.name));

    // Get the short names (JS names, perhaps minified).
    Iterable<jsAst.Name> interceptedShorts =
        interceptedSelectors.map(namer.invocationMirrorInternalName);
    Iterable<jsAst.Name> ordinaryShorts =
        ordinarySelectors.map(namer.invocationMirrorInternalName);

    jsAst.Expression sortedShorts;
    Iterable<String> sortedLongs;
    if (useDiffEncoding) {
      assert(minify);
      sortedShorts =
          new _DiffEncodedListOfNames([interceptedShorts, ordinaryShorts]);
    } else {
      Iterable<Selector> sorted =
          [interceptedSelectors, ordinarySelectors].expand((e) => (e));
      sortedShorts = js.concatenateStrings(
          js.joinLiterals(sorted.map(namer.invocationMirrorInternalName),
              js.stringPart(",")),
          addQuotes: true);

      if (!minify) {
        sortedLongs =
            sorted.map((selector) => selector.invocationMirrorMemberName);
      }
    }
    // Startup code that loops over the method names and puts handlers on the
    // Object class to catch noSuchMethod invocations.
    ClassElement objectClass = compiler.commonElements.objectClass;
    jsAst.Expression createInvocationMirror = backend.emitter
        .staticFunctionAccess(backend.helpers.createInvocationMirror);
    if (useDiffEncoding) {
      statements.add(js.statement(
          '''{
          var objectClassObject = processedClasses.collected[#objectClass],
              nameSequences = #diffEncoding.split("."),
              shortNames = [];
          if (objectClassObject instanceof Array)
              objectClassObject = objectClassObject[1];
          for (var j = 0; j < nameSequences.length; ++j) {
              var sequence = nameSequences[j].split(","),
                nameNumber = 0;
            // If we are loading a deferred library the object class will not be
            // in the collectedClasses so objectClassObject is undefined, and we
            // skip setting up the names.
            if (!objectClassObject) break;
            // Likewise, if the current sequence is empty, we don't process it.
            if (sequence.length == 0) continue;
            var diffEncodedString = sequence[0];
            for (var i = 0; i < diffEncodedString.length; i++) {
              var codes = [],
                  diff = 0,
                  digit = diffEncodedString.charCodeAt(i);
              for (; digit <= ${$Z};) {
                diff *= 26;
                diff += (digit - ${$A});
                digit = diffEncodedString.charCodeAt(++i);
              }
              diff *= 26;
              diff += (digit - ${$a});
              nameNumber += diff;
              for (var remaining = nameNumber;
                   remaining > 0;
                   remaining = (remaining / 88) | 0) {
                codes.unshift(${$HASH} + remaining % 88);
              }
              shortNames.push(
                String.fromCharCode.apply(String, codes));
            }
            if (sequence.length > 1) {
              Array.prototype.push.apply(shortNames, sequence.shift());
            }
          }
        }''',
          {
            'objectClass': js.quoteName(namer.className(objectClass)),
            'diffEncoding': sortedShorts
          }));
    } else {
      // No useDiffEncoding version.
      statements.add(js.statement(
          'var objectClassObject = processedClasses.collected[#objectClass],'
          '    shortNames = #diffEncoding.split(",")',
          {
            'objectClass': js.quoteName(namer.className(objectClass)),
            'diffEncoding': sortedShorts
          }));
      if (!minify) {
        statements.add(js.statement('var longNames = #longs.split(",")',
            {'longs': js.string(sortedLongs.join(','))}));
      }
      statements.add(js.statement('if (objectClassObject instanceof Array)'
          '  objectClassObject = objectClassObject[1];'));
    }

    dynamic isIntercepted = // jsAst.Expression or bool.
        interceptedSelectors.isEmpty
            ? false
            : ordinarySelectors.isEmpty
                ? true
                : js('j < #', js.number(interceptedSelectors.length));

    statements.add(js.statement(
        '''
      // If we are loading a deferred library the object class will not be in
      // the collectedClasses so objectClassObject is undefined, and we skip
      // setting up the names.
      if (objectClassObject) {
        for (var j = 0; j < shortNames.length; j++) {
          var type = 0;
          var shortName = shortNames[j];
          if (shortName.indexOf("${namer.getterPrefix}") == 0) type = 1;
          if (shortName.indexOf("${namer.setterPrefix}") == 0) type = 2;
          // Generate call to:
          //
          //     createInvocationMirror(String name, internalName, type,
          //         arguments, argumentNames)
          //

          // This 'if' is either a static choice or dynamic choice depending on
          // [isIntercepted].
          if (#isIntercepted) {
            objectClassObject[shortName] =
                (function(name, shortName, type) {
                  return function(receiver) {
                    return this.#noSuchMethodName(
                      receiver,
                      #createInvocationMirror(name, shortName, type,
                          // Create proper Array with all arguments except first
                          // (receiver).
                          Array.prototype.slice.call(arguments, 1),
                          []));
                  }
                 })(#names[j], shortName, type);
          } else {
            objectClassObject[shortName] =
                (function(name, shortName, type) {
                  return function() {
                    return this.#noSuchMethodName(
                      // Object.noSuchMethodName ignores the explicit receiver
                      // argument. We could pass anything in place of [this].
                      this,
                      #createInvocationMirror(name, shortName, type,
                          // Create proper Array with all arguments.
                          Array.prototype.slice.call(arguments, 0),
                          []));
                  }
                 })(#names[j], shortName, type);
          }
        }
      }''',
        {
          'noSuchMethodName': namer.noSuchMethodName,
          'createInvocationMirror': createInvocationMirror,
          'names': minify ? 'shortNames' : 'longNames',
          'isIntercepted': isIntercepted
        }));

    return statements;
  }
}

/// When pretty printed, this node computes a diff-encoded string for the list
/// of given names.
///
/// See [buildTrivialNsmHandlers].
class _DiffEncodedListOfNames extends jsAst.DeferredString
    implements jsAst.AstContainer {
  String _cachedValue;
  List<jsAst.ArrayInitializer> ast;

  Iterable<jsAst.Node> get containedNodes => ast;

  _DiffEncodedListOfNames(Iterable<Iterable<jsAst.Name>> names) {
    // Store the names in ArrayInitializer nodes to make them discoverable
    // by traversals of the ast.
    ast = names
        .map((Iterable i) => new jsAst.ArrayInitializer(i.toList()))
        .toList();
  }

  void _computeDiffEncodingForList(
      Iterable<jsAst.Name> names, StringBuffer diffEncoding) {
    // Treat string as a number in base 88 with digits in ASCII order from # to
    // z.  The short name sorting is based on length, and uses ASCII order for
    // equal length strings so this means that names are ascending.  The hash
    // character, #, is never given as input, but we need it because it's the
    // implicit leading zero (otherwise we could not code names with leading
    // dollar signs).
    int fromBase88(String x) {
      int answer = 0;
      for (int i = 0; i < x.length; i++) {
        int c = x.codeUnitAt(i);
        // No support for Unicode minified identifiers in JS.
        assert(c >= $$ && c <= $z);
        answer *= 88;
        answer += c - $HASH;
      }
      return answer;
    }

    // Big endian encoding, A = 0, B = 1...
    // A lower case letter terminates the number.
    String toBase26(int x) {
      int c = x;
      var encodingChars = <int>[];
      encodingChars.add($a + (c % 26));
      while (true) {
        c ~/= 26;
        if (c == 0) break;
        encodingChars.add($A + (c % 26));
      }
      return new String.fromCharCodes(encodingChars.reversed.toList());
    }

    // Sort by length, then lexicographic.
    int compare(String a, String b) {
      if (a.length != b.length) return a.length - b.length;
      return a.compareTo(b);
    }

    List<String> shorts = names.map((jsAst.Name name) => name.name).toList()
      ..sort(compare);

    int previous = 0;
    for (String short in shorts) {
      if (short.length <= NsmEmitter.MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING) {
        int base63 = fromBase88(short);
        int diff = base63 - previous;
        previous = base63;
        String base26Diff = toBase26(diff);
        diffEncoding.write(base26Diff);
      } else {
        if (diffEncoding.length != 0) {
          diffEncoding.write(',');
        }
        diffEncoding.write(short);
      }
    }
  }

  String _computeDiffEncoding() {
    StringBuffer buffer = new StringBuffer();
    for (jsAst.ArrayInitializer list in ast) {
      if (buffer.isNotEmpty) {
        // Emit period that resets the diff base to zero when we switch to
        // normal calling convention (this avoids the need to code negative
        // diffs).
        buffer.write(".");
      }
      List<jsAst.Name> names = list.elements;
      _computeDiffEncodingForList(names, buffer);
    }
    return '"${buffer.toString()}"';
  }

  String get value {
    if (_cachedValue == null) {
      _cachedValue = _computeDiffEncoding();
    }

    return _cachedValue;
  }
}
