/*
 * 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 android.widget.cts;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.app.Activity;
import android.app.Instrumentation;
import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Process;
import android.platform.test.annotations.AppModeFull;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.RemoteViews;
import android.widget.RemoteViewsService;
import android.widget.StackView;
import android.widget.cts.appwidget.MyAppWidgetProvider;
import android.widget.cts.appwidget.MyAppWidgetService;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;

import com.android.compatibility.common.util.PollingCheck;
import com.android.compatibility.common.util.SystemUtil;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Test {@link RemoteViews} that expect to operate within a {@link AppWidgetHostView} root.
 */
@LargeTest
@AppModeFull
@RunWith(AndroidJUnit4.class)
public class RemoteViewsWidgetTest {
    public static final String[] COUNTRY_LIST = new String[] {
        "Argentina", "Australia", "Belize", "Botswana", "Brazil", "Cameroon", "China", "Cyprus",
        "Denmark", "Djibouti", "Ethiopia", "Fiji", "Finland", "France", "Gabon", "Germany",
        "Ghana", "Haiti", "Honduras", "Iceland", "India", "Indonesia", "Ireland", "Italy",
        "Japan", "Kiribati", "Laos", "Lesotho", "Liberia", "Malaysia", "Mongolia", "Myanmar",
        "Nauru", "Norway", "Oman", "Pakistan", "Philippines", "Portugal", "Romania", "Russia",
        "Rwanda", "Singapore", "Slovakia", "Slovenia", "Somalia", "Swaziland", "Togo", "Tuvalu",
        "Uganda", "Ukraine", "United States", "Vanuatu", "Venezuela", "Zimbabwe"
    };

    private static final String GRANT_BIND_APP_WIDGET_PERMISSION_COMMAND =
        "appwidget grantbind --package android.widget.cts --user 0";

    private static final String REVOKE_BIND_APP_WIDGET_PERMISSION_COMMAND =
        "appwidget revokebind --package android.widget.cts --user 0";

    private static final long TEST_TIMEOUT_MS = 5000;

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

    private Instrumentation mInstrumentation;

    private Context mContext;

    private boolean mHasAppWidgets;

    private AppWidgetHostView mAppWidgetHostView;

    private int mAppWidgetId;

    private StackView mStackView;

    private ListView mListView;

    private AppWidgetHost mAppWidgetHost;

    @Before
    public void setup() throws Throwable {
        mInstrumentation = InstrumentationRegistry.getInstrumentation();
        mContext = mInstrumentation.getTargetContext();

        mHasAppWidgets = hasAppWidgets();
        if (!mHasAppWidgets) {
            return;
        }

        // We want to bind widgets - run a shell command to grant bind permission to our
        // package.
        grantBindAppWidgetPermission();

        mAppWidgetHost = new AppWidgetHost(mContext, 0);

        mAppWidgetHost.deleteHost();
        mAppWidgetHost.startListening();

        // Configure the app widget provider behavior
        final CountDownLatch providerCountDownLatch = new CountDownLatch(2);
        MyAppWidgetProvider.configure(providerCountDownLatch, null, null);

        // Grab the provider to be bound
        final AppWidgetProviderInfo providerInfo = getAppWidgetProviderInfo();

        // Allocate a widget id to bind
        mAppWidgetId = mAppWidgetHost.allocateAppWidgetId();

        // Bind the app widget
        boolean isBinding = getAppWidgetManager().bindAppWidgetIdIfAllowed(mAppWidgetId,
                providerInfo.getProfile(), providerInfo.provider, null);
        assertTrue(isBinding);

        // Wait for onEnabled and onUpdate calls on our provider
        try {
            assertTrue(providerCountDownLatch.await(TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS));
        } catch (InterruptedException ie) {
            fail(ie.getMessage());
        }

        // Configure the app widget service behavior
        final CountDownLatch factoryCountDownLatch = new CountDownLatch(2);
        RemoteViewsService.RemoteViewsFactory factory =
                mock(RemoteViewsService.RemoteViewsFactory.class);
        when(factory.getCount()).thenReturn(COUNTRY_LIST.length);
        doAnswer(new Answer<RemoteViews>() {
            @Override
            public RemoteViews answer(InvocationOnMock invocation) throws Throwable {
                final int position = (Integer) invocation.getArguments()[0];
                RemoteViews remoteViews = new RemoteViews(mContext.getPackageName(),
                        R.layout.remoteviews_adapter_item);
                remoteViews.setTextViewText(R.id.item, COUNTRY_LIST[position]);

                // Set a fill-intent which will be used to fill-in the pending intent template
                // which is set on the collection view in MyAppWidgetProvider.
                Bundle extras = new Bundle();
                extras.putString(MockURLSpanTestActivity.KEY_PARAM, COUNTRY_LIST[position]);
                Intent fillInIntent = new Intent();
                fillInIntent.putExtras(extras);
                remoteViews.setOnClickFillInIntent(R.id.item, fillInIntent);

                if (position == 0) {
                    factoryCountDownLatch.countDown();
                }
                return remoteViews;
            }
        }).when(factory).getViewAt(any(int.class));
        when(factory.getViewTypeCount()).thenReturn(1);
        MyAppWidgetService.setFactory(factory);

        mActivityRule.runOnUiThread(
                () -> mAppWidgetHostView = mAppWidgetHost.createView(
                        mContext, mAppWidgetId, providerInfo));

        // Wait our factory to be called to create the first item
        try {
            assertTrue(factoryCountDownLatch.await(TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS));
        } catch (InterruptedException ie) {
            fail(ie.getMessage());
        }

        // Add our host view to the activity behind this test. This is similar to how launchers
        // add widgets to the on-screen UI.
        ViewGroup root = (ViewGroup) mActivityRule.getActivity().findViewById(R.id.remoteView_host);
        FrameLayout.MarginLayoutParams lp = new FrameLayout.MarginLayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        mAppWidgetHostView.setLayoutParams(lp);

        mActivityRule.runOnUiThread(() -> root.addView(mAppWidgetHostView));
    }

