/*
 * Copyright (C) 2008 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.widget.cts;

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

import android.app.Instrumentation;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TabWidget;
import android.widget.TextView;
import android.widget.cts.util.TestUtils;

import androidx.test.InstrumentationRegistry;
import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.MediumTest;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;

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

/**
 * Test {@link TabWidget}.
 */
@MediumTest
@RunWith(AndroidJUnit4.class)
public class TabWidgetTest {
    private TabHostCtsActivity mActivity;
    private TabWidget mTabWidget;
    private Instrumentation mInstrumentation;

    @Rule
    public ActivityTestRule<TabHostCtsActivity> mActivityRule =
            new ActivityTestRule<>(TabHostCtsActivity.class);

    @Before
    public void setup() {
        mInstrumentation = InstrumentationRegistry.getInstrumentation();
        mActivity = mActivityRule.getActivity();
        mTabWidget = mActivity.getTabWidget();
    }

    @Test
    public void testConstructor() {
        new TabWidget(mActivity);

        new TabWidget(mActivity, null);

        new TabWidget(mActivity, null, 0);
    }

    @Test
    public void testConstructorWithStyle() {
        TabWidget tabWidget = new TabWidget(mActivity, null, 0, R.style.TabWidgetCustomStyle);

        assertFalse(tabWidget.isStripEnabled());

        Drawable leftStripDrawable = tabWidget.getLeftStripDrawable();
        assertNotNull(leftStripDrawable);
        TestUtils.assertAllPixelsOfColor("Left strip green", leftStripDrawable,
                leftStripDrawable.getIntrinsicWidth(), leftStripDrawable.getIntrinsicHeight(),
                true, 0xFF00FF00, 1, false);

        Drawable rightStripDrawable = tabWidget.getRightStripDrawable();
        assertNotNull(rightStripDrawable);
        TestUtils.assertAllPixelsOfColor("Right strip red", rightStripDrawable,
                rightStripDrawable.getIntrinsicWidth(), rightStripDrawable.getIntrinsicHeight(),
                true, 0xFFFF0000, 1, false);
    }

    @Test
    public void testInflateFromXml() {
        LayoutInflater inflater = LayoutInflater.from(mActivity);
        TabWidget tabWidget = (TabWidget) inflater.inflate(R.layout.tabhost_custom, null, false);

        assertFalse(tabWidget.isStripEnabled());

        Drawable leftStripDrawable = tabWidget.getLeftStripDrawable();
        assertNotNull(leftStripDrawable);
        TestUtils.assertAllPixelsOfColor("Left strip red", leftStripDrawable,
                leftStripDrawable.getIntrinsicWidth(), leftStripDrawable.getIntrinsicHeight(),
                true, 0xFFFF0000, 1, false);

        Drawable rightStripDrawable = tabWidget.getRightStripDrawable();
        assertNotNull(rightStripDrawable);
        TestUtils.assertAllPixelsOfColor("Right strip green", rightStripDrawable,
                rightStripDrawable.getIntrinsicWidth(), rightStripDrawable.getIntrinsicHeight(),
                true, 0xFF00FF00, 1, false);
    }

    @UiThreadTest
    @Test
    public void testTabCount() {
        // We have one tab added in onCreate() of our activity
        assertEquals(1, mTabWidget.getTabCount());

        for (int i = 1; i < 10; i++) {
            mTabWidget.addView(new TextView(mActivity));
            assertEquals(i + 1, mTabWidget.getTabCount());
        }
    }

    @UiThreadTest
    @Test
    public void testTabViews() {
        // We have one tab added in onCreate() of our activity. We "reach" into the default tab
        // indicator layout in the same way we do in TabHost_TabSpecTest tests.
        TextView tab0 = (TextView) mTabWidget.getChildTabViewAt(0).findViewById(android.R.id.title);
        assertNotNull(tab0);
        assertEquals(TabHostCtsActivity.INITIAL_TAB_LABEL, tab0.getText());

        for (int i = 1; i < 10; i++) {
            TextView toAdd = new TextView(mActivity);
            toAdd.setText("Tab #" + i);
            mTabWidget.addView(toAdd);
            assertEquals(toAdd, mTabWidget.getChildTabViewAt(i));
        }
    }

    @UiThreadTest
    @Test
    public void testChildDrawableStateChanged() {
        MockTabWidget mockTabWidget = new MockTabWidget(mActivity);
        TextView tv0 = new TextView(mActivity);
        TextView tv1 = new TextView(mActivity);
        mockTabWidget.addView(tv0);
        mockTabWidget.addView(tv1);
        mockTabWidget.setCurrentTab(1);
        mockTabWidget.reset();
        mockTabWidget.childDrawableStateChanged(tv0);
        assertFalse(mockTabWidget.hasCalledInvalidate());

        mockTabWidget.reset();
        mockTabWidget.childDrawableStateChanged(tv1);
        assertTrue(mockTabWidget.hasCalledInvalidate());

        mockTabWidget.reset();
        mockTabWidget.childDrawableStateChanged(null);
        assertFalse(mockTabWidget.hasCalledInvalidate());
    }

