/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * 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 android.text.cts;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import android.icu.util.ULocale;
import android.text.BidiFormatter;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextDirectionHeuristics;
import android.text.style.RelativeSizeSpan;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

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

import java.util.Locale;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class BidiFormatterTest {

    private static final BidiFormatter LTR_FMT = BidiFormatter.getInstance(false /* LTR context */);
    private static final BidiFormatter RTL_FMT = BidiFormatter.getInstance(true /* RTL context */);

    private static final BidiFormatter LTR_FMT_EXIT_RESET =
            new BidiFormatter.Builder(false /* LTR context */).stereoReset(false).build();
    private static final BidiFormatter RTL_FMT_EXIT_RESET =
            new BidiFormatter.Builder(true /* RTL context */).stereoReset(false).build();

    private static final String EN = "abba";
    private static final String HE = "\u05E0\u05E1";

    private static final String LRM = "\u200E";
    private static final String RLM = "\u200F";
    private static final String LRE = "\u202A";
    private static final String RLE = "\u202B";
    private static final String PDF = "\u202C";

    @Test
    public void testIsRtlContext() {
        assertEquals(false, LTR_FMT.isRtlContext());
        assertEquals(true, RTL_FMT.isRtlContext());

        assertEquals(false, BidiFormatter.getInstance(Locale.ENGLISH).isRtlContext());
        assertEquals(true, BidiFormatter.getInstance(true).isRtlContext());
    }

    @Test
    public void testCachedInstances() {
        // Test that we get the same cached static instances for simple cases
        BidiFormatter defaultFormatterInstance = BidiFormatter.getInstance();
        assertTrue(defaultFormatterInstance == LTR_FMT || defaultFormatterInstance == RTL_FMT);

        assertEquals(LTR_FMT, BidiFormatter.getInstance(false));
        assertEquals(RTL_FMT, BidiFormatter.getInstance(true));

        assertEquals(LTR_FMT, BidiFormatter.getInstance(false));
        assertEquals(RTL_FMT, BidiFormatter.getInstance(Locale.forLanguageTag("ar")));
    }

    @Test
    public void testBuilderIsRtlContext() {
        assertEquals(false, new BidiFormatter.Builder(false).build().isRtlContext());
        assertEquals(true, new BidiFormatter.Builder(true).build().isRtlContext());
    }

    @Test
    public void testIsRtl() {
        assertEquals(true, BidiFormatter.getInstance(true).isRtl(HE));
        assertEquals(true, BidiFormatter.getInstance(false).isRtl(HE));

        assertEquals(false, BidiFormatter.getInstance(true).isRtl(EN));
        assertEquals(false, BidiFormatter.getInstance(false).isRtl(EN));
    }

    @Test
    public void testUnicodeWrap() {
        // Make sure an input of null doesn't crash anything.
        assertNull(LTR_FMT.unicodeWrap(null));

        // Uniform directionality in opposite context.
        assertEquals("uniform dir opposite to LTR context",
                RLE + "." + HE + "." + PDF + LRM,
                LTR_FMT_EXIT_RESET.unicodeWrap("." + HE + "."));
        assertEquals("uniform dir opposite to LTR context, stereo reset",
                LRM + RLE + "." + HE + "." + PDF + LRM,
                LTR_FMT.unicodeWrap("." + HE + "."));
        assertEquals("uniform dir opposite to LTR context, stereo reset, no isolation",
                RLE + "." + HE + "." + PDF,
                LTR_FMT.unicodeWrap("." + HE + ".", false));
        assertEquals("neutral treated as opposite to LTR context",
                RLE + "." + PDF + LRM,
                LTR_FMT_EXIT_RESET.unicodeWrap(".", TextDirectionHeuristics.RTL));
        assertEquals("uniform dir opposite to RTL context",
                LRE + "." + EN + "." + PDF + RLM,
                RTL_FMT_EXIT_RESET.unicodeWrap("." + EN + "."));
        assertEquals("uniform dir opposite to RTL context, stereo reset",
                RLM + LRE + "." + EN + "." + PDF + RLM,
                RTL_FMT.unicodeWrap("." + EN + "."));
        assertEquals("uniform dir opposite to RTL context, stereo reset, no isolation",
                LRE + "." + EN + "." + PDF,
                RTL_FMT.unicodeWrap("." + EN + ".", false));
        assertEquals("neutral treated as opposite to RTL context",
                LRE + "." + PDF + RLM,
                RTL_FMT_EXIT_RESET.unicodeWrap(".", TextDirectionHeuristics.LTR));

        // We test mixed-directionality cases only with an explicit overall directionality parameter
        // because the estimation logic is outside the sphere of BidiFormatter, and different
        // estimators will treat them differently.

        // Overall directionality matching context, but with opposite exit directionality.
        assertEquals("exit dir opposite to LTR context",
                EN + HE + LRM,
                LTR_FMT_EXIT_RESET.unicodeWrap(EN + HE, TextDirectionHeuristics.LTR));
        assertEquals("exit dir opposite to LTR context, stereo reset",
                EN + HE + LRM,
                LTR_FMT.unicodeWrap(EN + HE, TextDirectionHeuristics.LTR));
        assertEquals("exit dir opposite to LTR context, stereo reset, no isolation",
                EN + HE,
                LTR_FMT.unicodeWrap(EN + HE, TextDirectionHeuristics.LTR, false));

        assertEquals("exit dir opposite to RTL context",
                HE + EN + RLM,
                RTL_FMT_EXIT_RESET.unicodeWrap(HE + EN, TextDirectionHeuristics.RTL));
        assertEquals("exit dir opposite to RTL context, stereo reset",
                HE + EN + RLM,
                RTL_FMT.unicodeWrap(HE + EN, TextDirectionHeuristics.RTL));
        assertEquals("exit dir opposite to RTL context, stereo reset, no isolation",
                HE + EN,
                RTL_FMT.unicodeWrap(HE + EN, TextDirectionHeuristics.RTL, false));

        // Overall directionality matching context, but with opposite entry directionality.
        assertEquals("entry dir opposite to LTR context",
                HE + EN,
                LTR_FMT_EXIT_RESET.unicodeWrap(HE + EN, TextDirectionHeuristics.LTR));
        assertEquals("entry dir opposite to LTR context, stereo reset",
                LRM + HE + EN,
                LTR_FMT.unicodeWrap(HE + EN, TextDirectionHeuristics.LTR));
        assertEquals("entry dir opposite to LTR context, stereo reset, no isolation",
                HE + EN,
                LTR_FMT.unicodeWrap(HE + EN, TextDirectionHeuristics.LTR, false));

        assertEquals("entry dir opposite to RTL context",
                EN + HE,
                RTL_FMT_EXIT_RESET.unicodeWrap(EN + HE, TextDirectionHeuristics.RTL));
        assertEquals("entry dir opposite to RTL context, stereo reset",
                RLM + EN + HE,
                RTL_FMT.unicodeWrap(EN + HE, TextDirectionHeuristics.RTL));
        assertEquals("entry dir opposite to RTL context, stereo reset, no isolation",
                EN + HE,
                RTL_FMT.unicodeWrap(EN + HE, TextDirectionHeuristics.RTL, false));

        // Overall directionality matching context, but with opposite entry and exit directionality.
        assertEquals("entry and exit dir opposite to LTR context",
                HE + EN + HE + LRM,
                LTR_FMT_EXIT_RESET.unicodeWrap(HE + EN + HE, TextDirectionHeuristics.LTR));
        assertEquals("entry and exit dir opposite to LTR context, stereo reset",
                LRM + HE + EN + HE + LRM,
                LTR_FMT.unicodeWrap(HE + EN + HE, TextDirectionHeuristics.LTR));
        assertEquals("entry and exit dir opposite to LTR context, no isolation",
                HE + EN + HE,
                LTR_FMT_EXIT_RESET.unicodeWrap(HE + EN + HE, TextDirectionHeuristics.LTR, false));

        assertEquals("entry and exit dir opposite to RTL context",
                EN + HE + EN + RLM,
                RTL_FMT_EXIT_RESET.unicodeWrap(EN + HE + EN, TextDirectionHeuristics.RTL));
        assertEquals("entry and exit dir opposite to RTL context, no isolation",
                EN + HE + EN,
                RTL_FMT_EXIT_RESET.unicodeWrap(EN + HE + EN, TextDirectionHeuristics.RTL, false));

        // Entry and exit directionality matching context, but with opposite overall directionality.
        assertEquals("overall dir (but not entry or exit dir) opposite to LTR context",
                RLE + EN + HE + EN + PDF + LRM,
                LTR_FMT_EXIT_RESET.unicodeWrap(EN + HE + EN, TextDirectionHeuristics.RTL));
        assertEquals("overall dir (but not entry or exit dir) opposite to LTR context, stereo reset",
                LRM + RLE + EN + HE + EN + PDF + LRM,
                LTR_FMT.unicodeWrap(EN + HE + EN, TextDirectionHeuristics.RTL));
        assertEquals("overall dir (but not entry or exit dir) opposite to LTR context, no isolation",
                RLE + EN + HE + EN + PDF,
                LTR_FMT_EXIT_RESET.unicodeWrap(EN + HE + EN, TextDirectionHeuristics.RTL, false));

        assertEquals("overall dir (but not entry or exit dir) opposite to RTL context",
                LRE + HE + EN + HE + PDF + RLM,
                RTL_FMT_EXIT_RESET.unicodeWrap(HE + EN + HE, TextDirectionHeuristics.LTR));
        assertEquals("overall dir (but not entry or exit dir) opposite to RTL context, stereo reset",
                RLM + LRE + HE + EN + HE + PDF + RLM,
                RTL_FMT.unicodeWrap(HE + EN + HE, TextDirectionHeuristics.LTR));
        assertEquals("overall dir (but not entry or exit dir) opposite to RTL context, no isolation",
                LRE + HE + EN + HE + PDF,
                RTL_FMT_EXIT_RESET.unicodeWrap(HE + EN + HE, TextDirectionHeuristics.LTR, false));
    }

    @Test
    public void testGetStereoReset() {
        assertTrue(LTR_FMT.getStereoReset());
        assertTrue(RTL_FMT.getStereoReset());
        assertFalse(LTR_FMT_EXIT_RESET.getStereoReset());
        assertFalse(RTL_FMT_EXIT_RESET.getStereoReset());
    }

    @Test
    public void testBuilder_construction() {
        final BidiFormatter defaultFmt = new BidiFormatter.Builder().build();
        // Test that the default locale and the BidiFormatter's locale have the same direction.
        assertEquals(ULocale.getDefault().isRightToLeft(), defaultFmt.isRtlContext());

        final BidiFormatter ltrFmt = new BidiFormatter.Builder(false).build();
        assertFalse(ltrFmt.isRtlContext());

        final BidiFormatter rtlFmt = new BidiFormatter.Builder(true).build();
        assertTrue(rtlFmt.isRtlContext());

        final BidiFormatter englishFmt = new BidiFormatter.Builder(Locale.ENGLISH).build();
        assertFalse(englishFmt.isRtlContext());

        final BidiFormatter arabicFmt =
                new BidiFormatter.Builder(Locale.forLanguageTag("ar")).build();
        assertTrue(arabicFmt.isRtlContext());
    }

    @Test
    public void testBuilder_setTextDirectionHeuristic() {
        final BidiFormatter defaultFmt = new BidiFormatter.Builder().build();
        assertFalse(defaultFmt.isRtl(EN + HE + EN));

        final BidiFormatter modifiedFmt = new BidiFormatter.Builder().setTextDirectionHeuristic(
                TextDirectionHeuristics.ANYRTL_LTR).build();
        assertTrue(modifiedFmt.isRtl(EN + HE + EN));
    }

    @Test
    public void testCharSequenceApis() {
        final CharSequence CS_HE = new SpannableString(HE);
        assertEquals(true, BidiFormatter.getInstance(true).isRtl(CS_HE));

        final SpannableString CS_EN_HE = new SpannableString(EN + HE);
        final Object RELATIVE_SIZE_SPAN = new RelativeSizeSpan(1.2f);
        CS_EN_HE.setSpan(RELATIVE_SIZE_SPAN, 0, EN.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);

        Spanned wrapped;
        Object[] spans;

        wrapped = (Spanned) LTR_FMT.unicodeWrap(CS_EN_HE);
        assertEquals(EN + HE + LRM, wrapped.toString());
        spans = wrapped.getSpans(0, wrapped.length(), Object.class);
        assertEquals(1, spans.length);
        assertEquals(RELATIVE_SIZE_SPAN, spans[0]);
        assertEquals(0, wrapped.getSpanStart(RELATIVE_SIZE_SPAN));
        assertEquals(EN.length(), wrapped.getSpanEnd(RELATIVE_SIZE_SPAN));

        wrapped = (Spanned) LTR_FMT.unicodeWrap(CS_EN_HE, TextDirectionHeuristics.LTR);
        assertEquals(EN + HE + LRM, wrapped.toString());
        spans = wrapped.getSpans(0, wrapped.length(), Object.class);
        assertEquals(1, spans.length);
        assertEquals(RELATIVE_SIZE_SPAN, spans[0]);
        assertEquals(0, wrapped.getSpanStart(RELATIVE_SIZE_SPAN));
        assertEquals(EN.length(), wrapped.getSpanEnd(RELATIVE_SIZE_SPAN));

        wrapped = (Spanned) LTR_FMT.unicodeWrap(CS_EN_HE, false);
        assertEquals(EN + HE, wrapped.toString());
        spans = wrapped.getSpans(0, wrapped.length(), Object.class);
        assertEquals(1, spans.length);
        assertEquals(RELATIVE_SIZE_SPAN, spans[0]);
        assertEquals(0, wrapped.getSpanStart(RELATIVE_SIZE_SPAN));
        assertEquals(EN.length(), wrapped.getSpanEnd(RELATIVE_SIZE_SPAN));

        wrapped = (Spanned) LTR_FMT.unicodeWrap(CS_EN_HE, TextDirectionHeuristics.LTR, false);
        assertEquals(EN + HE, wrapped.toString());
        spans = wrapped.getSpans(0, wrapped.length(), Object.class);
        assertEquals(1, spans.length);
        assertEquals(RELATIVE_SIZE_SPAN, spans[0]);
        assertEquals(0, wrapped.getSpanStart(RELATIVE_SIZE_SPAN));
        assertEquals(EN.length(), wrapped.getSpanEnd(RELATIVE_SIZE_SPAN));
    }
}
