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

part of _js_helper;

// Helper method used by internal libraries.
regExpGetNative(JSSyntaxRegExp regexp) => regexp._nativeRegExp;

/**
 * Returns a native version of the RegExp with the global flag set.
 *
 * The RegExp's `lastIndex` property is zero when it is returned.
 *
 * The returned regexp is shared, and its `lastIndex` property may be
 * modified by other uses, so the returned regexp must be used immediately
 * when it's returned, with no user-provided code run in between.
 */
regExpGetGlobalNative(JSSyntaxRegExp regexp) {
  var regexp = regexp._nativeGlobalVersion;
  JS("void", "#.lastIndex = 0", regexp);
  return regexp;
}

class JSSyntaxRegExp implements RegExp {
  final _nativeRegExp;
  var _nativeGlobalRegExp;
  var _nativeAnchoredRegExp;

  JSSyntaxRegExp(String pattern,
                 { bool multiLine: false,
                   bool caseSensitive: true })
      : this._nativeRegExp =
            makeNative(pattern, multiLine, caseSensitive, false);

  get _nativeGlobalVersion {
    if (_nativeGlobalRegExp != null) return _nativeGlobalRegExp;
    return _nativeGlobalRegExp = makeNative(_pattern,
                                            _isMultiLine,
                                            _isCaseSensitive,
                                            true);
  }

  get _nativeAnchoredVersion {
    if (_nativeAnchoredRegExp != null) return _nativeAnchoredRegExp;
    // An "anchored version" of a regexp is created by adding "|()" to the
    // source. This means that the regexp always matches at the first position
    // that it tries, and you can see if the original regexp matched, or it
    // was the added zero-width match that matched, by looking at the last
    // capture. If it is a String, the match participated, otherwise it didn't.
    return _nativeAnchoredRegExp = makeNative("$_pattern|()",
                                              _isMultiLine,
                                              _isCaseSensitive,
                                              true);
  }

  String get _pattern  => JS("String", "#.source", _nativeRegExp);
  bool get _isMultiLine => JS("bool", "#.multiline", _nativeRegExp);
  bool get _isCaseSensitive => JS("bool", "!#.ignoreCase", _nativeRegExp);

  static makeNative(
      String pattern, bool multiLine, bool caseSensitive, bool global) {
    checkString(pattern);
    String m = multiLine ? 'm' : '';
    String i = caseSensitive ? '' : 'i';
    String g = global ? 'g' : '';
    // We're using the JavaScript's try catch instead of the Dart one
    // to avoid dragging in Dart runtime support just because of using
    // RegExp.
    var regexp = JS('',
        '(function() {'
         'try {'
          'return new RegExp(#, # + # + #);'
         '} catch (e) {'
           'return e;'
         '}'
        '})()', pattern, m, i, g);
    if (JS('bool', '# instanceof RegExp', regexp)) return regexp;
    // The returned value is the JavaScript exception. Turn it into a
    // Dart exception.
    String errorMessage = JS('String', r'String(#)', regexp);
    throw new FormatException(
        "Illegal RegExp pattern: $pattern, $errorMessage");
  }

  Match firstMatch(String str) {
    List<String> m =
        JS('=List|Null', r'#.exec(#)', _nativeRegExp, checkString(str));
    if (m == null) return null;
    return new _MatchImplementation(this, m);
  }

  bool hasMatch(String str) {
    return JS('bool', r'#.test(#)', _nativeRegExp, checkString(str));
  }

  String stringMatch(String str) {
    var match = firstMatch(str);
    if (match != null) return match.group(0);
    return null;
  }

  Iterable<Match> allMatches(String str) {
    checkString(str);
    return new _AllMatchesIterable(this, str);
  }

  Match _execGlobal(String string, int start) {
    Object regexp = _nativeGlobalVersion;
    JS("void", "#.lastIndex = #", regexp, start);
    List match = JS("=List|Null", "#.exec(#)", regexp, string);
    if (match == null) return null;
    return new _MatchImplementation(this, match);
  }

  Match _execAnchored(String string, int start) {
    Object regexp = _nativeAnchoredVersion;
    JS("void", "#.lastIndex = #", regexp, start);
    List match = JS("=List|Null", "#.exec(#)", regexp, string);
    if (match == null) return null;
    // If the last capture group participated, the original regexp did not
    // match at the start position.
    if (match[match.length - 1] != null) return null;
    match.length -= 1;
    return new _MatchImplementation(this, match);
  }

  Match matchAsPrefix(String string, [int start = 0]) {
    if (start < 0 || start > string.length) {
      throw new RangeError.range(start, 0, string.length);
    }
    return _execAnchored(string, start);
  }

  String get pattern => _pattern;
  bool get isMultiLine => _isMultiLine;
  bool get isCaseSensitive => _isCaseSensitive;
}

class _MatchImplementation implements Match {
  final Pattern pattern;
  // Contains a JS RegExp match object.
  // It is an Array of String values with extra "index" and "input" properties.
  final List<String> _match;

  _MatchImplementation(this.pattern, this._match) {
    assert(JS("var", "#.input", _match) is String);
    assert(JS("var", "#.index", _match) is int);
  }

  String get str => JS("String", "#.input", _match);
  int get start => JS("int", "#.index", _match);
  int get end => start + _match[0].length;

  String group(int index) => _match[index];
  String operator [](int index) => group(index);
  int get groupCount => _match.length - 1;

  List<String> groups(List<int> groups) {
    List<String> out = [];
    for (int i in groups) {
      out.add(group(i));
    }
    return out;
  }
}

class _AllMatchesIterable extends IterableBase<Match> {
  final JSSyntaxRegExp _re;
  final String _string;

  const _AllMatchesIterable(this._re, this._string);

  Iterator<Match> get iterator => new _AllMatchesIterator(_re, _string);
}

class _AllMatchesIterator implements Iterator<Match> {
  final JSSyntaxRegExp _regExp;
  String _string;
  Match _current;

  _AllMatchesIterator(this._regExp, this._string);

  Match get current => _current;

  bool moveNext() {
    if (_string == null) return false;
    int index = 0;
    if (_current != null) {
      index = _current.end;
      if (_current.start == index) {
        index++;
      }
    }
    _current = _regExp._execGlobal(_string, index);
    if (_current == null) {
      _string = null;  // Marks iteration as ended.
      return false;
    }
    return true;
  }
}

/** Find the first match of [regExp] in [string] at or after [start]. */
Match firstMatchAfter(JSSyntaxRegExp regExp, String string, int start) {
  return regExp._execGlobal(string, start);
}