    @UiThreadTest
    @Test
    public void testSetCurrentTab() {
        mTabWidget.addView(new TextView(mActivity));

        assertTrue(mTabWidget.getChildAt(0).isSelected());
        assertFalse(mTabWidget.getChildAt(1).isSelected());
        assertTrue(mTabWidget.getChildAt(0).isFocused());
        assertFalse(mTabWidget.getChildAt(1).isFocused());

        mTabWidget.setCurrentTab(1);
        assertFalse(mTabWidget.getChildAt(0).isSelected());
        assertTrue(mTabWidget.getChildAt(1).isSelected());
        assertTrue(mTabWidget.getChildAt(0).isFocused());
        assertFalse(mTabWidget.getChildAt(1).isFocused());
    }

    @UiThreadTest
    @Test
    public void testFocusCurrentTab() {
        mTabWidget.addView(new TextView(mActivity));

        assertTrue(mTabWidget.getChildAt(0).isSelected());
        assertFalse(mTabWidget.getChildAt(1).isSelected());
        assertEquals(mTabWidget.getChildAt(0), mTabWidget.getFocusedChild());
        assertTrue(mTabWidget.getChildAt(0).isFocused());
        assertFalse(mTabWidget.getChildAt(1).isFocused());

        // normal
        mTabWidget.focusCurrentTab(1);
        assertFalse(mTabWidget.getChildAt(0).isSelected());
        assertTrue(mTabWidget.getChildAt(1).isSelected());
        assertEquals(mTabWidget.getChildAt(1), mTabWidget.getFocusedChild());
        assertFalse(mTabWidget.getChildAt(0).isFocused());
        assertTrue(mTabWidget.getChildAt(1).isFocused());

        mTabWidget.focusCurrentTab(0);
        assertTrue(mTabWidget.getChildAt(0).isSelected());
        assertFalse(mTabWidget.getChildAt(1).isSelected());
        assertEquals(mTabWidget.getChildAt(0), mTabWidget.getFocusedChild());
        assertTrue(mTabWidget.getChildAt(0).isFocused());
        assertFalse(mTabWidget.getChildAt(1).isFocused());
    }

    @UiThreadTest
    @Test(expected=NullPointerException.class)
    public void testFocusCurrentTabIndexTooLow() {
        mTabWidget.focusCurrentTab(-1);
    }

    @UiThreadTest
    @Test(expected=NullPointerException.class)
    public void testFocusCurrentTabIndexTooHigh() {
        mTabWidget.focusCurrentTab(mTabWidget.getChildCount() + 1);
    }

    @UiThreadTest
    @Test
    public void testSetEnabled() {
        mTabWidget.addView(new TextView(mActivity));
        mTabWidget.addView(new TextView(mActivity));
        assertTrue(mTabWidget.isEnabled());
        assertTrue(mTabWidget.getChildAt(0).isEnabled());
        assertTrue(mTabWidget.getChildAt(1).isEnabled());

        mTabWidget.setEnabled(false);
        assertFalse(mTabWidget.isEnabled());
        assertFalse(mTabWidget.getChildAt(0).isEnabled());
        assertFalse(mTabWidget.getChildAt(1).isEnabled());

        mTabWidget.setEnabled(true);
        assertTrue(mTabWidget.isEnabled());
        assertTrue(mTabWidget.getChildAt(0).isEnabled());
        assertTrue(mTabWidget.getChildAt(1).isEnabled());
    }

    @UiThreadTest
    @Test
    public void testAddView() {
        MockTabWidget mockTabWidget = new MockTabWidget(mActivity);

        // normal value
        View view1 = new TextView(mActivity);
        mockTabWidget.addView(view1);
        assertSame(view1, mockTabWidget.getChildAt(0));
        LayoutParams defaultLayoutParam = mockTabWidget.generateDefaultLayoutParams();
        if (mockTabWidget.getOrientation() == LinearLayout.VERTICAL) {
            assertEquals(defaultLayoutParam.height, LayoutParams.WRAP_CONTENT);
            assertEquals(defaultLayoutParam.width, LayoutParams.MATCH_PARENT);
        } else if (mockTabWidget.getOrientation() == LinearLayout.HORIZONTAL) {
            assertEquals(defaultLayoutParam.height, LayoutParams.WRAP_CONTENT);
            assertEquals(defaultLayoutParam.width, LayoutParams.WRAP_CONTENT);
        } else {
            assertNull(defaultLayoutParam);
        }

        View view2 = new RelativeLayout(mActivity);
        mockTabWidget.addView(view2);
        assertSame(view2, mockTabWidget.getChildAt(1));
    }

    @Test(expected=RuntimeException.class)
    public void testAddAdapterView() {
        MockTabWidget mockTabWidget = new MockTabWidget(mActivity);
        // Since TabWidget registers a click listener on each child, this is expected
        // to fail with anything that extends AdapterView
        mockTabWidget.addView(new ListView(mActivity));
    }

