// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/*
*******************************************************************************
*   Copyright (C) 2007-2010, International Business Machines
*   Corporation and others.  All Rights Reserved.
*******************************************************************************
*/

package com.ibm.icu.dev.test.bidi;

import java.awt.font.NumericShaper;
import java.awt.font.TextAttribute;
import java.text.AttributedString;

import org.junit.Test;

import com.ibm.icu.text.Bidi;

/**
 * Regression test for java.text.Bidi compatibility
 *
 * @author Matitiahu Allouche
 */

public class TestCompatibility extends BidiFmwk {

    void compareBidi(Bidi bidi, java.text.Bidi jbidi)
    {
        byte paraLevel = bidi.getParaLevel();
        if (bidi.baseIsLeftToRight() != jbidi.baseIsLeftToRight()) {
            errln("Discrepancy in baseIsLeftToRight for case " +
                  "(level=" + paraLevel + "): " +
                  u16ToPseudo(bidi.getTextAsString()) +
                  "\n    bidi: " + bidi.baseIsLeftToRight() +
                  "\n   jbidi: " + jbidi.baseIsLeftToRight());
        }
        if (bidi.getBaseLevel() != jbidi.getBaseLevel()) {
            errln("Discrepancy in getBaseLevel for case " +
                  "(level=" + paraLevel + "): " +
                  u16ToPseudo(bidi.getTextAsString()) +
                  "\n    bidi: " + bidi.getBaseLevel() +
                  "\n   jbidi: " + jbidi.getBaseLevel());
        }
        if (bidi.getLength() != jbidi.getLength()) {
            errln("Discrepancy in getLength for case " +
                  "(level=" + paraLevel + "): " +
                  u16ToPseudo(bidi.getTextAsString()) +
                  "\n    bidi: " + bidi.getLength() +
                  "\n   jbidi: " + jbidi.getLength());
        }
        int len = bidi.getLength();
        for (int i = 0; i < len; i++) {
            if (bidi.getLevelAt(i) != jbidi.getLevelAt(i)) {
                errln("Discrepancy in getLevelAt for offset " + i +
                      " of case " +
                      "(level=" + paraLevel + "): " +
                      u16ToPseudo(bidi.getTextAsString()) +
                      "\n    bidi: " + bidi.getLevelAt(i) +
                      "\n   jbidi: " + jbidi.getLevelAt(i));
            }
        }
        if (bidi.getRunCount() != jbidi.getRunCount()) {
            if (!(len == 0 && jbidi.getRunCount() == 1)) {
                errln("Discrepancy in getRunCount for case " +
                      "(level=" + paraLevel + "): " +
                      u16ToPseudo(bidi.getTextAsString()) +
                      "\n    bidi: " + bidi.getRunCount() +
                      "\n   jbidi: " + jbidi.getRunCount());
            }
        }
        int runCount = bidi.getRunCount();
        for (int i = 0; i < runCount; i++) {
            if (bidi.getRunLevel(i) != jbidi.getRunLevel(i)) {
                errln("Discrepancy in getRunLevel for run " + i +
                      " of case " +
                      "(level=" + paraLevel + "): " +
                      u16ToPseudo(bidi.getTextAsString()) +
                      "\n    bidi: " + bidi.getRunLevel(i) +
                      "\n   jbidi: " + jbidi.getRunLevel(i));
            }
            if (bidi.getRunLimit(i) != jbidi.getRunLimit(i)) {
                errln("Discrepancy in getRunLimit for run " + i +
                      " of case " +
                      "(level=" + paraLevel + "): " +
                      u16ToPseudo(bidi.getTextAsString()) +
                      "\n    bidi: " + bidi.getRunLimit(i) +
                      "\n   jbidi: " + jbidi.getRunLimit(i));
            }
            if (bidi.getRunStart(i) != jbidi.getRunStart(i)) {
                errln("Discrepancy in getRunStart for run " + i +
                      " of case " +
                      "(level=" + paraLevel + "): " +
                      u16ToPseudo(bidi.getTextAsString()) +
                      "\n    bidi: " + bidi.getRunStart(i) +
                      "\n   jbidi: " + jbidi.getRunStart(i));
            }
        }
        if (bidi.isLeftToRight() != jbidi.isLeftToRight()) {
            errln("Discrepancy in isLeftToRight for case " +
                  "(level=" + paraLevel + "): " +
                  u16ToPseudo(bidi.getTextAsString()) +
                  "\n    bidi: " + bidi.isLeftToRight() +
                  "\n   jbidi: " + jbidi.isLeftToRight());
        }
        if (bidi.isMixed() != jbidi.isMixed()) {
            errln("Discrepancy in isMixed for case " +
                  "(level=" + paraLevel + "): " +
                  u16ToPseudo(bidi.getTextAsString()) +
                  "\n    bidi: " + bidi.isMixed() +
                  "\n   jbidi: " + jbidi.isMixed());
        }
        if (bidi.isRightToLeft() != jbidi.isRightToLeft()) {
            errln("Discrepancy in isRightToLeft for case " +
                  "(level=" + paraLevel + "): " +
                  u16ToPseudo(bidi.getTextAsString()) +
                  "\n    bidi: " + bidi.isRightToLeft() +
                  "\n   jbidi: " + jbidi.isRightToLeft());
        }
        char[] text = bidi.getText();
        if (Bidi.requiresBidi(text, 0, text.length) !=
            java.text.Bidi.requiresBidi(text, 0, text.length)) {
            errln("Discrepancy in requiresBidi for case " +
                  u16ToPseudo(bidi.getTextAsString()) +
                  "\n    bidi: " + Bidi.requiresBidi(text, 0, text.length) +
                  "\n   jbidi: " + java.text.Bidi.requiresBidi(text, 0, text.length));
        }
        /* skip the next test, since the toString implementation are
         * not compatible
        if (!bidi.toString().equals(jbidi.toString())) {
            errln("Discrepancy in toString for case " +
                  "(level=" + paraLevel + "): " +
                  u16ToPseudo(bidi.getTextAsString() +
                  "\n    bidi: " + bidi.toString() +
                  "\n   jbidi: " + jbidi.toString()));
        }
         */
    }

