// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/**
 *******************************************************************************
 * Copyright (C) 2001-2010, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.dev.test.translit;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.text.Replaceable;
import com.ibm.icu.text.ReplaceableString;
import com.ibm.icu.text.Transliterator;

/**
 * @test
 * @summary Round trip test of Transliterator
 */
@RunWith(JUnit4.class)
public class ReplaceableTest extends TestFmwk {
    @Test
    public void Test() {
        check("Lower", "ABCD", "1234");
        check("Upper", "abcd\u00DF", "123455"); // must map 00DF to SS
        check("Title", "aBCD", "1234");
        check("NFC", "A\u0300E\u0300", "13");
        check("NFD", "\u00C0\u00C8", "1122");
        check("*(x) > A $1 B", "wxy", "11223");
        check("*(x)(y) > A $2 B $1 C $2 D", "wxyz", "113322334");
        check("*(x)(y)(z) > A $3 B $2 C $1 D", "wxyzu", "114433225");
        // TODO Revisit the following in 2.6 or later.
        check("*x > a", "xyz", "223"); // expect "123"?
        check("*x > a", "wxy", "113"); // expect "123"?
        check("*x > a", "\uFFFFxy", "_33"); // expect "_23"?
        check("*(x) > A $1 B", "\uFFFFxy", "__223");
    }

    void check(String transliteratorName, String test, String shouldProduceStyles) {
        TestReplaceable tr = new TestReplaceable(test, null);
        String original = tr.toString();

        Transliterator t;
        if (transliteratorName.startsWith("*")) {
            transliteratorName = transliteratorName.substring(1);
            t = Transliterator.createFromRules("test", transliteratorName,
                                               Transliterator.FORWARD);
        } else {
            t = Transliterator.getInstance(transliteratorName);
        }
        t.transliterate(tr);
        String newStyles = tr.getStyles();
        if (!newStyles.equals(shouldProduceStyles)) {
            errln("FAIL Styles: " + transliteratorName + " ( "
                + original + " ) => " + tr.toString() + "; should be {" + shouldProduceStyles + "}!");
        } else {
            logln("OK: " + transliteratorName + " ( " + original + " ) => " + tr.toString());
        }

        if (!tr.hasMetaData() || tr.chars.hasMetaData()
            || tr.styles.hasMetaData()) {
            errln("Fail hasMetaData()");
        }
    }


    /**
     * This is a test class that simulates styled text.
     * It associates a style number (0..65535) with each character,
     * and maintains that style in the normal fashion:
     * When setting text from raw string or characters,<br>
     * Set the styles to the style of the first character replaced.<br>
     * If no characters are replaced, use the style of the previous character.<br>
     * If at start, use the following character<br>
     * Otherwise use NO_STYLE.
     */
    static class TestReplaceable implements Replaceable {
        ReplaceableString chars;
        ReplaceableString styles;

        static final char NO_STYLE = '_';

        static final char NO_STYLE_MARK = 0xFFFF;

        TestReplaceable (String text, String styles) {
            chars = new ReplaceableString(text);
            StringBuffer s = new StringBuffer();
            for (int i = 0; i < text.length(); ++i) {
                if (styles != null && i < styles.length()) {
                    s.append(styles.charAt(i));
                } else {
                    if (text.charAt(i) == NO_STYLE_MARK) {
                        s.append(NO_STYLE);
                    } else {
                        s.append((char) (i + '1'));
                    }
                }
            }
            this.styles = new ReplaceableString(s.toString());
        }

        public String getStyles() {
            return styles.toString();
        }

        @Override
        public String toString() {
            return chars.toString() + "{" + styles.toString() + "}";
        }

        public String substring(int start, int limit) {
            return chars.substring(start, limit);
        }

        @Override
        public int length() {
            return chars.length();
        }

        @Override
        public char charAt(int offset) {
            return chars.charAt(offset);
        }

        @Override
        public int char32At(int offset) {
            return chars.char32At(offset);
        }

        @Override
        public void getChars(int srcStart, int srcLimit, char dst[], int dstStart) {
            chars.getChars(srcStart, srcLimit, dst, dstStart);
        }

        @Override
        public void replace(int start, int limit, String text) {
            if (substring(start,limit).equals(text)) return; // NO ACTION!
            if (DEBUG) System.out.print(Utility.escape(toString() + " -> replace(" + start +
                                            "," + limit + "," + text) + ") -> ");
            chars.replace(start, limit, text);
            fixStyles(start, limit, text.length());
            if (DEBUG) System.out.println(Utility.escape(toString()));
        }

        @Override
        public void replace(int start, int limit, char[] charArray,
                            int charsStart, int charsLen) {
            if (substring(start,limit).equals(new String(charArray, charsStart, charsLen-charsStart))) return; // NO ACTION!
            this.chars.replace(start, limit, charArray, charsStart, charsLen);
            fixStyles(start, limit, charsLen);
        }

        void fixStyles(int start, int limit, int newLen) {
            char newStyle = NO_STYLE;
            if (start != limit && styles.charAt(start) != NO_STYLE) {
                newStyle = styles.charAt(start);
            } else if (start > 0 && charAt(start-1) != NO_STYLE_MARK) {
                newStyle = styles.charAt(start-1);
            } else if (limit < styles.length()) {
                newStyle = styles.charAt(limit);
            }
            // dumb implementation for now.
            StringBuffer s = new StringBuffer();
            for (int i = 0; i < newLen; ++i) {
                // this doesn't really handle an embedded NO_STYLE_MARK
                // in the middle of a long run of characters right -- but
                // that case shouldn't happen anyway
                if (charAt(start+i) == NO_STYLE_MARK) {
                    s.append(NO_STYLE);
                } else {
                    s.append(newStyle);
                }
            }
            styles.replace(start, limit, s.toString());
        }

        @Override
        public void copy(int start, int limit, int dest) {
            chars.copy(start, limit, dest);
            styles.copy(start, limit, dest);
        }

        @Override
        public boolean hasMetaData() {
            return true;
        }

        static final boolean DEBUG = false;
    }

    @org.junit.Test
    public void Test5789() {
        String rules =
            "IETR > IET | \\' R; # (1) do split ietr between t and r\r\n" +
            "I[EH] > I; # (2) friedrich";
        Transliterator trans = Transliterator.createFromRules("foo", rules, Transliterator.FORWARD);
        String result =  trans.transliterate("BLENKDIETRICH");
        assertEquals("Rule breakage", "BLENKDIET'RICH", result);
    }
}
