/*
 * Copyright 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package java.lang;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Comparator;
import java.util.Locale;

import javaemul.internal.HashCodes;
import javaemul.internal.InternalPreconditions;
import javaemul.internal.StringHelper;
import javaemul.internal.annotations.DoNotInline;

/**
 * Intrinsic string class.
 */

public final class String implements Comparable<String>, CharSequence,
    Serializable {
  /* TODO(jat): consider whether we want to support the following methods;
   *
   * <ul>
   * <li>deprecated methods dealing with bytes (I assume not since I can't see
   * much use for them)
   * <ul>
   * <li>String(byte[] ascii, int hibyte)
   * <li>String(byte[] ascii, int hibyte, int offset, int count)
   * <li>getBytes(int srcBegin, int srcEnd, byte[] dst, int dstBegin)
   * </ul>
   * <li>methods which in JS will essentially do nothing or be the same as other
   * methods
   * <ul>
   * <li>copyValueOf(char[] data)
   * <li>copyValueOf(char[] data, int offset, int count)
   * </ul>
   * <li>methods added in Java 1.6 (the issue is how will it impact users
   * building against Java 1.5)
   * <ul>
   * <li>isEmpty()
   * </ul>
   * <li>other methods which are not straightforward in JS
   * <ul>
   * <li>format(String format, Object... args)
   * </ul>
   * </ul>
   *
   * <p>Also, in general, we need to improve our support of non-ASCII characters. The
   * problem is that correct support requires large tables, and we don't want to
   * make users who aren't going to use that pay for it. There are two ways to do
   * that:
   * <ol>
   * <li>construct the tables in such a way that if the corresponding method is
   * not called the table will be elided from the output.
   * <li>provide a deferred binding target selecting the level of compatibility
   * required. Those that only need ASCII (or perhaps a different relatively small
   * subset such as Latin1-5) will not pay for large tables, even if they do call
   * toLowercase(), for example.
   * </ol>
   *
   * Also, if we ever add multi-locale support, there are a number of other
   * methods such as toLowercase(Locale) we will want to consider supporting. This
   * is probably rare, but there will be some apps (such as a translation tool)
   * which cannot be written without this support.
   *
   * Another category of incomplete support is that we currently just use the JS
   * regex support, which is not exactly the same as Java. We should support Java
   * syntax by mapping it into equivalent JS patterns, or emulating them.
   *
   * IMPORTANT NOTE: if newer JREs add new interfaces to String, please update
   * {@link Devirtualizer} and {@link JavaResourceBase}
   */
  public static final Comparator<String> CASE_INSENSITIVE_ORDER = new Comparator<String>() {
    @Override
    public int compare(String a, String b) {
      return a.compareToIgnoreCase(b);
    }
  };

  // names for standard character sets that are supported
  private static final String CHARSET_8859_1 = "ISO-8859-1";
  private static final String CHARSET_LATIN1 = "ISO-LATIN-1";
  private static final String CHARSET_UTF8 = "UTF-8";

  public static String copyValueOf(char[] v) {
    return valueOf(v);
  }

  public static String copyValueOf(char[] v, int offset, int count) {
    return valueOf(v, offset, count);
  }

  public static String valueOf(boolean x) {
    return "" + x;
  }

  public static native String valueOf(char x) /*-{
    return String.fromCharCode(x);
  }-*/;

  public static String valueOf(char x[], int offset, int count) {
    int end = offset + count;
    InternalPreconditions.checkStringBounds(offset, end, x.length);
    return StringHelper.valueOf(x, offset, end);
  }

  public static String valueOf(char[] x) {
    return StringHelper.valueOf(x, 0, x.length);
  }

  public static String valueOf(double x) {
    return "" + x;
  }

  public static String valueOf(float x) {
    return "" + x;
  }

  public static String valueOf(int x) {
    return "" + x;
  }

  public static String valueOf(long x) {
    return "" + x;
  }

  public static String valueOf(Object x) {
    return "" + x;
  }

  // CHECKSTYLE_OFF: This class has special needs.

  /**
   * @skip
   */
  static String[] __createArray(int numElements) {
    return new String[numElements];
  }

  static native String __substr(String str, int beginIndex, int len) /*-{
    return str.substr(beginIndex, len);
  }-*/;

  /**
   * This method converts Java-escaped dollar signs "\$" into JavaScript-escaped
   * dollar signs "$$", and removes all other lone backslashes, which serve as
   * escapes in Java but are passed through literally in JavaScript.
   *
   * @skip
   */
  static String __translateReplaceString(String replaceStr) {
    int pos = 0;
    while (0 <= (pos = replaceStr.indexOf("\\", pos))) {
      if (replaceStr.charAt(pos + 1) == '$') {
        replaceStr = replaceStr.substring(0, pos) + "$"
            + replaceStr.substring(++pos);
      } else {
        replaceStr = replaceStr.substring(0, pos) + replaceStr.substring(++pos);
      }
    }
    return replaceStr;
  }

  /**
   * @skip
   */
  static String _String() {
    return "";
  }

  /**
   * @skip
   */
  static String _String(byte[] bytes) {
    return _String(bytes, 0, bytes.length);
  }

  /**
   * @skip
   */
  static String _String(byte[] bytes, int ofs, int len) {
    return utf8ToString(bytes, ofs, len);
  }

  /**
   * @skip
   */
  static String _String(byte[] bytes, int ofs, int len, String charset)
      throws UnsupportedEncodingException {
    if (CHARSET_UTF8.equalsIgnoreCase(charset)) {
      return utf8ToString(bytes, ofs, len);
    } else if (CHARSET_8859_1.equalsIgnoreCase(charset) || CHARSET_LATIN1.equalsIgnoreCase(charset)) {
      return latin1ToString(bytes, ofs, len);
    } else {
      throw new UnsupportedEncodingException("Charset " + charset
          + " not supported");
    }
  }

  /**
   * @skip
   */
  static String _String(byte[] bytes, String charsetName)
      throws UnsupportedEncodingException {
    return _String(bytes, 0, bytes.length, charsetName);
  }

  /**
   * @skip
   */
  static String _String(char value[]) {
    return valueOf(value);
  }

  /**
   * @skip
   */
  static String _String(char value[], int offset, int count) {
    return valueOf(value, offset, count);
  }

  /**
   * @skip
   */
  static String _String(int[] codePoints, int offset, int count) {
    char[] chars = new char[count * 2];
    int charIdx = 0;
    while (count-- > 0) {
      charIdx += Character.toChars(codePoints[offset++], chars, charIdx);
    }
    return valueOf(chars, 0, charIdx);
  }

  /**
   * @skip
   */
  static String _String(String other) {
    return other;
  }

  /**
   * @skip
   */
  static String _String(StringBuffer sb) {
    return valueOf(sb);
  }

  /**
   * @skip
   */
  static String _String(StringBuilder sb) {
    return valueOf(sb);
  }

  // CHECKSTYLE_ON

  private static native int compareTo(String thisStr, String otherStr) /*-{
    if (thisStr == otherStr) {
      return 0;
    }
    return thisStr < otherStr ? -1 : 1;
  }-*/;

  /**
   * Encode a single character in UTF8.
   *
   * @param bytes byte array to store character in
   * @param ofs offset into byte array to store first byte
   * @param codePoint character to encode
   * @return number of bytes consumed by encoding the character
   * @throws IllegalArgumentException if codepoint >= 2^26
   */
  private static int encodeUtf8(byte[] bytes, int ofs, int codePoint) {
    if (codePoint < (1 << 7)) {
      bytes[ofs] = (byte) (codePoint & 127);
      return 1;
    } else if (codePoint < (1 << 11)) {
      // 110xxxxx 10xxxxxx
      bytes[ofs++] = (byte) (((codePoint >> 6) & 31) | 0xC0);
      bytes[ofs] = (byte) ((codePoint & 63) | 0x80);
      return 2;
    } else if (codePoint < (1 << 16)) {
      // 1110xxxx 10xxxxxx 10xxxxxx
      bytes[ofs++] = (byte) (((codePoint >> 12) & 15) | 0xE0);
      bytes[ofs++] = (byte) (((codePoint >> 6) & 63) | 0x80);
      bytes[ofs] = (byte) ((codePoint & 63) | 0x80);
      return 3;
    } else if (codePoint < (1 << 21)) {
      // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
      bytes[ofs++] = (byte) (((codePoint >> 18) & 7) | 0xF0);
      bytes[ofs++] = (byte) (((codePoint >> 12) & 63) | 0x80);
      bytes[ofs++] = (byte) (((codePoint >> 6) & 63) | 0x80);
      bytes[ofs] = (byte) ((codePoint & 63) | 0x80);
      return 4;
    } else if (codePoint < (1 << 26)) {
      // 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
      bytes[ofs++] = (byte) (((codePoint >> 24) & 3) | 0xF8);
      bytes[ofs++] = (byte) (((codePoint >> 18) & 63) | 0x80);
      bytes[ofs++] = (byte) (((codePoint >> 12) & 63) | 0x80);
      bytes[ofs++] = (byte) (((codePoint >> 6) & 63) | 0x80);
      bytes[ofs] = (byte) ((codePoint & 63) | 0x80);
      return 5;
    }
    throw new IllegalArgumentException("Character out of range: " + codePoint);
  }

  private static String fromCodePoint(int codePoint) {
    if (codePoint >= Character.MIN_SUPPLEMENTARY_CODE_POINT) {
      char hiSurrogate = Character.getHighSurrogate(codePoint);
      char loSurrogate = Character.getLowSurrogate(codePoint);
      return String.valueOf(hiSurrogate)
          + String.valueOf(loSurrogate);
    } else {
      return String.valueOf((char) codePoint);
    }
  }

  private static byte[] getBytesLatin1(String str) {
    int n = str.length();
    byte[] bytes = new byte[n];
    for (int i = 0; i < n; ++i) {
      bytes[i] = (byte) (str.charAt(i) & 255);
    }
    return bytes;
  }

  private static byte[] getBytesUtf8(String str) {
    // TODO(jat): consider using unescape(encodeURIComponent(bytes)) instead
    int n = str.length();
    int byteCount = 0;
    for (int i = 0; i < n; ) {
      int ch = str.codePointAt(i);
      i += Character.charCount(ch);
      if (ch < (1 << 7)) {
        byteCount++;
      } else if (ch < (1 << 11)) {
        byteCount += 2;
      } else if (ch < (1 << 16)) {
        byteCount += 3;
      } else if (ch < (1 << 21)) {
        byteCount += 4;
      } else if (ch < (1 << 26)) {
        byteCount += 5;
      }
    }
    byte[] bytes = new byte[byteCount];
    int out = 0;
    for (int i = 0; i < n; ) {
      int ch = str.codePointAt(i);
      i += Character.charCount(ch);
      out += encodeUtf8(bytes, out, ch);
    }
    return bytes;
  }

  private static String latin1ToString(byte[] bytes, int ofs, int len) {
    char[] chars = new char[len];
    for (int i = 0; i < len; ++i) {
      chars[i] = (char) (bytes[ofs + i] & 255);
    }
    return valueOf(chars);
  }

  private static String utf8ToString(byte[] bytes, int ofs, int len) {
    // TODO(jat): consider using decodeURIComponent(escape(bytes)) instead
    int charCount = 0;
    for (int i = 0; i < len; ) {
      ++charCount;
      byte ch = bytes[ofs + i];
      if ((ch & 0xC0) == 0x80) {
        throw new IllegalArgumentException("Invalid UTF8 sequence");
      } else if ((ch & 0x80) == 0) {
        ++i;
      } else if ((ch & 0xE0) == 0xC0) {
        i += 2;
      } else if ((ch & 0xF0) == 0xE0) {
        i += 3;
      } else if ((ch & 0xF8) == 0xF0) {
        i += 4;
      } else {
        // no 5+ byte sequences since max codepoint is less than 2^21
        throw new IllegalArgumentException("Invalid UTF8 sequence");
      }
      if (i > len) {
        throw new IndexOutOfBoundsException("Invalid UTF8 sequence");
      }
    }
    char[] chars = new char[charCount];
    int outIdx = 0;
    int count = 0;
    for (int i = 0; i < len; ) {
      int ch = bytes[ofs + i++];
      if ((ch & 0x80) == 0) {
        count = 1;
        ch &= 127;
      } else if ((ch & 0xE0) == 0xC0) {
        count = 2;
        ch &= 31;
      } else if ((ch & 0xF0) == 0xE0) {
        count = 3;
        ch &= 15;
      } else if ((ch & 0xF8) == 0xF0) {
        count = 4;
        ch &= 7;
      } else if ((ch & 0xFC) == 0xF8) {
        count = 5;
        ch &= 3;
      }
      while (--count > 0) {
        byte b = bytes[ofs + i++];
        if ((b & 0xC0) != 0x80) {
          throw new IllegalArgumentException("Invalid UTF8 sequence at "
              + (ofs + i - 1) + ", byte=" + Integer.toHexString(b));
        }
        ch = (ch << 6) | (b & 63);
      }
      outIdx += Character.toChars(ch, chars, outIdx);
    }
    return valueOf(chars);
  }

  public String() {
    // magic delegation to _String
    _String();
  }

  public String(byte[] bytes) {
    // magic delegation to _String
    _String(bytes);
  }

  public String(byte[] bytes, int ofs, int len) {
    // magic delegation to _String
    _String(bytes, ofs, len);
  }

  public String(byte[] bytes, int ofs, int len, String charsetName)
      throws UnsupportedEncodingException {
    // magic delegation to _String
    _String(bytes, ofs, len, charsetName);
  }

  public String(byte[] bytes, String charsetName)
      throws UnsupportedEncodingException {
    // magic delegation to _String
    _String(bytes, charsetName);
  }

  public String(char value[]) {
    // magic delegation to _String
    _String(value);
  }

  public String(char value[], int offset, int count) {
    // magic delegation to _String
    _String(value, offset, count);
  }

  public String(int codePoints[], int offset, int count) {
    // magic delegation to _String
    _String(codePoints, offset, count);
  }

  public String(String other) {
    // magic delegation to _String
    _String(other);
  }

  public String(StringBuffer sb) {
    // magic delegation to _String
    _String(sb);
  }

  public String(StringBuilder sb) {
    // magic delegation to _String
    _String(sb);
  }

  @Override
  public native char charAt(int index) /*-{
    return this.charCodeAt(index);
  }-*/;

  public int codePointAt(int index) {
    return Character.codePointAt(this, index, length());
  }

  public int codePointBefore(int index) {
    return Character.codePointBefore(this, index, 0);
  }

  public int codePointCount(int beginIndex, int endIndex) {
    return Character.codePointCount(this, beginIndex, endIndex);
  }

  @Override
  public int compareTo(String other) {
    return compareTo(this, other);
  }

  public int compareToIgnoreCase(String other) {
    return compareTo(toLowerCase(), other.toLowerCase());
  }

  public native String concat(String str) /*-{
    return this + str;
  }-*/;

  public boolean contains(CharSequence s) {
    return indexOf(s.toString()) != -1;
  }

  public boolean contentEquals(CharSequence cs) {
    return equals(cs.toString());
  }

  public boolean contentEquals(StringBuffer sb) {
    return equals(sb.toString());
  }

  public boolean endsWith(String suffix) {
    // If IE8 supported negative start index, we could have just used "-suffixlength".
    int suffixlength = suffix.length();
    return __substr(this, length() - suffixlength, suffixlength).equals(suffix);
  }

  // Marked with @DoNotInline because we don't have static eval for "==" yet.
  @DoNotInline
  @Override
  public boolean equals(Object other) {
    // Java equality is translated into triple equality which is a quick to compare strings for
    // equality without any instanceOf checks.
    return this == other;
  }

  public native boolean equalsIgnoreCase(String other) /*-{
    if (other == null) {
      return false;
    }
    if (this == other) {
      return true;
    }
    return (this.length == other.length) && (this.toLowerCase() == other.toLowerCase());
  }-*/;

  public byte[] getBytes() {
    // default character set for GWT is UTF-8
    return getBytesUtf8(this);
  }

  public byte[] getBytes(String charSet) throws UnsupportedEncodingException {
    if (CHARSET_UTF8.equalsIgnoreCase(charSet)) {
      return getBytesUtf8(this);
    }
    if (CHARSET_8859_1.equalsIgnoreCase(charSet) || CHARSET_LATIN1.equalsIgnoreCase(charSet)) {
      return getBytesLatin1(this);
    }
    throw new UnsupportedEncodingException(charSet + " is not supported");
  }

  public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) {
    for (int srcIdx = srcBegin; srcIdx < srcEnd; ++srcIdx) {
      dst[dstBegin++] = charAt(srcIdx);
    }
  }

  /**
   * Magic; JSODevirtualizer will use this implementation.<p>
   *
   * Each class gets a synthetic stubs for getClass at AST construction time with the exception of
   * Object, JavaScriptObject and subclasses and String; see {@link GwtAstBuilder.createMembers()}.
   * <p>
   *
   * These stubs are replaced in {@link ReplaceGetClassOverrides} by an access to field __clazz
   * which is initialized in each class prototype to point to the class literal. String is
   * implemented as a plain JavaScript string hence lacking said field.<p>
   *
   * The devirtualizer {@code JsoDevirtualizer} will insert a trampoline that uses this
   * implementation.
   */
  @Override
  public Class<? extends Object> getClass() {
    return String.class;
  }

  @Override
  public int hashCode() {
    return HashCodes.hashCodeForString(this);
  }

  public int indexOf(int codePoint) {
    return indexOf(fromCodePoint(codePoint));
  }

  public int indexOf(int codePoint, int startIndex) {
    return indexOf(fromCodePoint(codePoint), startIndex);
  }

  public native int indexOf(String str) /*-{
    return this.indexOf(str);
  }-*/;

  public native int indexOf(String str, int startIndex) /*-{
    return this.indexOf(str, startIndex);
  }-*/;

  public native String intern() /*-{
    return this;
  }-*/;

  public native boolean isEmpty() /*-{
    return !this.length;
  }-*/;

  public int lastIndexOf(int codePoint) {
    return lastIndexOf(fromCodePoint(codePoint));
  }

  public int lastIndexOf(int codePoint, int startIndex) {
    return lastIndexOf(fromCodePoint(codePoint), startIndex);
  }

  public native int lastIndexOf(String str) /*-{
    return this.lastIndexOf(str);
  }-*/;

  public native int lastIndexOf(String str, int start) /*-{
    return this.lastIndexOf(str, start);
  }-*/;

  @Override
  public native int length() /*-{
    return this.length;
  }-*/;

  /**
   * Regular expressions vary from the standard implementation. The
   * <code>regex</code> parameter is interpreted by JavaScript as a JavaScript
   * regular expression. For consistency, use only the subset of regular
   * expression syntax common to both Java and JavaScript.
   *
   * TODO(jat): properly handle Java regex syntax
   */
  public native boolean matches(String regex) /*-{
    // We surround the regex with '^' and '$' because it must match
    // the entire string.
    return new RegExp('^(' + regex + ')$').test(this);
  }-*/;

  public int offsetByCodePoints(int index, int codePointOffset) {
    return Character.offsetByCodePoints(this, index, codePointOffset);
  }

  public boolean regionMatches(boolean ignoreCase, int toffset, String other,
      int ooffset, int len) {
    if (other == null) {
      throw new NullPointerException();
    }
    if (toffset < 0 || ooffset < 0 || len <= 0) {
      return false;
    }
    if (toffset + len > this.length() || ooffset + len > other.length()) {
      return false;
    }

    String left = __substr(this, toffset, len);
    String right = __substr(other, ooffset, len);
    return ignoreCase ? left.equalsIgnoreCase(right) : left.equals(right);
  }

  public boolean regionMatches(int toffset, String other, int ooffset, int len) {
    return regionMatches(false, toffset, other, ooffset, len);
  }

  public native String replace(char from, char to) /*-{
    // Translate 'from' into unicode escape sequence (\\u and a four-digit hexadecimal number).
    // Escape sequence replacement is used instead of a string literal replacement
    // in order to escape regexp special characters (e.g. '.').
    var hex = @java.lang.Integer::toHexString(I)(from);
    var regex = "\\u" + "0000".substring(hex.length) + hex;
    return this.replace(RegExp(regex, "g"), String.fromCharCode(to));
  }-*/;

  public String replace(CharSequence from, CharSequence to) {
    // Implementation note: This uses a regex replacement instead of
    // a string literal replacement because Safari does not
    // follow the spec for "$$" in the replacement string: it
    // will insert a literal "$$". IE and Firefox, meanwhile,
    // treat "$$" as "$".

    // Escape regex special characters from literal replacement string.
    String regex = from.toString().replaceAll("([/\\\\\\.\\*\\+\\?\\|\\(\\)\\[\\]\\{\\}$^])", "\\\\$1");
    // Escape $ since it is for match backrefs and \ since it is used to escape
    // $.
    String replacement = to.toString().replaceAll("\\\\", "\\\\\\\\").replaceAll("\\$", "\\\\$");

    return replaceAll(regex, replacement);
  }

  /**
   * Regular expressions vary from the standard implementation. The
   * <code>regex</code> parameter is interpreted by JavaScript as a JavaScript
   * regular expression. For consistency, use only the subset of regular
   * expression syntax common to both Java and JavaScript.
   *
   * TODO(jat): properly handle Java regex syntax
   */
  public native String replaceAll(String regex, String replace) /*-{
    replace = @java.lang.String::__translateReplaceString(Ljava/lang/String;)(replace);
    return this.replace(RegExp(regex, "g"), replace);
  }-*/;

  /**
   * Regular expressions vary from the standard implementation. The
   * <code>regex</code> parameter is interpreted by JavaScript as a JavaScript
   * regular expression. For consistency, use only the subset of regular
   * expression syntax common to both Java and JavaScript.
   *
   * TODO(jat): properly handle Java regex syntax
   */
  public native String replaceFirst(String regex, String replace) /*-{
    replace = @java.lang.String::__translateReplaceString(Ljava/lang/String;)(replace);
    return this.replace(RegExp(regex), replace);
  }-*/;

  /**
   * Regular expressions vary from the standard implementation. The
   * <code>regex</code> parameter is interpreted by JavaScript as a JavaScript
   * regular expression. For consistency, use only the subset of regular
   * expression syntax common to both Java and JavaScript.
   */
  public String[] split(String regex) {
    return split(regex, 0);
  }

  /**
   * Regular expressions vary from the standard implementation. The
   * <code>regex</code> parameter is interpreted by JavaScript as a JavaScript
   * regular expression. For consistency, use only the subset of regular
   * expression syntax common to both Java and JavaScript.
   *
   * TODO(jat): properly handle Java regex syntax
   */
  public native String[] split(String regex, int maxMatch) /*-{
    // The compiled regular expression created from the string
    var compiled = new RegExp(regex, "g");
    // the Javascipt array to hold the matches prior to conversion
    var out = [];
    // how many matches performed so far
    var count = 0;
    // The current string that is being matched; trimmed as each piece matches
    var trail = this;
    // used to detect repeated zero length matches
    // Must be null to start with because the first match of "" makes no
    // progress by intention
    var lastTrail = null;
    // We do the split manually to avoid Javascript incompatibility
    while (true) {
      // None of the information in the match returned are useful as we have no
      // subgroup handling
      var matchObj = compiled.exec(trail);
      if (matchObj == null || trail == "" || (count == (maxMatch - 1) && maxMatch > 0)) {
        out[count] = trail;
        break;
      } else {
        out[count] = trail.substring(0, matchObj.index);
        trail = trail.substring(matchObj.index + matchObj[0].length, trail.length);
        // Force the compiled pattern to reset internal state
        compiled.lastIndex = 0;
        // Only one zero length match per character to ensure termination
        if (lastTrail == trail) {
          out[count] = trail.substring(0, 1);
          trail = trail.substring(1);
        }
        lastTrail = trail;
        count++;
      }
    }
    // all blank delimiters at the end are supposed to disappear if maxMatch == 0;
    // however, if the input string is empty, the output should consist of a
    // single empty string
    if (maxMatch == 0 && this.length > 0) {
      var lastNonEmpty = out.length;
      while (lastNonEmpty > 0 && out[lastNonEmpty - 1] == "") {
        --lastNonEmpty;
      }
      if (lastNonEmpty < out.length) {
        out.splice(lastNonEmpty, out.length - lastNonEmpty);
      }
    }
    var jr = @java.lang.String::__createArray(I)(out.length);
    for ( var i = 0; i < out.length; ++i) {
      jr[i] = out[i];
    }
    return jr;
  }-*/;

  public boolean startsWith(String prefix) {
    return startsWith(prefix, 0);
  }

  public boolean startsWith(String prefix, int toffset) {
    return toffset >= 0 && __substr(this, toffset, prefix.length()).equals(prefix);
  }

  @Override
  public CharSequence subSequence(int beginIndex, int endIndex) {
    return this.substring(beginIndex, endIndex);
  }

  public String substring(int beginIndex) {
    return __substr(this, beginIndex, this.length() - beginIndex);
  }

  public String substring(int beginIndex, int endIndex) {
    return __substr(this, beginIndex, endIndex - beginIndex);
  }

  public char[] toCharArray() {
    int n = this.length();
    char[] charArr = new char[n];
    getChars(0, n, charArr, 0);
    return charArr;
  }

  /**
   * Transforms the String to lower-case in a locale insensitive way.
   * <p>
   * Unlike JRE, we don't do locale specific transformation by default. That is backward compatible
   * for GWT and in most of the cases that is what the developer actually wants. If you want to make
   * a transformation based on native locale of the browser, you can do
   * {@code toLowerCase(Locale.getDefault())} instead.
   */
  public native String toLowerCase() /*-{
    return this.toLowerCase();
  }-*/;

  /**
   * Transforms the String to lower-case based on the native locale of the browser.
   */
  private native String toLocaleLowerCase() /*-{
    return this.toLocaleLowerCase();
  }-*/;

  /**
   * If provided {@code locale} is {@link Locale#getDefault()}, uses javascript's
   * {@code toLocaleLowerCase} to do a locale specific transformation. Otherwise, it will fallback
   * to {@code toLowerCase} which performs the right thing for the limited set of Locale's
   * predefined in GWT Locale emulation.
   */
  public String toLowerCase(Locale locale) {
    return locale == Locale.getDefault() ? toLocaleLowerCase() : toLowerCase();
  }

  // See the notes in lowerCase pair.
  public native String toUpperCase() /*-{
    return this.toUpperCase();
  }-*/;

  // See the notes in lowerCase pair.
  private native String toLocaleUpperCase() /*-{
    return this.toLocaleUpperCase();
  }-*/;

  // See the notes in lowerCase pair.
  public String toUpperCase(Locale locale) {
    return locale == Locale.getDefault() ? toLocaleUpperCase() : toUpperCase();
  }

  @Override
  public String toString() {
    /*
     * Magic: this method is only used during compiler optimizations; the generated JS will instead alias
     * this method to the native String.prototype.toString() function.
     */
    return this;
  }

  public String trim() {
    int length = length();
    int start = 0;
    while (start < length && charAt(start) <= ' ') {
      start++;
    }
    int end = length;
    while (end > start && charAt(end - 1) <= ' ') {
      end--;
    }
    return start > 0 || end < length ? substring(start, end) : this;
  }
}
