/*
 * 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 static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;

import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.StateSet;
import android.util.Xml;
import android.view.Gravity;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.cts.util.TestUtils;

import androidx.test.InstrumentationRegistry;
import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.SmallTest;
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;
import org.xmlpull.v1.XmlPullParser;

/**
 * Test {@link CompoundButton}.
 */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class CompoundButtonTest  {
    private Instrumentation mInstrumentation;
    private Activity mActivity;
    private CompoundButton mCompoundButton;

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

    @Before
    public void setup() {
        mInstrumentation = InstrumentationRegistry.getInstrumentation();
        mActivity = mActivityRule.getActivity();
        mCompoundButton = (CompoundButton) mActivity.findViewById(R.id.compound_button);
    }

    @Test
    public void testConstructor() {
        XmlPullParser parser = mActivity.getResources().getXml(R.layout.compoundbutton_layout);
        AttributeSet mAttrSet = Xml.asAttributeSet(parser);

        new MockCompoundButton(mActivity, mAttrSet, 0);
        new MockCompoundButton(mActivity, mAttrSet);
        new MockCompoundButton(mActivity);
    }

    @Test(expected=NullPointerException.class)
    public void testConstructorWithNullContext1() {
        new MockCompoundButton(null);
    }

    @Test(expected=NullPointerException.class)
    public void testConstructorWithNullContext2() {
        new MockCompoundButton(null, null);
    }

    @Test(expected=NullPointerException.class)
    public void testConstructorWithNullContext3() {
        new MockCompoundButton(null, null, -1);
    }

    @UiThreadTest
    @Test
    public void testAccessChecked() {
        CompoundButton.OnCheckedChangeListener mockCheckedChangeListener =
                mock(CompoundButton.OnCheckedChangeListener.class);
        mCompoundButton.setOnCheckedChangeListener(mockCheckedChangeListener);
        assertFalse(mCompoundButton.isChecked());
        verifyZeroInteractions(mockCheckedChangeListener);

        mCompoundButton.setChecked(true);
        assertTrue(mCompoundButton.isChecked());
        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCompoundButton, true);

        reset(mockCheckedChangeListener);
        mCompoundButton.setChecked(true);
        assertTrue(mCompoundButton.isChecked());
        verifyZeroInteractions(mockCheckedChangeListener);

        mCompoundButton.setChecked(false);
        assertFalse(mCompoundButton.isChecked());
        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCompoundButton, false);
    }

    @UiThreadTest
    @Test
    public void testSetOnCheckedChangeListener() {
        CompoundButton.OnCheckedChangeListener mockCheckedChangeListener =
                mock(CompoundButton.OnCheckedChangeListener.class);
        mCompoundButton.setOnCheckedChangeListener(mockCheckedChangeListener);
        assertFalse(mCompoundButton.isChecked());
        verifyZeroInteractions(mockCheckedChangeListener);

        mCompoundButton.setChecked(true);
        verify(mockCheckedChangeListener, times(1)).onCheckedChanged(mCompoundButton, true);

        // set null
        mCompoundButton.setOnCheckedChangeListener(null);
        reset(mockCheckedChangeListener);
        mCompoundButton.setChecked(false);
        verifyZeroInteractions(mockCheckedChangeListener);
    }

    @UiThreadTest
    @Test
    public void testToggle() {
        assertFalse(mCompoundButton.isChecked());

        mCompoundButton.toggle();
        assertTrue(mCompoundButton.isChecked());

        mCompoundButton.toggle();
        assertFalse(mCompoundButton.isChecked());

        mCompoundButton.setChecked(true);
        mCompoundButton.toggle();
        assertFalse(mCompoundButton.isChecked());
    }

    @UiThreadTest
    @Test
    public void testPerformClick() {
        assertFalse(mCompoundButton.isChecked());

        // performClick without OnClickListener will return false.
        assertFalse(mCompoundButton.performClick());
        assertTrue(mCompoundButton.isChecked());

        assertFalse(mCompoundButton.performClick());
        assertFalse(mCompoundButton.isChecked());

        // performClick with OnClickListener will return true.
        mCompoundButton.setOnClickListener((view) -> {});
        assertTrue(mCompoundButton.performClick());
        assertTrue(mCompoundButton.isChecked());

        assertTrue(mCompoundButton.performClick());
        assertFalse(mCompoundButton.isChecked());
    }

    @UiThreadTest
    @Test
    public void testDrawableStateChanged() {
        MockCompoundButton compoundButton = new MockCompoundButton(mActivity);
        assertFalse(compoundButton.isChecked());
        // drawableStateChanged without any drawables.
        compoundButton.drawableStateChanged();

        // drawableStateChanged when CheckMarkDrawable is not null.
        Drawable drawable = mActivity.getDrawable(R.drawable.statelistdrawable);
        compoundButton.setButtonDrawable(drawable);
        drawable.setState(null);
        assertNull(drawable.getState());

        compoundButton.drawableStateChanged();
        assertNotNull(drawable.getState());
        assertSame(compoundButton.getDrawableState(), drawable.getState());
    }

    @UiThreadTest
    @Test
    public void testSetButtonDrawableByDrawable() {
        // set null drawable
        mCompoundButton.setButtonDrawable(null);
        assertNull(mCompoundButton.getButtonDrawable());

        // set drawable when button is GONE
        mCompoundButton.setVisibility(View.GONE);
        Drawable firstDrawable = mActivity.getDrawable(R.drawable.scenery);
        firstDrawable.setVisible(true, false);
        assertEquals(StateSet.WILD_CARD, firstDrawable.getState());

        mCompoundButton.setButtonDrawable(firstDrawable);
        assertSame(firstDrawable, mCompoundButton.getButtonDrawable());
        assertFalse(firstDrawable.isVisible());

        // update drawable when button is VISIBLE
        mCompoundButton.setVisibility(View.VISIBLE);
        Drawable secondDrawable = mActivity.getDrawable(R.drawable.pass);
        secondDrawable.setVisible(true, false);
        assertEquals(StateSet.WILD_CARD, secondDrawable.getState());

        mCompoundButton.setButtonDrawable(secondDrawable);
        assertSame(secondDrawable, mCompoundButton.getButtonDrawable());
        assertTrue(secondDrawable.isVisible());
        // the firstDrawable is not active.
        assertFalse(firstDrawable.isVisible());
    }

    @UiThreadTest
    @Test
    public void testSetButtonDrawableById() {
        // resId is 0
        mCompoundButton.setButtonDrawable(0);

        // set drawable
        mCompoundButton.setButtonDrawable(R.drawable.scenery);

        // set the same drawable again
        mCompoundButton.setButtonDrawable(R.drawable.scenery);

        // update drawable
        mCompoundButton.setButtonDrawable(R.drawable.pass);
    }

    @Test
    public void testOnCreateDrawableState() {
        // compoundButton is not checked, append 0 to state array.
        MockCompoundButton compoundButton = new MockCompoundButton(mActivity);
        int[] state = compoundButton.onCreateDrawableState(0);
        assertEquals(0, state[state.length - 1]);

        // compoundButton is checked, append R.attr.state_checked to state array.
        compoundButton.setChecked(true);
        int[] checkedState = compoundButton.onCreateDrawableState(0);
        assertEquals(state[0], checkedState[0]);
        assertEquals(android.R.attr.state_checked,
                checkedState[checkedState.length - 1]);

        // compoundButton is not checked again.
        compoundButton.setChecked(false);
        state = compoundButton.onCreateDrawableState(0);
        assertEquals(0, state[state.length - 1]);
    }

    @Test
    public void testOnDraw() {
        int viewHeight;
        int drawableWidth;
        int drawableHeight;
        Rect bounds;
        Drawable drawable;
        Canvas canvas = new Canvas(android.graphics.Bitmap.createBitmap(100, 100,
                android.graphics.Bitmap.Config.ARGB_8888));
        MockCompoundButton compoundButton;

        // onDraw when there is no drawable
        compoundButton = new MockCompoundButton(mActivity);
        compoundButton.onDraw(canvas);

        // onDraw when Gravity.TOP, it's default.
        compoundButton = new MockCompoundButton(mActivity);
        drawable = mActivity.getDrawable(R.drawable.scenery);
        compoundButton.setButtonDrawable(drawable);
        viewHeight = compoundButton.getHeight();
        drawableWidth = drawable.getIntrinsicWidth();
        drawableHeight = drawable.getIntrinsicHeight();

        compoundButton.onDraw(canvas);
        bounds = drawable.copyBounds();
        assertEquals(0, bounds.left);
        assertEquals(drawableWidth, bounds.right);
        assertEquals(0, bounds.top);
        assertEquals(drawableHeight, bounds.bottom);

        // onDraw when Gravity.BOTTOM
        compoundButton.setGravity(Gravity.BOTTOM);
        compoundButton.onDraw(canvas);
        bounds = drawable.copyBounds();
        assertEquals(0, bounds.left);
        assertEquals(drawableWidth, bounds.right);
        assertEquals(viewHeight - drawableHeight, bounds.top);
        assertEquals(viewHeight, bounds.bottom);

        // onDraw when Gravity.CENTER_VERTICAL
        compoundButton.setGravity(Gravity.CENTER_VERTICAL);
        compoundButton.onDraw(canvas);
        bounds = drawable.copyBounds();
        assertEquals(0, bounds.left);
        assertEquals(drawableWidth, bounds.right);
        assertEquals( (viewHeight - drawableHeight) / 2, bounds.top);
        assertEquals( (viewHeight - drawableHeight) / 2 + drawableHeight, bounds.bottom);
    }

    @UiThreadTest
    @Test
    public void testAccessInstanceState() {
        Parcelable state;

        assertFalse(mCompoundButton.isChecked());
        assertFalse(mCompoundButton.getFreezesText());

        state = mCompoundButton.onSaveInstanceState();
        assertNotNull(state);
        assertFalse(mCompoundButton.getFreezesText());

        mCompoundButton.setChecked(true);

        mCompoundButton.onRestoreInstanceState(state);
        assertFalse(mCompoundButton.isChecked());
        assertTrue(mCompoundButton.isLayoutRequested());
    }

    @Test
    public void testVerifyDrawable() {
        MockCompoundButton compoundButton = new MockCompoundButton(mActivity);
        Drawable drawable = mActivity.getDrawable(R.drawable.scenery);

        assertTrue(compoundButton.verifyDrawable(null));
        assertFalse(compoundButton.verifyDrawable(drawable));

        compoundButton.setButtonDrawable(drawable);
        assertTrue(compoundButton.verifyDrawable(null));
        assertTrue(compoundButton.verifyDrawable(drawable));
    }

    @UiThreadTest
    @Test
    public void testButtonTint() {
        CompoundButton tintedButton = (CompoundButton) mActivity.findViewById(R.id.button_tint);

        assertEquals("Button tint inflated correctly",
                Color.WHITE, tintedButton.getButtonTintList().getDefaultColor());
        assertEquals("Button tint mode inflated correctly",
                PorterDuff.Mode.SRC_OVER, tintedButton.getButtonTintMode());

        Drawable mockDrawable = spy(new ColorDrawable(Color.GREEN));

        mCompoundButton.setButtonDrawable(mockDrawable);
        // No button tint applied by default
        verify(mockDrawable, never()).setTintList(any(ColorStateList.class));

        mCompoundButton.setButtonTintList(ColorStateList.valueOf(Color.WHITE));
        // Button tint applied when setButtonTintList() called after setButton()
        verify(mockDrawable, times(1)).setTintList(TestUtils.colorStateListOf(Color.WHITE));

        reset(mockDrawable);
        mCompoundButton.setButtonDrawable(null);
        mCompoundButton.setButtonDrawable(mockDrawable);
        // Button tint applied when setButtonTintList() called before setButton()
        verify(mockDrawable, times(1)).setTintList(TestUtils.colorStateListOf(Color.WHITE));
    }

    public static final class MockCompoundButton extends CompoundButton {
        public MockCompoundButton(Context context) {
            super(context);
        }

        public MockCompoundButton(Context context, AttributeSet attrs) {
            super(context, attrs, 0);
        }

        public MockCompoundButton(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }

        @Override
        protected void drawableStateChanged() {
            super.drawableStateChanged();
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
        }

        @Override
        protected int[] onCreateDrawableState(int extraSpace) {
            return super.onCreateDrawableState(extraSpace);
        }

        @Override
        protected boolean verifyDrawable(Drawable who) {
            return super.verifyDrawable(who);
        }
    }
}
