/*
 * 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.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
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 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
@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() {
        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);
    }
}