    @After
    public void teardown() {
        if (!mHasAppWidgets) {
            return;
        }
        mAppWidgetHost.deleteHost();
        revokeBindAppWidgetPermission();
    }

    private void grantBindAppWidgetPermission() {
        try {
            SystemUtil.runShellCommand(mInstrumentation, GRANT_BIND_APP_WIDGET_PERMISSION_COMMAND);
        } catch (IOException e) {
            fail("Error granting app widget permission. Command: "
                    + GRANT_BIND_APP_WIDGET_PERMISSION_COMMAND + ": ["
                    + e.getMessage() + "]");
        }
    }

    private void revokeBindAppWidgetPermission() {
        try {
            SystemUtil.runShellCommand(mInstrumentation, REVOKE_BIND_APP_WIDGET_PERMISSION_COMMAND);
        } catch (IOException e) {
            fail("Error revoking app widget permission. Command: "
                    + REVOKE_BIND_APP_WIDGET_PERMISSION_COMMAND + ": ["
                    + e.getMessage() + "]");
        }
    }

    private boolean hasAppWidgets() {
        return mInstrumentation.getTargetContext().getPackageManager()
                .hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS);
    }

    private AppWidgetManager getAppWidgetManager() {
        return (AppWidgetManager) mContext.getSystemService(Context.APPWIDGET_SERVICE);
    }

    private AppWidgetProviderInfo getAppWidgetProviderInfo() {
        ComponentName firstComponentName = new ComponentName(mContext.getPackageName(),
                MyAppWidgetProvider.class.getName());

        return getProviderInfo(firstComponentName);
    }

    private AppWidgetProviderInfo getProviderInfo(ComponentName componentName) {
        List<AppWidgetProviderInfo> providers = getAppWidgetManager().getInstalledProviders();

        final int providerCount = providers.size();
        for (int i = 0; i < providerCount; i++) {
            AppWidgetProviderInfo provider = providers.get(i);
            if (componentName.equals(provider.provider)
                    && Process.myUserHandle().equals(provider.getProfile())) {
                return provider;

            }
        }

        return null;
    }

    @Test
    public void testInitialState() {
        if (!mHasAppWidgets) {
            return;
        }

        assertNotNull(mAppWidgetHostView);
        mStackView = (StackView) mAppWidgetHostView.findViewById(R.id.remoteViews_stack);
        assertNotNull(mStackView);

        assertEquals(COUNTRY_LIST.length, mStackView.getCount());
        assertEquals(0, mStackView.getDisplayedChild());
        assertEquals(R.id.remoteViews_empty, mStackView.getEmptyView().getId());
    }

    private void verifySetDisplayedChild(int displayedChildIndex) {
        final CountDownLatch updateLatch = new CountDownLatch(1);
        MyAppWidgetProvider.configure(updateLatch, null, null);

        // Create the intent to update the widget. Note that we're passing the value
        // for displayed child index in the intent
        Intent intent = new Intent(mContext, MyAppWidgetProvider.class);
        intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new  int[] { mAppWidgetId });
        intent.putExtra(MyAppWidgetProvider.KEY_DISPLAYED_CHILD_INDEX, displayedChildIndex);
        mContext.sendBroadcast(intent);

        // Wait until the update request has been processed
        try {
            assertTrue(updateLatch.await(TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS));
        } catch (InterruptedException ie) {
            fail(ie.getMessage());
        }
        // And wait until the underlying StackView has been updated to switch to the requested
        // child
        PollingCheck.waitFor(TEST_TIMEOUT_MS,
                () -> mStackView.getDisplayedChild() == displayedChildIndex);
    }

    @Test
    public void testSetDisplayedChild() {
        if (!mHasAppWidgets) {
            return;
        }

        mStackView = (StackView) mAppWidgetHostView.findViewById(R.id.remoteViews_stack);

        verifySetDisplayedChild(4);
        verifySetDisplayedChild(2);
        verifySetDisplayedChild(6);
    }

    private void verifyShowCommand(String intentShowKey, int expectedDisplayedChild) {
        final CountDownLatch updateLatch = new CountDownLatch(1);
        MyAppWidgetProvider.configure(updateLatch, null, null);

        // Create the intent to update the widget. Note that we're passing the "indication"
        // which one of showNext / showPrevious APIs to execute in the intent that we're
        // creating.
        Intent intent = new Intent(mContext, MyAppWidgetProvider.class);
        intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new  int[] { mAppWidgetId });
        intent.putExtra(intentShowKey, true);
        mContext.sendBroadcast(intent);

        // Wait until the update request has been processed
        try {
            assertTrue(updateLatch.await(TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS));
        } catch (InterruptedException ie) {
            fail(ie.getMessage());
        }
        // And wait until the underlying StackView has been updated to switch to the expected
        // child
        PollingCheck.waitFor(TEST_TIMEOUT_MS,
                () -> mStackView.getDisplayedChild() == expectedDisplayedChild);
    }

    @Test
    public void testShowNextPrevious() {
        if (!mHasAppWidgets) {
            return;
        }

        mStackView = (StackView) mAppWidgetHostView.findViewById(R.id.remoteViews_stack);

        // Two forward
        verifyShowCommand(MyAppWidgetProvider.KEY_SHOW_NEXT, 1);
        verifyShowCommand(MyAppWidgetProvider.KEY_SHOW_NEXT, 2);
        // Four back (looping to the end of the adapter data)
        verifyShowCommand(MyAppWidgetProvider.KEY_SHOW_PREVIOUS, 1);
        verifyShowCommand(MyAppWidgetProvider.KEY_SHOW_PREVIOUS, 0);
        verifyShowCommand(MyAppWidgetProvider.KEY_SHOW_PREVIOUS, COUNTRY_LIST.length - 1);
        verifyShowCommand(MyAppWidgetProvider.KEY_SHOW_PREVIOUS, COUNTRY_LIST.length - 2);
        // And three forward (looping to the start of the adapter data)
        verifyShowCommand(MyAppWidgetProvider.KEY_SHOW_NEXT, COUNTRY_LIST.length - 1);
        verifyShowCommand(MyAppWidgetProvider.KEY_SHOW_NEXT, 0);
        verifyShowCommand(MyAppWidgetProvider.KEY_SHOW_NEXT, 1);
    }

    private void verifyItemClickIntents(int indexToClick) throws Throwable {
        Instrumentation.ActivityMonitor am = mInstrumentation.addMonitor(
                MockURLSpanTestActivity.class.getName(), null, false);

        mStackView = (StackView) mAppWidgetHostView.findViewById(R.id.remoteViews_stack);
        PollingCheck.waitFor(() -> mStackView.getCurrentView() != null);
        final View initialView = mStackView.getCurrentView();
        mActivityRule.runOnUiThread(
                () -> mStackView.performItemClick(initialView, indexToClick, 0L));

        Activity newActivity = am.waitForActivityWithTimeout(TEST_TIMEOUT_MS);
        assertNotNull(newActivity);
        assertTrue(newActivity instanceof MockURLSpanTestActivity);
        assertEquals(COUNTRY_LIST[indexToClick], ((MockURLSpanTestActivity) newActivity).getParam());
        newActivity.finish();
    }

    @Test
    public void testSetOnClickPendingIntent() throws Throwable {
        if (!mHasAppWidgets) {
            return;
        }

        verifyItemClickIntents(0);

        // Switch to another child
        verifySetDisplayedChild(2);
        verifyItemClickIntents(2);

        // And one more
        verifyShowCommand(MyAppWidgetProvider.KEY_SHOW_NEXT, 3);
        verifyItemClickIntents(3);
    }

    private class ListScrollListener implements AbsListView.OnScrollListener {
        private CountDownLatch mLatchToNotify;

        private int mTargetPosition;

        public ListScrollListener(CountDownLatch latchToNotify, int targetPosition) {
            mLatchToNotify = latchToNotify;
            mTargetPosition = targetPosition;
        }

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                int totalItemCount) {
            if ((mTargetPosition >= firstVisibleItem) &&
                    (mTargetPosition <= (firstVisibleItem + visibleItemCount))) {
                mLatchToNotify.countDown();
            }
        }
    }

    @Test
    public void testSetScrollPosition() {
        if (!mHasAppWidgets) {
            return;
        }

        mListView = (ListView) mAppWidgetHostView.findViewById(R.id.remoteViews_list);

        final CountDownLatch updateLatch = new CountDownLatch(1);
        final AtomicBoolean scrollToPositionIsComplete = new AtomicBoolean(false);
        // We're configuring our provider with three parameters:
        // 1. The CountDownLatch to be notified when the provider has been enabled
        // 2. The gating condition that waits until ListView has populated its content
        //    so that we can proceed to call setScrollPosition on it
        // 3. The gating condition that waits until the setScrollPosition has completed
        //    its processing / scrolling so that we can proceed to call
        //    setRelativeScrollPosition on it
        MyAppWidgetProvider.configure(updateLatch, () -> mListView.getChildCount() > 0,
                scrollToPositionIsComplete::get);

        final int positionToScrollTo = COUNTRY_LIST.length - 10;
        final int scrollByAmount = COUNTRY_LIST.length / 2;
        final int offsetScrollTarget = positionToScrollTo - scrollByAmount;

        // Register the first scroll listener on our ListView. The listener will notify our latch
        // when the "target" item comes into view. If that never happens, the latch will
        // time out and fail the test.
        final CountDownLatch scrollToPositionLatch = new CountDownLatch(1);
        mListView.setOnScrollListener(
                new ListScrollListener(scrollToPositionLatch, positionToScrollTo));

        // Create the intent to update the widget. Note that we're passing the "indication"
        // to switch to our ListView in the intent that we're creating.
        Intent intent = new Intent(mContext, MyAppWidgetProvider.class);
        intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new  int[] { mAppWidgetId });
        intent.putExtra(MyAppWidgetProvider.KEY_SWITCH_TO_LIST, true);
        intent.putExtra(MyAppWidgetProvider.KEY_SCROLL_POSITION, positionToScrollTo);
        intent.putExtra(MyAppWidgetProvider.KEY_SCROLL_OFFSET, -scrollByAmount);
        mContext.sendBroadcast(intent);

        // Wait until the update request has been processed
        try {
            assertTrue(updateLatch.await(TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS));
        } catch (InterruptedException ie) {
            fail(ie.getMessage());
        }
        // And wait until the underlying ListView has been updated to be visible
        PollingCheck.waitFor(TEST_TIMEOUT_MS, () -> mListView.getVisibility() == View.VISIBLE);

        // Wait until our ListView has at least one visible child view. At that point we know
        // that not only the host view is on screen, but also that the list view has completed
        // its layout pass after having asked its adapter to populate the list content.
        PollingCheck.waitFor(TEST_TIMEOUT_MS, () -> mListView.getChildCount() > 0);

        // If we're on a really big display, we might be in a situation where the position
        // we're going to scroll to is already visible. In that case the logic in the rest
        // of this test will never fire off a listener callback and then fail the test.
        final int lastVisiblePosition = mListView.getLastVisiblePosition();
        if (positionToScrollTo <= lastVisiblePosition) {
            return;
        }

        boolean result = false;
        try {
            result = scrollToPositionLatch.await(20, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            // ignore
        }
        assertTrue("Timed out while waiting for the target view to be scrolled into view", result);

        if ((offsetScrollTarget < 0) ||
                (offsetScrollTarget >= mListView.getFirstVisiblePosition())) {
            // We can't scroll up because the target is either already visible or negative
            return;
        }

        // Now register another scroll listener on our ListView. The listener will notify our latch
        // when our new "target" item comes into view. If that never happens, the latch will
        // time out and fail the test.
        final CountDownLatch scrollByOffsetLatch = new CountDownLatch(1);
        mListView.setOnScrollListener(
                new ListScrollListener(scrollByOffsetLatch, offsetScrollTarget));

        // Update our atomic boolean to "kick off" the widget provider request to call
        // setRelativeScrollPosition on our RemoteViews
        scrollToPositionIsComplete.set(true);
        try {
            result = scrollByOffsetLatch.await(20, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            // ignore
        }
        assertTrue("Timed out while waiting for the target view to be scrolled into view", result);
    }
}
