/*
 * 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 com.google.gwt.emultest.java.lang;

import com.google.gwt.junit.client.GWTTestCase;
import java.util.Arrays;

/**
 * Tests for java.lang.Character.
 */
public class CharacterTest extends GWTTestCase {

  private 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);
    }
  }

  /**
   * Helper class which applies some arbitrary char mutation function
   * to a string and returns it.
   */
  public abstract class Changer {
    String original;

    public Changer(String o) {
      original = o;
    }

    public abstract char change(char c);

    public String changed() {
      StringBuffer buf = new StringBuffer();
      for (int i = 0; i < original.length(); i++) {
        buf.append(change(original.charAt(i)));
      }
      return buf.toString();
    }
  }
  /**
   * Helper class which collects the set of characters which pass some
   * arbitrary boolean function. 
   */
  public abstract class Judge {
    String original;

    public Judge(String o) {
      original = o;
    }

    public String allPass() {
      StringBuffer buf = new StringBuffer();
      for (int i = 0; i < original.length(); i++) {
        if (pass(original.charAt(i))) {
          buf.append(original.charAt(i));
        }
      }
      return buf.toString();
    }

    public abstract boolean pass(char c);
  }

  class LowerCaseJudge extends Judge {
    public LowerCaseJudge(String s) {
      super(s);
    }

    @Override
    public boolean pass(char c) {
      return Character.isLowerCase(c);
    }
  }

  class UpperCaseJudge extends Judge {
    public UpperCaseJudge(String s) {
      super(s);
    }

    @Override
    public boolean pass(char c) {
      return Character.isUpperCase(c);
    }
  }

  public static String allChars;

  public static final int NUM_CHARS_HANDLED = 127;

  static {
    StringBuffer b = new StringBuffer();
    for (char c = 0; c < NUM_CHARS_HANDLED; c++) {
      b.append(c);
    }
    allChars = b.toString();
  }

  Judge digitJudge = new Judge(allChars) {
    @Override
    public boolean pass(char c) {
      return Character.isDigit(c);
    }
  };
  Judge letterJudge = new Judge(allChars) {
    @Override
    public boolean pass(char c) {
      return Character.isLetter(c);
    }
  };
  Judge letterOrDigitJudge = new Judge(allChars) {
    @Override
    public boolean pass(char c) {
      return Character.isLetterOrDigit(c);
    }
  };
  Changer lowerCaseChanger = new Changer(allChars) {
    @Override
    public char change(char c) {
      return Character.toLowerCase(c);
    }
  };
  Judge lowerCaseJudge = new LowerCaseJudge(allChars);
  Judge spaceJudge = new Judge(allChars) {
    @Override
    @SuppressWarnings("deprecation") // Character.isSpace()
    public boolean pass(char c) {
      return Character.isSpace(c); // suppress deprecation
    }
  };
  Changer upperCaseChanger = new Changer(allChars) {
    @Override
    public char change(char c) {
      return Character.toUpperCase(c);
    }
  };
  Judge upperCaseJudge = new UpperCaseJudge(allChars);

  @Override
  public String getModuleName() {
    return "com.google.gwt.emultest.EmulSuite";
  }

  public void testCharValue() {
    assertEquals((char) 32, new Character((char) 32).charValue());
  }

  public void testCodePoint() {
    assertEquals(1, Character.charCount(65));
    assertEquals(2, Character.charCount(Character.MIN_SUPPLEMENTARY_CODE_POINT));
    char[] testPlain = new char[] { 'C', 'A', 'T' };
    char[] testUnicode = new char[] { 'C', '\uD801', '\uDF00', 'T' };
    CharSequence plainSequence = new CharSequenceAdapter(testPlain);
    CharSequence unicodeSequence = new CharSequenceAdapter(testUnicode);
    assertEquals(65, Character.codePointAt(testPlain, 1));
    assertEquals(65, Character.codePointAt(plainSequence, 1));
    assertEquals("codePointAt fails on surrogate pair", 67328,
        Character.codePointAt(testUnicode, 1));
    assertEquals("codePointAt fails on surrogate pair", 67328,
        Character.codePointAt(unicodeSequence, 1));
    assertEquals("codePointAt fails on first char of surrogate pair", 0xD801,
        Character.codePointAt(testUnicode, 1, 2));
    assertEquals(65, Character.codePointBefore(testPlain, 2));
    assertEquals(65, Character.codePointBefore(plainSequence, 2));
    assertEquals("codePointBefore fails on surrogate pair", 67328,
        Character.codePointBefore(testUnicode, 3));
    assertEquals("codePointBefore fails on surrogate pair", 67328,
        Character.codePointBefore(unicodeSequence, 3));
    assertEquals("codePointBefore fails on second char of surrogate pair",
        0xDF00, Character.codePointBefore(testUnicode, 3, 2));
    assertEquals("codePointCount(plain): ", 3,
        Character.codePointCount(testPlain, 0, 3));
    assertEquals("codePointCount(plain): ", 3,
        Character.codePointCount(plainSequence, 0, 3));
    assertEquals("codePointCount(unicode): ", 3,
        Character.codePointCount(testUnicode, 0, 4));
    assertEquals("codePointCount(unicode): ", 3,
        Character.codePointCount(unicodeSequence, 0, 4));
    assertEquals(1, Character.codePointCount(testPlain, 1, 1));
    assertEquals(1, Character.codePointCount(plainSequence, 1, 2));
    assertEquals(1, Character.codePointCount(testUnicode, 1, 2));
    assertEquals(1, Character.codePointCount(unicodeSequence, 1, 3));
    assertEquals(2, Character.codePointCount(testUnicode, 2, 2));
    assertEquals(2, Character.codePointCount(unicodeSequence, 2, 4));
    assertEquals(1, Character.offsetByCodePoints(testUnicode, 0, 4, 0, 1));
    assertEquals(1, Character.offsetByCodePoints(unicodeSequence, 0, 1));
    assertEquals("offsetByCodePoints(1,1): ", 3,
        Character.offsetByCodePoints(testUnicode, 0, 4, 1, 1));
    assertEquals("offsetByCodePoints(1,1): ", 3,
        Character.offsetByCodePoints(unicodeSequence, 1, 1));
    assertEquals("offsetByCodePoints(2,1): ", 3,
        Character.offsetByCodePoints(testUnicode, 0, 4, 2, 1));
    assertEquals("offsetByCodePoints(2,1): ", 3,
        Character.offsetByCodePoints(unicodeSequence, 2, 1));
    assertEquals(4, Character.offsetByCodePoints(testUnicode, 0, 4, 3, 1));
    assertEquals(4, Character.offsetByCodePoints(unicodeSequence, 3, 1));
    assertEquals(1, Character.offsetByCodePoints(testUnicode, 0, 4, 2, -1));
    assertEquals(1, Character.offsetByCodePoints(unicodeSequence, 2, -1));
    assertEquals(1, Character.offsetByCodePoints(testUnicode, 0, 4, 3, -1));
    assertEquals(1, Character.offsetByCodePoints(unicodeSequence, 3, -1));
    assertEquals("offsetByCodePoints(4.-1): ", 3,
        Character.offsetByCodePoints(testUnicode, 0, 4, 4, -1));
    assertEquals("offsetByCodePoints(4.-1): ", 3,
        Character.offsetByCodePoints(unicodeSequence, 4, -1));
    assertEquals(0, Character.offsetByCodePoints(testUnicode, 0, 4, 3, -2));
    assertEquals(0, Character.offsetByCodePoints(unicodeSequence, 3, -2));
    char[] nonBmpChar = new char[] { '\uD800', '\uDF46' };
    assertEquals(0x10346, Character.codePointAt(nonBmpChar, 0));
    assertEquals(1, Character.codePointCount(nonBmpChar, 0, 2));
  }

  public void testCompare() {
    assertTrue(Character.compare('A', 'B') < 0);
    assertTrue(Character.compare('B', 'A') > 0);
    assertEquals(0, Character.compare('C', 'C'));
    assertTrue(Character.compare('\uA001', '\uA000') > 0);
  }

  public void testCompareTo() {
    assertTrue(Character.valueOf('A').compareTo('B') < 0);
    assertTrue(Character.valueOf('B').compareTo('A') > 0);
    assertTrue(Character.valueOf('C').compareTo('C') == 0);
    assertTrue(Character.valueOf('\uA001').compareTo('\uA000') > 0);
  }

  public void testConstructor() {
    assertEquals(new Character((char) 32), new Character(' '));
  }

  public void testDigit() {
    assertEquals("wrong number of digits", 10, digitJudge.allPass().length());
  }
  
  public void testSurrogates() {
    assertFalse(Character.isHighSurrogate('\uDF46'));
    assertTrue(Character.isLowSurrogate('\uDF46'));
    assertTrue(Character.isHighSurrogate('\uD800'));
    assertFalse(Character.isLowSurrogate('\uD800'));
    assertFalse(Character.isHighSurrogate('X'));
    assertFalse(Character.isLowSurrogate('X'));
    assertTrue(Character.isSurrogatePair('\uD800', '\uDF46'));
    assertFalse(Character.isSurrogatePair('\uDF46', '\uD800'));
    assertFalse(Character.isSurrogatePair('A', '\uDF46'));
    assertFalse(Character.isSurrogatePair('\uD800', 'A'));
    char[] chars = Character.toChars(0x10346);
    assertEquals(0xD800, chars[0]);
    assertEquals(0xDF46, chars[1]);
    assertEquals(2, Character.toChars(67328, chars, 0));
    assertEquals(0xD801, chars[0]);
    assertEquals(0xDF00, chars[1]);
    assertEquals(1, Character.toChars(65, chars, 0));
    assertEquals('A', chars[0]);
    assertTrue(Character.isSupplementaryCodePoint(0x10346));
    assertFalse(Character.isSupplementaryCodePoint(65));
    assertTrue(Character.isValidCodePoint(0x10346));
    assertTrue(Character.isValidCodePoint(65));
    assertFalse(Character.isValidCodePoint(0x1FFFFFFF));
    assertEquals(0x10346, Character.toCodePoint('\uD800', '\uDF46'));
  }

  public void testLetter() {
    assertEquals("wrong number of letters", 52, letterJudge.allPass().length());
  }

  public void testLetterOrDigit() {
    assertEquals("wrong number of letters", 62,
        letterOrDigitJudge.allPass().length());
  }

  public void testLowerCase() {
    assertEquals("wrong number of lowercase letters", 26,
        lowerCaseJudge.allPass().length());
    assertEquals("wrong number of lowercase letters after toLowerCase", 52,
        new LowerCaseJudge(lowerCaseChanger.changed()).allPass().length());
  }

  public void testSpace() {
    assertEquals("wrong number of spaces", 5, spaceJudge.allPass().length());
  }

  public void testToFromDigit() {
    for (int i = 0; i < 16; i++) {
      assertEquals(i, Character.digit(Character.forDigit(i, 16), 16));
    }
    assertEquals(1, Character.digit('1', 10));
    assertEquals('9', Character.forDigit(9, 10));
    assertEquals(-1, Character.digit('7', 6));
    assertEquals(-1, Character.digit('8', 8));
    assertEquals(-1, Character.digit('A', 10));
  }

  @SuppressWarnings("deprecation")
  public void testIsSpace() {
    assertFalse(Character.isSpace('a'));
    assertFalse(Character.isSpace('_'));

    assertTrue(Character.isSpace(' '));
    assertTrue(Character.isSpace('\n'));
  }

  public void testIsWhitepace() {
    char[] separators = {
        '\u0020', // SPACE.
        '\u1680', // OGHAM SPACE MARK.
        '\u2000', // EN QUAD.
        '\u2001', // EM QUAD.
        '\u2002', // EN SPACE.
        '\u2003', // EM SPACE.
        '\u2004', // THREE-PER-EM SPACE.
        '\u2005', // FOUR-PER-EM SPACE.
        '\u2006', // SIX-PER-EM SPACE.
        '\u2008', // PUNCTUATION SPACE.
        '\u2009', // THIN SPACE.
        '\u200A', // HAIR SPACE.
        '\u2028', // LINE SEPARATOR.
        '\u2029', // PARAGRAPH SEPARATOR.
        '\u205F', // MEDIUM MATHEMATICAL SPACE.
        '\u3000' // IDEOGRAPHIC SPACE.
    };

    char[] nonBreakingSpaceSeparators = {
        '\u00A0', // NO-BREAK SPACE.
        '\u2007', // FIGURE SPACE.
        '\u202F' // NARROW NO-BREAK SPACE.
    };

    char[] specialCases = {
      '\t', // HORIZONTAL TABULATION.
      '\n', // LINE FEED.
      '\u000B', // VERTICAL TABULATION.
      '\f', // FORM FEED.
      '\r', // CARRIAGE RETURN.
      '\u001C', // FILE SEPARATOR.
      '\u001D', // GROUP SEPARATOR.
      '\u001E', // RECORD SEPARATOR.
      '\u001F' // UNIT SEPARATOR.
    };

    char[] typicalCounterExamples = {
        'a', // LATIN SMALL LETTER A.
        'B', // LATIN CAPITAL LETTER B.
        '_', // LOW LINE.
        '\u2500' // BOX DRAWINGS LIGHT HORIZONTAL.
    };

    int[] supplementaryCounterExamples = {
        0x2070E, // UNICODE HAN CHARACTER 'to castrate a fowl, a capon'.
        0x20731, // UNICODE HAN CHARACTER 'to peel, pare'.
        0x29D98, // UNICODE HAN CHARACTER 'a general name for perch, etc.'.
    };

    // Must match unicode space separator characters.
    for (char c : separators) {
      assertTrue(Character.isWhitespace(c));
      assertTrue(Character.isWhitespace((int) c));
    }

    // But NOT the non-breaking spaces.
    for (char c : nonBreakingSpaceSeparators) {
      assertFalse(Character.isWhitespace(c));
      assertFalse(Character.isWhitespace((int) c));
    }

    // The ASCII legacy cases.
    for (char c : specialCases) {
      assertTrue(Character.isWhitespace(c));
      assertTrue(Character.isWhitespace((int) c));
    }

    // Behave appropriately on other characters, like the alphabet.
    for (char c : typicalCounterExamples) {
      assertFalse(Character.isWhitespace(c));
      assertFalse(Character.isWhitespace((int) c));
    }

    // Support for non-UCS-2 characters.
    for (int c : supplementaryCounterExamples) {
      assertFalse(Character.isWhitespace(c));
    }
  }

  public void test_isTitleCaseC() {
    char[] expectedTitleCaseChars = {
      (char) 0x01c5,
      (char) 0x01c8,
      (char) 0x01cb,
      (char) 0x01f2,
      (char) 0x1f88,
      (char) 0x1f89,
      (char) 0x1f8a,
      (char) 0x1f8b,
      (char) 0x1f8c,
      (char) 0x1f8d,
      (char) 0x1f8e,
      (char) 0x1f8f,
      (char) 0x1f98,
      (char) 0x1f99,
      (char) 0x1f9a,
      (char) 0x1f9b,
      (char) 0x1f9c,
      (char) 0x1f9d,
      (char) 0x1f9e,
      (char) 0x1f9f,
      (char) 0x1fa8,
      (char) 0x1fa9,
      (char) 0x1faa,
      (char) 0x1fab,
      (char) 0x1fac,
      (char) 0x1fad,
      (char) 0x1fae,
      (char) 0x1faf,
      (char) 0x1fbc,
      (char) 0x1fcc,
      (char) 0x1ffc
    };

    char[] foundChars = new char[expectedTitleCaseChars.length];
    int lastFoundCharIndex = 0;
    for (char c = 0; c < 65535; c++) {
      if (Character.isTitleCase(c)) {
        foundChars[lastFoundCharIndex++] = c;
      }
    }

    assertTrue(Arrays.equals(expectedTitleCaseChars, foundChars));
  }

  public void testToString() {
    assertEquals(" ", new Character((char) 32).toString());
  }

  public void testUpperCase() {
    assertEquals("wrong number of uppercase letters", 26,
        upperCaseJudge.allPass().length());
    assertEquals("wrong number of uppercase letters after toUpperCase", 52,
        new UpperCaseJudge(upperCaseChanger.changed()).allPass().length());
  }
  
  public void testValueOf() {
    assertEquals('A', Character.valueOf('A').charValue());
  }
}
