/*
 * 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 static javaemul.internal.InternalPreconditions.checkCriticalArgument;

import java.io.Serializable;
import javaemul.internal.NativeRegExp;
import javaemul.internal.annotations.HasNoSideEffects;

/**
 * Wraps a native <code>char</code> as an object.
 *
 * TODO(jat): many of the classification methods implemented here are not
 * correct in that they only handle ASCII characters, and many other methods
 * are not currently implemented.  I think the proper approach is to introduce * a deferred binding parameter which substitutes an implementation using
 * a fully-correct Unicode character database, at the expense of additional
 * data being downloaded.  That way developers that need the functionality
 * can get it without those who don't need it paying for it.
 *
 * <pre>
 * The following methods are still not implemented -- most would require Unicode
 * character db to be useful:
 *  - digit / is* / to*(int codePoint)
 *  - isDefined(char)
 *  - isIdentifierIgnorable(char)
 *  - isJavaIdentifierPart(char)
 *  - isJavaIdentifierStart(char)
 *  - isJavaLetter(char) -- deprecated, so probably not
 *  - isJavaLetterOrDigit(char) -- deprecated, so probably not
 *  - isISOControl(char)
 *  - isMirrored(char)
 *  - isSpaceChar(char)
 *  - isUnicodeIdentifierPart(char)
 *  - isUnicodeIdentifierStart(char)
 *  - getDirectionality(*)
 *  - getNumericValue(*)
 *  - getType(*)
 *  - reverseBytes(char) -- any use for this at all in the browser?
 *  - toTitleCase(*)
 *  - all the category constants for classification
 *
 * The following do not properly handle characters outside of ASCII:
 *  - digit(char c, int radix)
 *  - isDigit(char c)
 *  - isLetter(char c)
 *  - isLetterOrDigit(char c)
 *  - isLowerCase(char c)
 *  - isUpperCase(char c)
 * </pre>
 */
public final class Character implements Comparable<Character>, Serializable {
  /**
   * Helper class to share code between implementations, by making a char
   * array look like a CharSequence.
   */
  static class CharSequenceAdapter implements CharSequence {
    private char[] charArray;
    private int start;
    private int end;

    public CharSequenceAdapter(char[] charArray) {
      this(charArray, 0, charArray.length);
    }

    public CharSequenceAdapter(char[] charArray, int start, int end) {
      this.charArray = charArray;
      this.start = start;
      this.end = end;
    }

    @Override
    public char charAt(int index) {
      return charArray[index + start];
    }

    @Override
    public int length() {
      return end - start;
    }

    @Override
    public java.lang.CharSequence subSequence(int start, int end) {
      return new CharSequenceAdapter(charArray, this.start + start,
          this.start + end);
    }
  }

  /**
   * Use nested class to avoid clinit on outer.
   */
  private static class BoxedValues {
    // Box values according to JLS - from \u0000 to \u007f
    private static Character[] boxedValues = new Character[128];

    @HasNoSideEffects
    private static Character get(char c) {
      Character result = BoxedValues.boxedValues[c];
      if (result == null) {
        result = BoxedValues.boxedValues[c] = new Character(c);
      }
      return result;
    }
  }

  public static final Class<Character> TYPE = Character.class;
  public static final int MIN_RADIX = 2;

  public static final int MAX_RADIX = 36;
  public static final char MIN_VALUE = '\u0000';

  public static final char MAX_VALUE = '\uFFFF';
  public static final char MIN_SURROGATE = '\uD800';
  public static final char MAX_SURROGATE = '\uDFFF';
  public static final char MIN_LOW_SURROGATE = '\uDC00';
  public static final char MAX_LOW_SURROGATE = '\uDFFF';
  public static final char MIN_HIGH_SURROGATE = '\uD800';

  public static final char MAX_HIGH_SURROGATE = '\uDBFF';
  public static final int MIN_SUPPLEMENTARY_CODE_POINT = 0x10000;
  public static final int MIN_CODE_POINT = 0x0000;

