/*
 * Copyright (C) 2016 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 androidx.transition;

import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.lessThan;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;

import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.os.Build;
import android.support.test.InstrumentationRegistry;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.MediumTest;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.junit.Before;
import org.junit.Test;

@MediumTest
public class FadeTest extends BaseTest {

    private View mView;
    private ViewGroup mRoot;

    @UiThreadTest
    @Before
    public void setUp() {
        mRoot = rule.getActivity().getRoot();
        mView = new View(rule.getActivity());
        mRoot.addView(mView, new ViewGroup.LayoutParams(100, 100));
    }

    @Test
    public void testMode() {
        assertThat(Fade.IN, is(Visibility.MODE_IN));
        assertThat(Fade.OUT, is(Visibility.MODE_OUT));
        final Fade fade = new Fade();
        assertThat(fade.getMode(), is(Visibility.MODE_IN | Visibility.MODE_OUT));
        fade.setMode(Visibility.MODE_IN);
        assertThat(fade.getMode(), is(Visibility.MODE_IN));
    }

    @Test
    @UiThreadTest
    public void testDisappear() {
        final Fade fade = new Fade();
        final TransitionValues startValues = new TransitionValues();
        startValues.view = mView;
        fade.captureStartValues(startValues);
        mView.setVisibility(View.INVISIBLE);
        final TransitionValues endValues = new TransitionValues();
        endValues.view = mView;
        fade.captureEndValues(endValues);
        Animator animator = fade.createAnimator(mRoot, startValues, endValues);
        assertThat(animator, is(notNullValue()));
    }

    @Test
    @UiThreadTest
    public void testAppear() {
        mView.setVisibility(View.INVISIBLE);
        final Fade fade = new Fade();
        final TransitionValues startValues = new TransitionValues();
        startValues.view = mView;
        fade.captureStartValues(startValues);
        mView.setVisibility(View.VISIBLE);
        final TransitionValues endValues = new TransitionValues();
        endValues.view = mView;
        fade.captureEndValues(endValues);
        Animator animator = fade.createAnimator(mRoot, startValues, endValues);
        assertThat(animator, is(notNullValue()));
    }

    @Test
    @UiThreadTest
    public void testNoChange() {
        final Fade fade = new Fade();
        final TransitionValues startValues = new TransitionValues();
        startValues.view = mView;
        fade.captureStartValues(startValues);
        final TransitionValues endValues = new TransitionValues();
        endValues.view = mView;
        fade.captureEndValues(endValues);
        Animator animator = fade.createAnimator(mRoot, startValues, endValues);
        // No visibility change; no animation should happen
        assertThat(animator, is(nullValue()));
    }

    @Test
    public void testFadeOutThenIn() throws Throwable {
        // Fade out
        final Runnable interrupt = mock(Runnable.class);
        float[] valuesOut = new float[2];
        final InterruptibleFade fadeOut = new InterruptibleFade(Fade.MODE_OUT, interrupt,
                valuesOut);
        final Transition.TransitionListener listenerOut = mock(Transition.TransitionListener.class);
        fadeOut.addListener(listenerOut);
        changeVisibility(fadeOut, mRoot, mView, View.INVISIBLE);
        verify(listenerOut, timeout(3000)).onTransitionStart(any(Transition.class));

        // The view is in the middle of fading out
        verify(interrupt, timeout(3000)).run();

        // Fade in
        float[] valuesIn = new float[2];
        final InterruptibleFade fadeIn = new InterruptibleFade(Fade.MODE_IN, null, valuesIn);
        final Transition.TransitionListener listenerIn = mock(Transition.TransitionListener.class);
        fadeIn.addListener(listenerIn);
        changeVisibility(fadeIn, mRoot, mView, View.VISIBLE);
        verify(listenerOut, timeout(3000)).onTransitionPause(any(Transition.class));
        verify(listenerIn, timeout(3000)).onTransitionStart(any(Transition.class));
        assertThat(valuesOut[1], allOf(greaterThan(0f), lessThan(1f)));
        if (Build.VERSION.SDK_INT >= 19 && fadeOut.mInitialAlpha >= 0) {
            // These won't match on API levels 18 and below due to lack of Animator pause.
            assertEquals(valuesOut[1], valuesIn[0], 0.01f);
        }

        verify(listenerIn, timeout(3000)).onTransitionEnd(any(Transition.class));
        assertThat(mView.getVisibility(), is(View.VISIBLE));
        assertEquals(valuesIn[1], 1.f, 0.01f);
    }

    @Test
    public void testFadeInThenOut() throws Throwable {
        changeVisibility(null, mRoot, mView, View.INVISIBLE);
        InstrumentationRegistry.getInstrumentation().waitForIdleSync();

        // Fade in
        final Runnable interrupt = mock(Runnable.class);
        float[] valuesIn = new float[2];
        final InterruptibleFade fadeIn = new InterruptibleFade(Fade.MODE_IN, interrupt, valuesIn);
        final Transition.TransitionListener listenerIn = mock(Transition.TransitionListener.class);
        fadeIn.addListener(listenerIn);
        changeVisibility(fadeIn, mRoot, mView, View.VISIBLE);
        verify(listenerIn, timeout(3000)).onTransitionStart(any(Transition.class));

        // The view is in the middle of fading in
        verify(interrupt, timeout(3000)).run();

        // Fade out
        float[] valuesOut = new float[2];
        final InterruptibleFade fadeOut = new InterruptibleFade(Fade.MODE_OUT, null, valuesOut);
        final Transition.TransitionListener listenerOut = mock(Transition.TransitionListener.class);
        fadeOut.addListener(listenerOut);
        changeVisibility(fadeOut, mRoot, mView, View.INVISIBLE);
        verify(listenerIn, timeout(3000)).onTransitionPause(any(Transition.class));
        verify(listenerOut, timeout(3000)).onTransitionStart(any(Transition.class));
        assertThat(valuesIn[1], allOf(greaterThan(0f), lessThan(1f)));
        if (Build.VERSION.SDK_INT >= 19 && fadeIn.mInitialAlpha >= 0) {
            // These won't match on API levels 18 and below due to lack of Animator pause.
            assertEquals(valuesIn[1], valuesOut[0], 0.01f);
        }

        verify(listenerOut, timeout(3000)).onTransitionEnd(any(Transition.class));
        assertThat(mView.getVisibility(), is(View.INVISIBLE));
    }

    @Test
    public void testFadeWithAlpha() throws Throwable {
        // Set the view alpha to 0.5
        rule.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mView.setAlpha(0.5f);
            }
        });
        // Fade out
        final Fade fadeOut = new Fade(Fade.OUT);
        final Transition.TransitionListener listenerOut = mock(Transition.TransitionListener.class);
        fadeOut.addListener(listenerOut);
        changeVisibility(fadeOut, mRoot, mView, View.INVISIBLE);
        verify(listenerOut, timeout(3000)).onTransitionStart(any(Transition.class));
        verify(listenerOut, timeout(3000)).onTransitionEnd(any(Transition.class));
        // Fade in
        final Fade fadeIn = new Fade(Fade.IN);
        final Transition.TransitionListener listenerIn = mock(Transition.TransitionListener.class);
        fadeIn.addListener(listenerIn);
        changeVisibility(fadeIn, mRoot, mView, View.VISIBLE);
        verify(listenerIn, timeout(3000)).onTransitionStart(any(Transition.class));
        verify(listenerIn, timeout(3000)).onTransitionEnd(any(Transition.class));
        // Confirm that the view still has the original alpha value
        assertThat(mView.getVisibility(), is(View.VISIBLE));
        assertEquals(0.5f, mView.getAlpha(), 0.01f);
    }

    private void changeVisibility(final Fade fade, final ViewGroup container, final View target,
            final int visibility) throws Throwable {
        rule.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (fade != null) {
                    TransitionManager.beginDelayedTransition(container, fade);
                }
                target.setVisibility(visibility);
            }
        });
    }

    /**
     * A special version of {@link Fade} that runs a specified {@link Runnable} soon after the
     * target starts fading in or out.
     */
    private static class InterruptibleFade extends Fade {

        static final float ALPHA_THRESHOLD = 0.2f;

        float mInitialAlpha = -1;
        Runnable mMiddle;
        final float[] mAlphaValues;

        InterruptibleFade(int mode, Runnable middle, float[] alphaValues) {
            super(mode);
            mMiddle = middle;
            mAlphaValues = alphaValues;
        }

        @Nullable
        @Override
        public Animator createAnimator(@NonNull ViewGroup sceneRoot,
                @Nullable final TransitionValues startValues,
                @Nullable final TransitionValues endValues) {
            final Animator animator = super.createAnimator(sceneRoot, startValues, endValues);
            if (animator instanceof ObjectAnimator) {
                ((ObjectAnimator) animator).addUpdateListener(
                        new ValueAnimator.AnimatorUpdateListener() {
                            @Override
                            public void onAnimationUpdate(ValueAnimator animation) {
                                final float alpha = (float) animation.getAnimatedValue();
                                mAlphaValues[1] = alpha;
                                if (mInitialAlpha < 0) {
                                    mInitialAlpha = alpha;
                                    mAlphaValues[0] = mInitialAlpha;
                                } else if (Math.abs(alpha - mInitialAlpha) > ALPHA_THRESHOLD) {
                                    if (mMiddle != null) {
                                        mMiddle.run();
                                        mMiddle = null;
                                    }
                                }
                            }
                        });
            }
            return animator;
        }

    }

}
