// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.components.browser_ui.widget;

import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.SmallTest;
import android.support.test.rule.UiThreadTestRule;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.EditText;
import android.widget.TextView;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.components.browser_ui.widget.test.R;

import java.util.Arrays;
import java.util.List;

/**
 * Tests for {@link RadioButtonLayout}.
 */
@RunWith(BaseJUnit4ClassRunner.class)
public class RadioButtonWithDescriptionLayoutTest {
    private static final String NON_ZERO_MARGIN_ASSERT_MESSAGE =
            "First N-1 items should have a non-zero margin";
    private static final String ZERO_MARGIN_ASSERT_MESSAGE =
            "The last item should have a zero margin";
    private static final String PRIMARY_MATCH_ASSERT_MESSAGE =
            "Primary text set through addButtons should match the view's primary text.";
    private static final String DESCRIPTION_MATCH_ASSERT_MESSAGE =
            "Description set through addButtons should match the view's description.";
    private static final String TAG_MATCH_ASSERT_MESSAGE =
            "Tag set through addButtons should match the view's tag.";

    private static final String PRIMARY_MATCH_FROM_XML_ASSERT_MESSAGE =
            "Primary text set through layout should match the view's primary text.";
    private static final String DESC_MATCH_FROM_XML_ASSERT_MESSAGE =
            "Description text set through layout should match the view's description.";
    private static final String HINT_MATCH_FROM_XML_ASSERT_MESSAGE =
            "Hint message set through layout should match the view's hint message.";

    @Rule
    public UiThreadTestRule mRule = new UiThreadTestRule();

    private Context mContext;

    @Before
    public void setUp() {
        mContext = InstrumentationRegistry.getTargetContext();
    }

    @Test
    @SmallTest
    @UiThreadTest
    public void testMargins() {
        RadioButtonWithDescriptionLayout layout = new RadioButtonWithDescriptionLayout(mContext);

        // Add one set of buttons.
        List<RadioButtonWithDescription> buttons =
                Arrays.asList(createRadioButtonWithDescription("a", "a_desc", "a_tag"),
                        createRadioButtonWithDescription("b", "b_desc", "b_tag"),
                        createRadioButtonWithDescription("c", "c_desc", "c_tag"));
        layout.addButtons(buttons);
        Assert.assertEquals(3, layout.getChildCount());

        // Test the margins.
        for (int i = 0; i < layout.getChildCount(); i++) {
            View child = layout.getChildAt(i);
            MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();

            if (i < layout.getChildCount() - 1) {
                Assert.assertNotEquals(NON_ZERO_MARGIN_ASSERT_MESSAGE, 0, params.bottomMargin);
            } else {
                Assert.assertEquals(ZERO_MARGIN_ASSERT_MESSAGE, 0, params.bottomMargin);
            }
        }

        // Add more buttons.
        List<RadioButtonWithDescription> moreButtons =
                Arrays.asList(createRadioButtonWithDescription("d", "d_desc", null),
                        createRadioButtonWithDescription("e", "e_desc", null),
                        createRadioButtonWithDescription("f", "f_desc", null));
        layout.addButtons(moreButtons);
        Assert.assertEquals(6, layout.getChildCount());

        // Test the margins.
        for (int i = 0; i < layout.getChildCount(); i++) {
            View child = layout.getChildAt(i);
            MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();

            if (i < layout.getChildCount() - 1) {
                Assert.assertNotEquals(NON_ZERO_MARGIN_ASSERT_MESSAGE, 0, params.bottomMargin);
            } else {
                Assert.assertEquals(ZERO_MARGIN_ASSERT_MESSAGE, 0, params.bottomMargin);
            }
        }
    }