    @Test
    public void testCompatibility()
    {
        // This test case does not work well on Java 1.4/1.4.1 environment,
        // because of insufficient Bidi implementation in these versions.
        // This test case also does not work will with Java 1.7 environment,
        // because the changes to the Java Bidi implementation.
        String javaVersion = System.getProperty("java.version");
        if (javaVersion.startsWith("1.4.0") || javaVersion.startsWith("1.4.1") || javaVersion.startsWith("1.7")) {
            logln("\nSkipping TestCompatibility.  The test case is known to fail on Java "
                    + javaVersion + "\n");
            return;
        }
        logln("\nEntering TestCompatibility\n");
        /* check constant field values */
        int val;
        val = Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT;
        val = Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT;
        val = Bidi.DIRECTION_LEFT_TO_RIGHT;
        val = Bidi.DIRECTION_RIGHT_TO_LEFT;
        logln("last val = " + val);

        String[] data = {"",
                         /* the following 2 cases are skipped, because
                          * java.text.Bidi has bugs which cause discrepancies
                         "abc",
                         "ABC",
                          */
                         "abc def",
                         "ABC DEF",
                         "abc 123 def",
                         "ABC 123 DEF",
                         "abc DEF ghi",
                         "abc DEF 123 xyz",
                         "abc GHIJ 12345 def KLM"
                        };
        int dataCnt = data.length;
        Bidi bidi;
        java.text.Bidi jbidi;
        for (int i = 0; i < dataCnt; i++) {
            String src = pseudoToU16(data[i]);
            bidi = new Bidi(src, Bidi.DIRECTION_LEFT_TO_RIGHT);
            jbidi = new java.text.Bidi(src, java.text.Bidi.DIRECTION_LEFT_TO_RIGHT);
            compareBidi(bidi, jbidi);
            bidi = new Bidi(src, Bidi.DIRECTION_RIGHT_TO_LEFT);
            jbidi = new java.text.Bidi(src, java.text.Bidi.DIRECTION_RIGHT_TO_LEFT);
            compareBidi(bidi, jbidi);
            char[] chars = src.toCharArray();
            bidi = new Bidi(chars, 0, null, 0, chars.length, Bidi.DIRECTION_LEFT_TO_RIGHT);
            jbidi = new java.text.Bidi(chars, 0, null, 0, chars.length, java.text.Bidi.DIRECTION_LEFT_TO_RIGHT);
            compareBidi(bidi, jbidi);
        }
        /* check bogus flags */
        bidi = new Bidi("abc", 999);
        assertEquals("\nDirection should be LTR", Bidi.LTR, bidi.getDirection());
        /* check constructor with overriding embeddings */
        bidi = new Bidi(new char[] { 's', 's', 's' }, 0,
                        new byte[] {(byte) -7, (byte) -2, (byte) -3 },
                        0, 3, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
        jbidi = new java.text.Bidi(new char[] { 's', 's', 's' }, 0,
                        new byte[] {(byte) -7, (byte) -2, (byte) -3 },
                        0, 3, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);

        AttributedString as = new AttributedString("HEBREW 123 english MOREHEB");
        as.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_RTL);
        as.addAttribute(TextAttribute.NUMERIC_SHAPING, NumericShaper.getShaper(NumericShaper.ARABIC));
        as.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(1), 0, 26);
        as.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-1), 0, 6);
        as.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(-1), 19, 26);
        bidi = new Bidi(as.getIterator());
        jbidi = new java.text.Bidi(as.getIterator());
        compareBidi(bidi, jbidi);
        String out = bidi.writeReordered(0);
        logln("Output #1 of Bidi(AttributedCharacterIterator): " + out);

        as = new AttributedString("HEBREW 123 english MOREHEB");
        as.addAttribute(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_RTL);
        as.addAttribute(TextAttribute.BIDI_EMBEDDING, new Integer(0), 0, 26);
        bidi = new Bidi(as.getIterator());
        jbidi = new java.text.Bidi(as.getIterator());
        compareBidi(bidi, jbidi);
        out = bidi.writeReordered(0);
        logln("Output #2 of Bidi(AttributedCharacterIterator): " + out);

        as = new AttributedString("HEBREW 123 english MOREHEB");
        bidi = new Bidi(as.getIterator());
        jbidi = new java.text.Bidi(as.getIterator());
        compareBidi(bidi, jbidi);
        out = bidi.writeReordered(0);
        logln("Output #3 of Bidi(AttributedCharacterIterator): " + out);

        char[] text = "abc==(123)==>def".toCharArray();
        bidi = new Bidi(text, 3, null, 0, 10, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
        jbidi = new java.text.Bidi(text, 3, null, 0, 10, java.text.Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
        compareBidi(bidi, jbidi);
        out = bidi.writeReordered(0);
        logln("Output of Bidi(abc==(123)==>def,3,null,0,10, DEFAULT_LTR): " + out);
        bidi = new Bidi(text, 3, null, 0, 10, Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT);
        jbidi = new java.text.Bidi(text, 3, null, 0, 10, java.text.Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT);
        compareBidi(bidi, jbidi);
        out = bidi.writeReordered(0);
        logln("Output of Bidi(abc==(123)==>def,3,null,0,10, DEFAULT_RTL): " + out);
        byte[] levels = new byte[] {0,0,0,-1,-1,-1,0,0,0,0};
        bidi = new Bidi(text, 3, levels, 0, 10, Bidi.DIRECTION_LEFT_TO_RIGHT);
        jbidi = new java.text.Bidi(text, 3, levels, 0, 10, java.text.Bidi.DIRECTION_LEFT_TO_RIGHT);
        compareBidi(bidi, jbidi);
        out = bidi.writeReordered(0);
        logln("Output of Bidi(abc==(123)==>def,3,levels,0,10, LTR): " + out);
        bidi = new Bidi(text, 3, levels, 0, 10, Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT);
        jbidi = new java.text.Bidi(text, 3, levels, 0, 10, java.text.Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT);
        compareBidi(bidi, jbidi);
        out = bidi.writeReordered(0);
        logln("Output of Bidi(abc==(123)==>def,3,levels,0,10, DEFAULT_RTL): " + out);

        /* test reorderVisually */
        byte[] myLevels = new byte[] {1,2,0,1,2,1,2,0,1,2};
        Character[] objects = new Character[10];
        levels = new byte[objects.length];
        for (int i = 0; i < objects.length; i++) {
            objects[i] = new Character((char)('a'+i));
            levels[i] = myLevels[i];
        }
        Bidi.reorderVisually(levels, 3, objects, 3, 7);
        String strbidi = "";
        for (int i = 0; i < objects.length; i++) {
            strbidi += objects[i].toString();
        }
        for (int i = 0; i < objects.length; i++) {
            objects[i] = new Character((char)('a'+i));
            levels[i] = myLevels[i];
        }
        java.text.Bidi.reorderVisually(levels, 3, objects, 3, 7);
        String strjbidi = "";
        for (int i = 0; i < objects.length; i++) {
            strjbidi += objects[i].toString();
        }
        if (!strjbidi.equals(strbidi)) {
            errln("Discrepancy in reorderVisually " +
                  "\n      bidi: " + strbidi +
                  "\n     jbidi: " + strjbidi);
        } else {
            logln("Correct match in reorderVisually " +
                  "\n      bidi: " + strbidi +
                  "\n     jbidi: " + strjbidi);
        }

        logln("\nExiting TestCompatibility\n");
    }
}
