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

import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;

import android.Manifest;
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
import android.os.SystemClock;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.UiSelector;
import android.util.ArrayMap;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Switch;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.runner.RunWith;

import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeoutException;

@RunWith(AndroidJUnit4.class)
public abstract class BasePermissionsTest {
    private static final String PLATFORM_PACKAGE_NAME = "android";

    private static final long IDLE_TIMEOUT_MILLIS = 500;
    private static final long GLOBAL_TIMEOUT_MILLIS = 5000;

    private static final long RETRY_TIMEOUT = 5000;
    private static final String LOG_TAG = "BasePermissionsTest";

    private static Map<String, String> sPermissionToLabelResNameMap = new ArrayMap<>();
    static {
        // Contacts
        sPermissionToLabelResNameMap.put(Manifest.permission.READ_CONTACTS,
                "@android:string/permgrouplab_contacts");
        sPermissionToLabelResNameMap.put(Manifest.permission.WRITE_CONTACTS,
                "@android:string/permgrouplab_contacts");
        // Calendar
        sPermissionToLabelResNameMap.put(Manifest.permission.READ_CALENDAR,
                "@android:string/permgrouplab_calendar");
        sPermissionToLabelResNameMap.put(Manifest.permission.WRITE_CALENDAR,
                "@android:string/permgrouplab_calendar");
        // SMS
        sPermissionToLabelResNameMap.put(Manifest.permission.SEND_SMS,
                "@android:string/permgrouplab_sms");
        sPermissionToLabelResNameMap.put(Manifest.permission.RECEIVE_SMS,
                "@android:string/permgrouplab_sms");
        sPermissionToLabelResNameMap.put(Manifest.permission.READ_SMS,
                "@android:string/permgrouplab_sms");
        sPermissionToLabelResNameMap.put(Manifest.permission.RECEIVE_WAP_PUSH,
                "@android:string/permgrouplab_sms");
        sPermissionToLabelResNameMap.put(Manifest.permission.RECEIVE_MMS,
                "@android:string/permgrouplab_sms");
        sPermissionToLabelResNameMap.put("android.permission.READ_CELL_BROADCASTS",
                "@android:string/permgrouplab_sms");
        // Storage
        sPermissionToLabelResNameMap.put(Manifest.permission.READ_EXTERNAL_STORAGE,
                "@android:string/permgrouplab_storage");
        sPermissionToLabelResNameMap.put(Manifest.permission.WRITE_EXTERNAL_STORAGE,
                "@android:string/permgrouplab_storage");
        // Location
        sPermissionToLabelResNameMap.put(Manifest.permission.ACCESS_FINE_LOCATION,
                "@android:string/permgrouplab_location");
        sPermissionToLabelResNameMap.put(Manifest.permission.ACCESS_COARSE_LOCATION,
                "@android:string/permgrouplab_location");
        // Phone
        sPermissionToLabelResNameMap.put(Manifest.permission.READ_PHONE_STATE,
                "@android:string/permgrouplab_phone");
        sPermissionToLabelResNameMap.put(Manifest.permission.CALL_PHONE,
                "@android:string/permgrouplab_phone");
        sPermissionToLabelResNameMap.put("android.permission.ACCESS_IMS_CALL_SERVICE",
                "@android:string/permgrouplab_phone");
        sPermissionToLabelResNameMap.put(Manifest.permission.READ_CALL_LOG,
                "@android:string/permgrouplab_phone");
        sPermissionToLabelResNameMap.put(Manifest.permission.WRITE_CALL_LOG,
                "@android:string/permgrouplab_phone");
        sPermissionToLabelResNameMap.put(Manifest.permission.ADD_VOICEMAIL,
                "@android:string/permgrouplab_phone");
        sPermissionToLabelResNameMap.put(Manifest.permission.USE_SIP,
                "@android:string/permgrouplab_phone");
        sPermissionToLabelResNameMap.put(Manifest.permission.PROCESS_OUTGOING_CALLS,
                "@android:string/permgrouplab_phone");
        // Microphone
        sPermissionToLabelResNameMap.put(Manifest.permission.RECORD_AUDIO,
                "@android:string/permgrouplab_microphone");
        // Camera
        sPermissionToLabelResNameMap.put(Manifest.permission.CAMERA,
                "@android:string/permgrouplab_camera");
        // Body sensors
        sPermissionToLabelResNameMap.put(Manifest.permission.BODY_SENSORS,
                "@android:string/permgrouplab_sensors");
    }