    @Test
    @SmallTest
    @UiThreadTest
    public void testAddButtons() {
        RadioButtonWithDescriptionLayout layout = new RadioButtonWithDescriptionLayout(mContext);

        // Add one set of options.
        List<RadioButtonWithDescription> buttons =
                Arrays.asList(createRadioButtonWithDescription("a", "a_desc", "a_tag"),
                        createRadioButtonWithDescription("b", "b_desc", "b_tag"),
                        createRadioButtonWithDescription("c", "c_desc", "c_tag"));
        layout.addButtons(buttons);
        Assert.assertEquals(3, layout.getChildCount());

        for (int i = 0; i < layout.getChildCount(); i++) {
            RadioButtonWithDescription b = (RadioButtonWithDescription) layout.getChildAt(i);
            Assert.assertEquals(PRIMARY_MATCH_ASSERT_MESSAGE,
                    buttons.get(i).getPrimaryText().toString(), b.getPrimaryText().toString());
            Assert.assertEquals(DESCRIPTION_MATCH_ASSERT_MESSAGE,
                    buttons.get(i).getDescriptionText().toString(),
                    b.getDescriptionText().toString());
            Assert.assertEquals(TAG_MATCH_ASSERT_MESSAGE, buttons.get(i).getTag(), b.getTag());
        }

        // Add even more options, but without tags.
        List<RadioButtonWithDescription> moreButtons =
                Arrays.asList(createRadioButtonWithDescription("d", "d_desc", null),
                        createRadioButtonWithDescription("e", "e_desc", null),
                        createRadioButtonWithDescription("f", "f_desc", null));
        layout.addButtons(moreButtons);
        Assert.assertEquals(6, layout.getChildCount());
        for (int i = 0; i < 3; i++) {
            RadioButtonWithDescription b = (RadioButtonWithDescription) layout.getChildAt(i);
            Assert.assertEquals(PRIMARY_MATCH_ASSERT_MESSAGE,
                    buttons.get(i).getPrimaryText().toString(), b.getPrimaryText().toString());
            Assert.assertEquals(DESCRIPTION_MATCH_ASSERT_MESSAGE,
                    buttons.get(i).getDescriptionText().toString(),
                    b.getDescriptionText().toString());
            Assert.assertEquals(TAG_MATCH_ASSERT_MESSAGE, buttons.get(i).getTag(), b.getTag());
        }
        for (int i = 3; i < 6; i++) {
            RadioButtonWithDescription b = (RadioButtonWithDescription) layout.getChildAt(i);
            Assert.assertEquals(PRIMARY_MATCH_ASSERT_MESSAGE,
                    moreButtons.get(i - 3).getPrimaryText().toString(),
                    b.getPrimaryText().toString());
            Assert.assertEquals(DESCRIPTION_MATCH_ASSERT_MESSAGE,
                    moreButtons.get(i - 3).getDescriptionText().toString(),
                    b.getDescriptionText().toString());
            Assert.assertEquals(
                    TAG_MATCH_ASSERT_MESSAGE, moreButtons.get(i - 3).getTag(), b.getTag());
        }
    }

    @Test
    @SmallTest
    @UiThreadTest
    public void testSelection() {
        final RadioButtonWithDescriptionLayout layout =
                new RadioButtonWithDescriptionLayout(mContext);

        // Add one set of options.
        List<RadioButtonWithDescription> buttons =
                Arrays.asList(createRadioButtonWithDescription("a", "a_desc", null),
                        createRadioButtonWithDescription("b", "b_desc", null),
                        createRadioButtonWithDescription("c", "c_desc", null));
        layout.addButtons(buttons);
        Assert.assertEquals(3, layout.getChildCount());

        // Nothing should be selected by default.
        for (int i = 0; i < layout.getChildCount(); i++) {
            RadioButtonWithDescription child = (RadioButtonWithDescription) layout.getChildAt(i);
            Assert.assertFalse(child.isChecked());
        }

        // Select the second one.
        layout.selectChildAtIndexForTesting(1);
        for (int i = 0; i < layout.getChildCount(); i++) {
            RadioButtonWithDescription child = (RadioButtonWithDescription) layout.getChildAt(i);
            Assert.assertEquals(i == 1, child.isChecked());
        }

        // Add even more options.
        List<RadioButtonWithDescription> moreButtons =
                Arrays.asList(createRadioButtonWithDescription("d", "d_desc", null),
                        createRadioButtonWithDescription("e", "e_desc", null),
                        createRadioButtonWithDescription("f", "f_desc", null));
        layout.addButtons(moreButtons);
        Assert.assertEquals(6, layout.getChildCount());

        // Second child should still be checked.
        for (int i = 0; i < layout.getChildCount(); i++) {
            RadioButtonWithDescription child = (RadioButtonWithDescription) layout.getChildAt(i);
            Assert.assertEquals(i == 1, child.isChecked());
        }
    }