    @Test(expected=NullPointerException.class)
    public void testAddNullView() {
        MockTabWidget mockTabWidget = new MockTabWidget(mActivity);
        // Since TabWidget registers a click listener on each child, this is expected
        // to fail with anything that extends AdapterView
        mockTabWidget.addView(null);
    }

    @UiThreadTest
    @Test
    public void testStripEnabled() {
        mTabWidget.setStripEnabled(true);
        assertTrue(mTabWidget.isStripEnabled());

        mTabWidget.setStripEnabled(false);
        assertFalse(mTabWidget.isStripEnabled());
    }

    @Test
    public void testStripDrawables() throws Throwable {
        mTabWidget.setStripEnabled(true);

        // Test setting left strip drawable
        mActivityRule.runOnUiThread(() -> mTabWidget.setLeftStripDrawable(R.drawable.icon_green));
        Drawable leftStripDrawable = mTabWidget.getLeftStripDrawable();
        assertNotNull(leftStripDrawable);
        TestUtils.assertAllPixelsOfColor("Left strip green", leftStripDrawable,
                leftStripDrawable.getIntrinsicWidth(), leftStripDrawable.getIntrinsicHeight(),
                true, 0xFF00FF00, 1, false);

        mActivityRule.runOnUiThread(() -> mTabWidget.setLeftStripDrawable(
                mActivity.getDrawable(R.drawable.icon_red)));
        leftStripDrawable = mTabWidget.getLeftStripDrawable();
        assertNotNull(leftStripDrawable);
        TestUtils.assertAllPixelsOfColor("Left strip red", leftStripDrawable,
                leftStripDrawable.getIntrinsicWidth(), leftStripDrawable.getIntrinsicHeight(),
                true, 0xFFFF0000, 1, false);

        mActivityRule.runOnUiThread(() -> mTabWidget.setLeftStripDrawable(null));
        leftStripDrawable = mTabWidget.getLeftStripDrawable();
        assertNull(leftStripDrawable);

        // Wait for draw.
        mInstrumentation.waitForIdleSync();

        // Test setting right strip drawable
        mActivityRule.runOnUiThread(() -> mTabWidget.setRightStripDrawable(R.drawable.icon_red));
        Drawable rightStripDrawable = mTabWidget.getRightStripDrawable();
        assertNotNull(rightStripDrawable);
        TestUtils.assertAllPixelsOfColor("Right strip red", rightStripDrawable,
                rightStripDrawable.getIntrinsicWidth(), rightStripDrawable.getIntrinsicHeight(),
                true, 0xFFFF0000, 1, false);

        mActivityRule.runOnUiThread(() -> mTabWidget.setRightStripDrawable(
                mActivity.getDrawable(R.drawable.icon_green)));
        rightStripDrawable = mTabWidget.getRightStripDrawable();
        assertNotNull(rightStripDrawable);
        TestUtils.assertAllPixelsOfColor("Left strip green", rightStripDrawable,
                rightStripDrawable.getIntrinsicWidth(), rightStripDrawable.getIntrinsicHeight(),
                true, 0xFF00FF00, 1, false);

        mActivityRule.runOnUiThread(() -> mTabWidget.setRightStripDrawable(null));
        rightStripDrawable = mTabWidget.getRightStripDrawable();
        assertNull(rightStripDrawable);

        // Wait for draw.
        mInstrumentation.waitForIdleSync();
    }

    @UiThreadTest
    @Test
    public void testDividerDrawables() {
        mTabWidget.setDividerDrawable(R.drawable.icon_blue);
        Drawable dividerDrawable = mTabWidget.getDividerDrawable();
        assertNotNull(dividerDrawable);
        TestUtils.assertAllPixelsOfColor("Divider blue", dividerDrawable,
                dividerDrawable.getIntrinsicWidth(), dividerDrawable.getIntrinsicHeight(),
                true, 0xFF0000FF, 1, false);

        mTabWidget.setDividerDrawable(mActivity.getDrawable(R.drawable.icon_yellow));
        dividerDrawable = mTabWidget.getDividerDrawable();
        assertNotNull(dividerDrawable);
        TestUtils.assertAllPixelsOfColor("Divider yellow", dividerDrawable,
                dividerDrawable.getIntrinsicWidth(), dividerDrawable.getIntrinsicHeight(),
                true, 0xFFFFFF00, 1, false);

    }

    /*
     * Mock class for TabWidget to be used in test cases.
     */
    private class MockTabWidget extends TabWidget {
        private boolean mCalledInvalidate = false;

        public MockTabWidget(Context context) {
            super(context);
        }

        @Override
        protected LayoutParams generateDefaultLayoutParams() {
            return super.generateDefaultLayoutParams();
        }

        @Override
        public void invalidate() {
            super.invalidate();
            mCalledInvalidate = true;
        }

        public boolean hasCalledInvalidate() {
            return mCalledInvalidate;
        }

        public void reset() {
            mCalledInvalidate = false;
        }
    }
}