    private Context mContext;
    private Resources mPlatformResources;

    protected static Instrumentation getInstrumentation() {
        return InstrumentationRegistry.getInstrumentation();
    }

    protected static void assertPermissionRequestResult(BasePermissionActivity.Result result,
            int requestCode, String[] permissions, boolean[] granted) {
        assertEquals(requestCode, result.requestCode);
        for (int i = 0; i < permissions.length; i++) {
            assertEquals(permissions[i], result.permissions[i]);
            assertEquals(granted[i] ? PackageManager.PERMISSION_GRANTED
                    : PackageManager.PERMISSION_DENIED, result.grantResults[i]);

        }
    }

    protected static UiDevice getUiDevice() {
        return UiDevice.getInstance(getInstrumentation());
    }

    protected static Activity launchActivity(String packageName,
            Class<?> clazz, Bundle extras) {
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.setClassName(packageName, clazz.getName());
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (extras != null) {
            intent.putExtras(extras);
        }
        Activity activity = getInstrumentation().startActivitySync(intent);
        getInstrumentation().waitForIdleSync();

        return activity;
    }

    @Before
    public void beforeTest() {
        mContext = InstrumentationRegistry.getTargetContext();
        try {
            Context platformContext = mContext.createPackageContext(PLATFORM_PACKAGE_NAME, 0);
            mPlatformResources = platformContext.getResources();
        } catch (PackageManager.NameNotFoundException e) {
            /* cannot happen */
        }

        UiObject2 button = getUiDevice().findObject(By.text("Close"));
        if (button != null) {
            button.click();
        }
    }

    protected BasePermissionActivity.Result requestPermissions(
            String[] permissions, int requestCode, Class<?> clazz, Runnable postRequestAction)
            throws Exception {
        // Start an activity
        BasePermissionActivity activity = (BasePermissionActivity) launchActivity(
                getInstrumentation().getTargetContext().getPackageName(), clazz, null);

        activity.waitForOnCreate();

        // Request the permissions
        activity.requestPermissions(permissions, requestCode);

        // Define a more conservative idle criteria
        getInstrumentation().getUiAutomation().waitForIdle(
                IDLE_TIMEOUT_MILLIS, GLOBAL_TIMEOUT_MILLIS);

        // Perform the post-request action
        if (postRequestAction != null) {
            postRequestAction.run();
        }

        BasePermissionActivity.Result result = activity.getResult();
        activity.finish();
        return result;
    }

    protected void clickAllowButton() throws Exception {
        getUiDevice().findObject(new UiSelector().resourceId(
                "com.android.packageinstaller:id/permission_allow_button")).click();
    }

    protected void clickDenyButton() throws Exception {
        getUiDevice().findObject(new UiSelector().resourceId(
                "com.android.packageinstaller:id/permission_deny_button")).click();
    }

    protected void clickDontAskAgainCheckbox() throws Exception {
        getUiDevice().findObject(new UiSelector().resourceId(
                "com.android.packageinstaller:id/do_not_ask_checkbox")).click();
    }

    protected void clickDontAskAgainButton() throws Exception {
        getUiDevice().findObject(new UiSelector().resourceId(
                "com.android.packageinstaller:id/permission_deny_dont_ask_again_button")).click();
    }

    protected void grantPermission(String permission) throws Exception {
        grantPermissions(new String[]{permission});
    }

    protected void grantPermissions(String[] permissions) throws Exception {
        setPermissionGrantState(permissions, true, false);
    }

    protected void revokePermission(String permission) throws Exception {
        revokePermissions(new String[] {permission}, false);
    }

    protected void revokePermissions(String[] permissions, boolean legacyApp) throws Exception {
        setPermissionGrantState(permissions, false, legacyApp);
    }

