// 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 nativeRegexp = regexp._nativeGlobalVersion;
  JS("void", "#.lastIndex = 0", nativeRegexp);
  return nativeRegexp;
}

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('JSExtendableArray|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("JSExtendableArray|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("JSExtendableArray|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 input => 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);
}