  public static final int MAX_CODE_POINT = 0x10FFFF;

  public static final int SIZE = 16;
  public static final int BYTES = SIZE / Byte.SIZE;

  public static int charCount(int codePoint) {
    return codePoint >= MIN_SUPPLEMENTARY_CODE_POINT ? 2 : 1;
  }

  public static int codePointAt(char[] a, int index) {
    return codePointAt(new CharSequenceAdapter(a), index, a.length);
  }

  public static int codePointAt(char[] a, int index, int limit) {
    return codePointAt(new CharSequenceAdapter(a), index, limit);
  }

  public static int codePointAt(CharSequence seq, int index) {
    return codePointAt(seq, index, seq.length());
  }

  public static int codePointBefore(char[] a, int index) {
    return codePointBefore(new CharSequenceAdapter(a), index, 0);
  }

  public static int codePointBefore(char[] a, int index, int start) {
    return codePointBefore(new CharSequenceAdapter(a), index, start);
  }

  public static int codePointBefore(CharSequence cs, int index) {
    return codePointBefore(cs, index, 0);
  }

  public static int codePointCount(char[] a, int offset, int count) {
    return codePointCount(new CharSequenceAdapter(a), offset, offset + count);
  }

  public static int codePointCount(CharSequence seq, int beginIndex,
      int endIndex) {
    int count = 0;
    for (int idx = beginIndex; idx < endIndex; ) {
      char ch = seq.charAt(idx++);
      if (isHighSurrogate(ch) && idx < endIndex
          && (isLowSurrogate(seq.charAt(idx)))) {
        // skip the second char of surrogate pairs
        ++idx;
      }
      ++count;
    }
    return count;
  }

  public static int compare(char x, char y) {
    // JLS specifies that the chars are promoted to int before subtraction.
    return x - y;
  }

  /*
   * TODO: correct Unicode handling.
   */
  public static int digit(char c, int radix) {
    if (radix < MIN_RADIX || radix > MAX_RADIX) {
      return -1;
    }

    if (c >= '0' && c < '0' + Math.min(radix, 10)) {
      return c - '0';
    }

    // The offset by 10 is to re-base the alpha values
    if (c >= 'a' && c < (radix + 'a' - 10)) {
      return c - 'a' + 10;
    }

    if (c >= 'A' && c < (radix + 'A' - 10)) {
      return c - 'A' + 10;
    }

    return -1;
  }

  public static char forDigit(int digit, int radix) {
    if (radix < MIN_RADIX || radix > MAX_RADIX) {
      return 0;
    }

    if (digit < 0 || digit >= radix) {
      return 0;
    }

    return forDigit(digit);
  }

  public static int hashCode(char c) {
    return c;
  }

  public static boolean isBmpCodePoint(int codePoint) {
    return codePoint >= MIN_VALUE && codePoint <= MAX_VALUE;
  }

  private static NativeRegExp digitRegex;

  /*
   * TODO: correct Unicode handling.
   */
  public static boolean isDigit(char c) {
    if (digitRegex == null) {
      digitRegex = new NativeRegExp("\\d");
    }
    return digitRegex.test(String.valueOf(c));
  }

  public static boolean isHighSurrogate(char ch) {
    return ch >= MIN_HIGH_SURROGATE && ch <= MAX_HIGH_SURROGATE;
  }

  private static NativeRegExp leterRegex;

  /*
   * TODO: correct Unicode handling.
   */
  public static boolean isLetter(char c) {
    if (leterRegex == null) {
      leterRegex = new NativeRegExp("[A-Z]", "i");
    }
    return leterRegex.test(String.valueOf(c));
  }

  private static NativeRegExp isLeterOrDigitRegex;