    private void setPermissionGrantState(String[] permissions, boolean granted,
            boolean legacyApp) throws Exception {
        getUiDevice().pressBack();
        waitForIdle();
        getUiDevice().pressBack();
        waitForIdle();
        getUiDevice().pressBack();
        waitForIdle();

        // Open the app details settings
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        intent.setData(Uri.parse("package:" + mContext.getPackageName()));
        startActivity(intent);

        waitForIdle();

        // Open the permissions UI
        AccessibilityNodeInfo permLabelView = getNodeTimed(() -> findByText("Permissions"));
        Assert.assertNotNull("Permissions label should be present", permLabelView);

        AccessibilityNodeInfo permItemView = findCollectionItem(permLabelView);
        Assert.assertNotNull("Permissions item should be present", permLabelView);

        click(permItemView);

        waitForIdle();

        for (String permission : permissions) {
            // Find the permission toggle
            String permissionLabel = getPermissionLabel(permission);

            AccessibilityNodeInfo labelView = getNodeTimed(() -> findByText(permissionLabel));
            Assert.assertNotNull("Permission label should be present", labelView);

            AccessibilityNodeInfo itemView = findCollectionItem(labelView);
            Assert.assertNotNull("Permission item should be present", itemView);

            final AccessibilityNodeInfo toggleView = findSwitch(itemView);
            Assert.assertNotNull("Permission toggle should be present", toggleView);

            final boolean wasGranted = toggleView.isChecked();
            if (granted != wasGranted) {
                // Toggle the permission

                if (!itemView.getActionList().contains(AccessibilityAction.ACTION_CLICK)) {
                    click(toggleView);
                } else {
                    click(itemView);
                }

                waitForIdle();

                if (wasGranted && legacyApp) {
                    String packageName = getInstrumentation().getContext().getPackageManager()
                            .getPermissionControllerPackageName();
                    String resIdName = "com.android.packageinstaller"
                            + ":string/grant_dialog_button_deny_anyway";
                    Resources resources = getInstrumentation().getContext()
                            .createPackageContext(packageName, 0).getResources();
                    final int confirmResId = resources.getIdentifier(resIdName, null, null);
                    String confirmTitle = resources.getString(confirmResId);
                    UiObject denyAnyway = getUiDevice().findObject(new UiSelector()
                            .text(confirmTitle.toUpperCase()));
                    denyAnyway.click();

                    waitForIdle();
                }
            }
        }

        getUiDevice().pressBack();
        waitForIdle();
        getUiDevice().pressBack();
        waitForIdle();
    }

    private String getPermissionLabel(String permission) throws Exception {
        String labelResName = sPermissionToLabelResNameMap.get(permission);
        assertNotNull("Unknown permisison " + permission, labelResName);
        final int resourceId = mPlatformResources.getIdentifier(labelResName, null, null);
        return mPlatformResources.getString(resourceId);
    }

    private void startActivity(final Intent intent) throws Exception {
        getInstrumentation().getUiAutomation().executeAndWaitForEvent(
                () -> {
            try {
                getInstrumentation().getContext().startActivity(intent);
            } catch (Exception e) {
                fail("Cannot start activity: " + intent);
            }
        }, (AccessibilityEvent event) -> event.getEventType()
                        == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
         , GLOBAL_TIMEOUT_MILLIS);
    }

    private AccessibilityNodeInfo findByText(String text) throws Exception {
        AccessibilityNodeInfo root = getInstrumentation().getUiAutomation().getRootInActiveWindow();
        AccessibilityNodeInfo result = findByText(root, text);
        if (result != null) {
            return result;
        }
        return findByTextInCollection(root, text);
    }

    private static AccessibilityNodeInfo findByText(AccessibilityNodeInfo root, String text) {
        List<AccessibilityNodeInfo> nodes = root.findAccessibilityNodeInfosByText(text);
        for (AccessibilityNodeInfo node : nodes) {
            if (node.getText().toString().equals(text)) {
                return node;
            }
        }
        return null;
    }