    @Test
    @SmallTest
    @UiThreadTest
    public void testAccessoryViewAdded() {
        final RadioButtonWithDescriptionLayout layout =
                new RadioButtonWithDescriptionLayout(mContext);

        List<RadioButtonWithDescription> buttons =
                Arrays.asList(createRadioButtonWithDescription("a", "a_desc", null),
                        createRadioButtonWithDescription("b", "b_desc", null),
                        createRadioButtonWithDescription("c", "c_desc", null));
        layout.addButtons(buttons);

        RadioButtonWithDescription firstButton = (RadioButtonWithDescription) layout.getChildAt(0);
        final TextView accessoryTextView = new TextView(mContext);
        layout.attachAccessoryView(accessoryTextView, firstButton);
        Assert.assertEquals(
                "The accessory view should be right after the position of it's attachment host.",
                accessoryTextView, layout.getChildAt(1));
    }

    @Test
    @SmallTest
    @UiThreadTest
    public void testAccessoryViewAddedThenReadded() {
        final RadioButtonWithDescriptionLayout layout =
                new RadioButtonWithDescriptionLayout(mContext);

        List<RadioButtonWithDescription> buttons =
                Arrays.asList(createRadioButtonWithDescription("a", "a_desc", null),
                        createRadioButtonWithDescription("b", "b_desc", null),
                        createRadioButtonWithDescription("c", "c_desc", null));
        layout.addButtons(buttons);

        RadioButtonWithDescription firstButton = (RadioButtonWithDescription) layout.getChildAt(0);
        RadioButtonWithDescription lastButton =
                (RadioButtonWithDescription) layout.getChildAt(layout.getChildCount() - 1);
        final TextView accessoryTextView = new TextView(mContext);
        layout.attachAccessoryView(accessoryTextView, firstButton);
        layout.attachAccessoryView(accessoryTextView, lastButton);
        Assert.assertNotEquals(
                "The accessory view shouldn't be in the first position it was inserted at.",
                accessoryTextView, layout.getChildAt(1));
        Assert.assertEquals("The accessory view should be at the new position it was placed at.",
                accessoryTextView, layout.getChildAt(layout.getChildCount() - 1));
    }

