/*
 * Copyright (C) 2014 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 com.android.cts.verifier.notifications;

import android.app.Notification;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import com.android.cts.verifier.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Tests that the notification ranker honors user preferences about package priority.
 * Users can, in Settings, specify a package as being high priority. This should
 * result in the notificaitons from that package being ranked higher than those from
 * other packages.
 */
public class PackagePriorityVerifierActivity
        extends InteractiveVerifierActivity {
    private static final String ACTION_POST = "com.android.cts.robot.ACTION_POST";
    private static final String ACTION_CANCEL = "com.android.cts.robot.ACTION_CANCEL";
    private static final String EXTRA_ID = "ID";
    private static final String EXTRA_NOTIFICATION = "NOTIFICATION";
    static final String NOTIFICATION_BOT_PACKAGE = "com.android.cts.robot";
    private CharSequence mAppLabel;

    @Override
    int getTitleResource() {
        return R.string.package_priority_test;
    }

    @Override
    int getInstructionsResource() {
        return R.string.package_priority_info;
    }

    // Test Setup

    @Override
    protected List<InteractiveTestCase> createTestItems() {
        mAppLabel = getString(R.string.app_name);
        List<InteractiveTestCase> tests = new ArrayList<>(17);
        tests.add(new CheckForBot());
        tests.add(new IsEnabledTest());
        tests.add(new ServiceStartedTest());
        tests.add(new WaitForSetPriorityDefault());
        tests.add(new DefaultOrderTest());
        tests.add(new WaitForSetPriorityHigh());
        tests.add(new PackagePriorityOrderTest());
        return tests;
    }

    // Tests

    /** Make sure the helper package is installed. */
    protected class CheckForBot extends InteractiveTestCase {
        @Override
        View inflate(ViewGroup parent) {
            return createAutoItem(parent, R.string.package_priority_bot);
        }

        @Override
        void test() {
            PackageManager pm = mContext.getPackageManager();
            try {
                pm.getPackageInfo(NOTIFICATION_BOT_PACKAGE, 0);
                status = PASS;
            } catch (PackageManager.NameNotFoundException e) {
                status = FAIL;
                logFail("You must install the CTS Robot helper, aka " + NOTIFICATION_BOT_PACKAGE);
            }
            next();
        }
    }

    /** Wait for the user to set the target package priority to default. */
    protected class WaitForSetPriorityDefault extends InteractiveTestCase {
        @Override
        View inflate(ViewGroup parent) {
            return createRetryItem(parent, R.string.package_priority_default, mAppLabel);
        }

        @Override
        void setUp() {
            Log.i("WaitForSetPriorityDefault", "waiting for user");
            status = WAIT_FOR_USER;
        }

        @Override
        void test() {
            status = PASS;
            next();
        }

        @Override
        void tearDown() {
            MockListener.resetListenerData(mContext);
            delay();
        }
    }

    /** Wait for the user to set the target package priority to high. */
    protected class WaitForSetPriorityHigh extends InteractiveTestCase {
        @Override
        View inflate(ViewGroup parent) {
            return createRetryItem(parent, R.string.package_priority_high, mAppLabel);
        }

        @Override
        void setUp() {
            Log.i("WaitForSetPriorityHigh", "waiting for user");
            status = WAIT_FOR_USER;
        }

        @Override
        void test() {
            status = PASS;
            next();
        }

        @Override
        void tearDown() {
            MockListener.resetListenerData(mContext);
            delay();
        }
    }

    /**
     * With default priority, the notifcations should be reverse-ordered by time.
     * A is before B, and therefor should B should rank before A.
     */
    protected class DefaultOrderTest extends InteractiveTestCase {
        @Override
        View inflate(ViewGroup parent) {
            return createAutoItem(parent, R.string.attention_default_order);
        }

        @Override
        void setUp() {
            sendNotifications();
            status = READY;
            // wait for notifications to move through the system
            delay();
        }

        @Override
        void test() {
            MockListener.probeListenerOrder(mContext,
                    new MockListener.StringListResultCatcher() {
                        @Override
                        public void accept(List<String> orderedKeys) {
                            int rankA = indexOfPackageInKeys(orderedKeys, getPackageName());
                            int rankB = indexOfPackageInKeys(orderedKeys, NOTIFICATION_BOT_PACKAGE);
                            if (rankB != -1 && rankB < rankA) {
                                status = PASS;
                            } else {
                                logFail("expected rankA (" + rankA + ") > rankB (" + rankB + ")");
                                status = FAIL;
                            }
                            next();
                        }
                    });
            delay();  // in case the catcher never returns
        }

        @Override
        void tearDown() {
            cancelNotifications();
            MockListener.resetListenerData(mContext);
            delay();
        }
    }

    /**
     * With higher package priority, A should rank above B.
     */
    protected class PackagePriorityOrderTest extends InteractiveTestCase {
        @Override
        View inflate(ViewGroup parent) {
            return createAutoItem(parent, R.string.package_priority_user_order);
        }

        @Override
        void setUp() {
            sendNotifications();
            status = READY;
            // wait for notifications to move through the system
            delay();
        }

        @Override
        void test() {
            MockListener.probeListenerOrder(mContext,
                    new MockListener.StringListResultCatcher() {
                        @Override
                        public void accept(List<String> orderedKeys) {
                            int rankA = indexOfPackageInKeys(orderedKeys, getPackageName());
                            int rankB = indexOfPackageInKeys(orderedKeys, NOTIFICATION_BOT_PACKAGE);
                            if (rankA != -1 && rankA < rankB) {
                                status = PASS;
                            } else {
                                logFail("expected rankA (" + rankA + ") < rankB (" + rankB + ")");
                                status = FAIL;
                            }
                            next();
                        }
                    });
            delay();  // in case the catcher never returns
        }

        @Override
        void tearDown() {
            cancelNotifications();
            MockListener.resetListenerData(mContext);
            delay();
        }
    }
    // Utilities

    private void sendNotifications() {
        // post ours first, with an explicit time in the past to avoid any races.
        Notification.Builder alice = new Notification.Builder(mContext)
                .setContentTitle("alice title")
                .setContentText("alice content")
                .setSmallIcon(R.drawable.ic_stat_alice)
                .setWhen(System.currentTimeMillis() - 10000L)
                .setPriority(Notification.PRIORITY_DEFAULT);
        mNm.notify(0, alice.build());

        // then post theirs, so it should be higher by default due to recency
        Notification.Builder bob = new Notification.Builder(mContext)
                .setContentTitle("bob title")
                .setContentText("bob content")
                .setSmallIcon(android.R.drawable.stat_notify_error) // must be global resource
                .setWhen(System.currentTimeMillis())
                .setPriority(Notification.PRIORITY_DEFAULT);
        Intent postIntent = new Intent(ACTION_POST);
        postIntent.setPackage(NOTIFICATION_BOT_PACKAGE);
        postIntent.putExtra(EXTRA_ID, 0);
        postIntent.putExtra(EXTRA_NOTIFICATION, bob.build());
        postIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
        sendBroadcast(postIntent);
    }

    private void cancelNotifications() {
        //cancel ours
        mNm.cancelAll();
        //cancel theirs
        Intent cancelIntent = new Intent(ACTION_CANCEL);
        cancelIntent.setPackage(NOTIFICATION_BOT_PACKAGE);
        cancelIntent.putExtra(EXTRA_ID, 0);
        cancelIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
        sendBroadcast(cancelIntent);
    }

    /** Search a list of notification keys for a given packageName. */
    private int indexOfPackageInKeys(List<String> orderedKeys, String packageName) {
        for (int i = 0; i < orderedKeys.size(); i++) {
            if (orderedKeys.get(i).contains(packageName)) {
                return i;
            }
        }
        return -1;
    }
}