    private static AccessibilityNodeInfo findByTextInCollection(AccessibilityNodeInfo root,
            String text)  throws Exception {
        AccessibilityNodeInfo result;
        final int childCount = root.getChildCount();
        for (int i = 0; i < childCount; i++) {
            AccessibilityNodeInfo child = root.getChild(i);
            if (child == null) {
                continue;
            }
            if (child.getCollectionInfo() != null) {
                scrollTop(child);
                result = getNodeTimed(() -> findByText(child, text));
                if (result != null) {
                    return result;
                }
                while (child.getActionList().contains(AccessibilityAction.ACTION_SCROLL_FORWARD)) {
                    scrollForward(child);
                    result = getNodeTimed(() -> findByText(child, text));
                    if (result != null) {
                        return result;
                    }
                }
            } else {
                result = findByTextInCollection(child, text);
                if (result != null) {
                    return result;
                }
            }
        }
        return null;
    }

    private static void scrollTop(AccessibilityNodeInfo node) throws Exception {
        try {
            while (node.getActionList().contains(AccessibilityAction.ACTION_SCROLL_BACKWARD)) {
                scroll(node, false);
            }
        } catch (TimeoutException e) {
            /* ignore */
        }
    }

    private static void scrollForward(AccessibilityNodeInfo node) throws Exception {
        try {
            scroll(node, true);
        } catch (TimeoutException e) {
            /* ignore */
        }
    }

    private static void scroll(AccessibilityNodeInfo node, boolean forward) throws Exception {
        getInstrumentation().getUiAutomation().executeAndWaitForEvent(
                () -> node.performAction(forward
                        ? AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
                        : AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD),
                (AccessibilityEvent event) -> event.getEventType()
                        == AccessibilityEvent.TYPE_VIEW_SCROLLED,
                GLOBAL_TIMEOUT_MILLIS);
        waitForIdle();
    }


    private static void click(AccessibilityNodeInfo node) throws Exception {
        getInstrumentation().getUiAutomation().executeAndWaitForEvent(
                () -> node.performAction(AccessibilityNodeInfo.ACTION_CLICK),
                (AccessibilityEvent event) -> event.getEventType()
                        == AccessibilityEvent.TYPE_VIEW_CLICKED,
                GLOBAL_TIMEOUT_MILLIS);
    }

    private static AccessibilityNodeInfo findCollectionItem(AccessibilityNodeInfo current)
            throws Exception {
        AccessibilityNodeInfo result = current;
        while (result != null) {
            if (result.getCollectionItemInfo() != null) {
                return result;
            }
            result = result.getParent();
        }
        return null;
    }

    private static AccessibilityNodeInfo findSwitch(AccessibilityNodeInfo root) throws Exception {
        if (Switch.class.getName().equals(root.getClassName().toString())) {
            return root;
        }
        final int childCount = root.getChildCount();
        for (int i = 0; i < childCount; i++) {
            AccessibilityNodeInfo child = root.getChild(i);
            if (child == null) {
                continue;
            }
            if (Switch.class.getName().equals(child.getClassName().toString())) {
                return child;
            }
            AccessibilityNodeInfo result = findSwitch(child);
            if (result != null) {
                return result;
            }
        }
        return null;
    }

    private static AccessibilityNodeInfo getNodeTimed(
            Callable<AccessibilityNodeInfo> callable) throws Exception {
        final long startTimeMillis = SystemClock.uptimeMillis();
        while (true) {
            try {
                AccessibilityNodeInfo node = callable.call();

                if (node != null) {
                    return node;
                }
            } catch (NullPointerException e) {
                Log.e(LOG_TAG, "NPE while finding AccessibilityNodeInfo", e);
            }

            final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
            if (elapsedTimeMillis > RETRY_TIMEOUT) {
                return null;
            }
            SystemClock.sleep(2 * elapsedTimeMillis);
        }
    }

    private static void waitForIdle() throws TimeoutException {
        getInstrumentation().getUiAutomation().waitForIdle(IDLE_TIMEOUT_MILLIS,
                GLOBAL_TIMEOUT_MILLIS);
    }
 }