  /*
   * TODO: correct Unicode handling.
   */
  public static boolean isLetterOrDigit(char c) {
    if (isLeterOrDigitRegex == null) {
      isLeterOrDigitRegex = new NativeRegExp("[A-Z\\d]", "i");
    }
    return isLeterOrDigitRegex.test(String.valueOf(c));
  }

  /*
   * TODO: correct Unicode handling.
   */
  public static boolean isLowerCase(char c) {
    return toLowerCase(c) == c && isLetter(c);
  }

  public static boolean isLowSurrogate(char ch) {
    return ch >= MIN_LOW_SURROGATE && ch <= MAX_LOW_SURROGATE;
  }

  /**
   * Deprecated - see isWhitespace(char).
   */
  @Deprecated
  public static boolean isSpace(char c) {
    switch (c) {
      case ' ':
        return true;
      case '\n':
        return true;
      case '\t':
        return true;
      case '\f':
        return true;
      case '\r':
        return true;
      default:
        return false;
    }
  }

  public static boolean isWhitespace(char ch) {
    return isWhitespace(String.valueOf(ch));
  }

  public static boolean isWhitespace(int codePoint) {
    return isWhitespace(String.fromCodePoint(codePoint));
  }

  private static NativeRegExp whitespaceRegex;

  private static boolean isWhitespace(String ch) {
    if (whitespaceRegex == null) {
      // The regex would just be /\s/, but browsers handle non-breaking spaces inconsistently. Also,
      // the Java definition includes separators.
      whitespaceRegex =
          new NativeRegExp(
              "[\\u1680\\u180E\\u2000-\\u2006\\u2008-\\u200A\\u2028\\u2029\\u205F\\u3000\\uFEFF]"
                  + "|[\\t-\\r ]"
                  + "|[\\x1C-\\x1F]");
    }
    return whitespaceRegex.test(ch);
  }

  public static boolean isSupplementaryCodePoint(int codePoint) {
    return codePoint >= MIN_SUPPLEMENTARY_CODE_POINT && codePoint <= MAX_CODE_POINT;
  }

  public static boolean isSurrogatePair(char highSurrogate, char lowSurrogate) {
    return isHighSurrogate(highSurrogate) && isLowSurrogate(lowSurrogate);
  }

  public static boolean isTitleCase(char c) {
    // https://www.compart.com/en/unicode/category/Lt
    return c != toUpperCase(c) && c != toLowerCase(c);
  }

  /*
   * TODO: correct Unicode handling.
   */
  public static boolean isUpperCase(char c) {
    return toUpperCase(c) == c && isLetter(c);
  }

  public static boolean isValidCodePoint(int codePoint) {
    return codePoint >= MIN_CODE_POINT && codePoint <= MAX_CODE_POINT;
  }

  public static int offsetByCodePoints(char[] a, int start, int count, int index,
      int codePointOffset) {
    return offsetByCodePoints(new CharSequenceAdapter(a, start, count), index,
        codePointOffset);
  }

  public static int offsetByCodePoints(CharSequence seq, int index,
      int codePointOffset) {
    if (codePointOffset < 0) {
      // move backwards
      while (codePointOffset < 0) {
        --index;
        if (Character.isLowSurrogate(seq.charAt(index))
            && Character.isHighSurrogate(seq.charAt(index - 1))) {
          --index;
        }
        ++codePointOffset;
      }
    } else {
      // move forwards
      while (codePointOffset > 0) {
        if (Character.isHighSurrogate(seq.charAt(index))
            && Character.isLowSurrogate(seq.charAt(index + 1))) {
          ++index;
        }
        ++index;
        --codePointOffset;
      }
    }
    return index;
  }

  public static char[] toChars(int codePoint) {
    checkCriticalArgument(codePoint >= 0 && codePoint <= MAX_CODE_POINT);

    if (codePoint >= MIN_SUPPLEMENTARY_CODE_POINT) {
      return new char[] {
          getHighSurrogate(codePoint),
          getLowSurrogate(codePoint),
      };
    } else {
      return new char[] {
          (char) codePoint,
      };
    }
  }