    @Test
    @SmallTest
    @UiThreadTest
    public void testCombinedRadioButtons() {
        // Test if radio buttons are set up correctly when there are multiple classes in the same
        // layout.
        View content = LayoutInflater.from(mContext).inflate(
                R.layout.radio_button_with_description_layout_test, null, false);

        RadioButtonWithDescriptionLayout layout =
                content.findViewById(R.id.test_radio_button_layout);
        RadioButtonWithDescription b1 = content.findViewById(R.id.test_radio_description_1);
        RadioButtonWithDescription b2 = content.findViewById(R.id.test_radio_description_2);
        RadioButtonWithEditText b3 = content.findViewById(R.id.test_radio_edit_text_1);
        RadioButtonWithEditText b4 = content.findViewById(R.id.test_radio_edit_text_2);

        Assert.assertNotNull(layout);
        Assert.assertNotNull(b1);
        Assert.assertNotNull(b2);
        Assert.assertNotNull(b3);
        Assert.assertNotNull(b4);

        layout.selectChildAtIndexForTesting(3);

        Assert.assertEquals(PRIMARY_MATCH_FROM_XML_ASSERT_MESSAGE, b1.getPrimaryText().toString(),
                mContext.getResources().getString(R.string.test_primary_1));
        Assert.assertEquals(PRIMARY_MATCH_FROM_XML_ASSERT_MESSAGE, b2.getPrimaryText().toString(),
                mContext.getResources().getString(R.string.test_primary_2));
        Assert.assertEquals(PRIMARY_MATCH_FROM_XML_ASSERT_MESSAGE, b3.getPrimaryText().toString(),
                mContext.getResources().getString(R.string.test_primary_3));
        Assert.assertEquals(PRIMARY_MATCH_FROM_XML_ASSERT_MESSAGE, b4.getPrimaryText().toString(),
                mContext.getResources().getString(R.string.test_primary_4));

        Assert.assertTrue(
                DESC_MATCH_FROM_XML_ASSERT_MESSAGE, TextUtils.isEmpty(b1.getDescriptionText()));
        Assert.assertEquals(DESC_MATCH_FROM_XML_ASSERT_MESSAGE, b2.getDescriptionText().toString(),
                mContext.getResources().getString(R.string.test_desc_2));
        Assert.assertTrue(
                DESC_MATCH_FROM_XML_ASSERT_MESSAGE, TextUtils.isEmpty(b3.getDescriptionText()));
        Assert.assertEquals(DESC_MATCH_FROM_XML_ASSERT_MESSAGE, b4.getDescriptionText().toString(),
                mContext.getResources().getString(R.string.test_desc_4));

        Assert.assertEquals(HINT_MATCH_FROM_XML_ASSERT_MESSAGE,
                ((EditText) b3.getPrimaryTextView()).getHint().toString(),
                mContext.getResources().getString(R.string.test_uri));
        Assert.assertEquals(HINT_MATCH_FROM_XML_ASSERT_MESSAGE,
                ((EditText) b4.getPrimaryTextView()).getHint().toString(),
                mContext.getResources().getString(R.string.test_uri));

        Assert.assertFalse(b1.isChecked());
        Assert.assertFalse(b2.isChecked());
        Assert.assertFalse(b3.isChecked());
        Assert.assertTrue(b4.isChecked());
    }

    @Test
    @SmallTest
    public void testSetEnable() {
        View content = LayoutInflater.from(mContext).inflate(
                R.layout.radio_button_with_description_layout_test, null, false);

        RadioButtonWithDescriptionLayout layout =
                content.findViewById(R.id.test_radio_button_layout);
        RadioButtonWithDescription b1 = content.findViewById(R.id.test_radio_description_1);
        RadioButtonWithDescription b2 = content.findViewById(R.id.test_radio_description_2);
        RadioButtonWithEditText b3 = content.findViewById(R.id.test_radio_edit_text_1);
        RadioButtonWithEditText b4 = content.findViewById(R.id.test_radio_edit_text_2);

        final TextView textView1 = new TextView(mContext);
        final TextView textView3 = new TextView(mContext);

        layout.attachAccessoryView(textView1, b1);
        layout.attachAccessoryView(textView3, b3);

        layout.setEnabled(false);

        Assert.assertFalse(b1.isEnabled());
        Assert.assertFalse(b2.isEnabled());
        Assert.assertFalse(b3.isEnabled());
        Assert.assertFalse(b4.isEnabled());
        Assert.assertFalse(textView1.isEnabled());
        Assert.assertFalse(textView3.isEnabled());

        layout.setEnabled(true);

        Assert.assertTrue(b1.isEnabled());
        Assert.assertTrue(b2.isEnabled());
        Assert.assertTrue(b3.isEnabled());
        Assert.assertTrue(b4.isEnabled());
        Assert.assertTrue(textView1.isEnabled());
        Assert.assertTrue(textView3.isEnabled());
    }

    private RadioButtonWithDescription createRadioButtonWithDescription(
            String primary, String description, Object tag) {
        RadioButtonWithDescription b = new RadioButtonWithDescription(mContext, null);
        b.setPrimaryText(primary);
        b.setDescriptionText(description);
        b.setTag(tag);
        return b;
    }
}