  public static int toChars(int codePoint, char[] dst, int dstIndex) {
    checkCriticalArgument(codePoint >= 0 && codePoint <= MAX_CODE_POINT);

    if (codePoint >= MIN_SUPPLEMENTARY_CODE_POINT) {
      dst[dstIndex++] = getHighSurrogate(codePoint);
      dst[dstIndex] = getLowSurrogate(codePoint);
      return 2;
    } else {
      dst[dstIndex] = (char) codePoint;
      return 1;
    }
  }

  public static int toCodePoint(char highSurrogate, char lowSurrogate) {
    /*
     * High and low surrogate chars have the bottom 10 bits to store the value
     * above MIN_SUPPLEMENTARY_CODE_POINT, so grab those bits and add the
     * offset.
     */
    return MIN_SUPPLEMENTARY_CODE_POINT + ((highSurrogate & 1023) << 10) + (lowSurrogate & 1023);
  }

  public static char toLowerCase(char c) {
    return CaseMapper.charToLowerCase(c);
  }

  public static String toString(char x) {
    return String.valueOf(x);
  }

  public static char toUpperCase(char c) {
    return CaseMapper.charToUpperCase(c);
  }

  public static Character valueOf(char c) {
    if (c < 128) {
      return BoxedValues.get(c);
    }
    return new Character(c);
  }

  static int codePointAt(CharSequence cs, int index, int limit) {
    char hiSurrogate = cs.charAt(index++);
    char loSurrogate;
    if (Character.isHighSurrogate(hiSurrogate) && index < limit
        && Character.isLowSurrogate(loSurrogate = cs.charAt(index))) {
      return Character.toCodePoint(hiSurrogate, loSurrogate);
    }
    return hiSurrogate;
  }

  static int codePointBefore(CharSequence cs, int index, int start) {
    char loSurrogate = cs.charAt(--index);
    char highSurrogate;
    if (isLowSurrogate(loSurrogate) && index > start
        && isHighSurrogate(highSurrogate = cs.charAt(index - 1))) {
      return toCodePoint(highSurrogate, loSurrogate);
    }
    return loSurrogate;
  }

  /**
   * Shared implementation with {@link Long#toString}.
   *
   * @skip
   */
  static char forDigit(int digit) {
    final int overBaseTen = digit - 10;
    return (char) (overBaseTen < 0 ? '0' + digit : 'a' + overBaseTen);
  }

  /**
   * Computes the high surrogate character of the UTF16 representation of a
   * non-BMP code point. See {@link getLowSurrogate}.
   *
   * @param codePoint requested codePoint, required to be >=
   *          MIN_SUPPLEMENTARY_CODE_POINT
   * @return high surrogate character
   */
  static char getHighSurrogate(int codePoint) {
    return (char) (MIN_HIGH_SURROGATE
        + (((codePoint - MIN_SUPPLEMENTARY_CODE_POINT) >> 10) & 1023));
  }

  /**
   * Computes the low surrogate character of the UTF16 representation of a
   * non-BMP code point. See {@link getHighSurrogate}.
   *
   * @param codePoint requested codePoint, required to be >=
   *          MIN_SUPPLEMENTARY_CODE_POINT
   * @return low surrogate character
   */
  static char getLowSurrogate(int codePoint) {
    return (char) (MIN_LOW_SURROGATE + ((codePoint - MIN_SUPPLEMENTARY_CODE_POINT) & 1023));
  }

  private final transient char value;

  public Character(char value) {
    this.value = value;
  }

  public char charValue() {
    return value;
  }

  @Override
  public int compareTo(Character c) {
    return compare(value, c.value);
  }

  @Override
  public boolean equals(Object o) {
    return (o instanceof Character) && (((Character) o).value == value);
  }

  @Override
  public int hashCode() {
    return hashCode(value);
  }

  @Override
  public String toString() {
    return String.valueOf(value);
  }
}
