/*
       Licensed to the Apache Software Foundation (ASF) under one
       or more contributor license agreements.  See the NOTICE file
       distributed with this work for additional information
       regarding copyright ownership.  The ASF licenses this file
       to you 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 org.apache.cordova.geolocation;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.LOG;

import android.content.pm.PackageManager;

/**
 * This class provides reflective methods for permission requesting and checking so that plugins
 * written for cordova-android 5.0.0+ can still compile with earlier cordova-android versions.
 */
public class PermissionHelper {
    private static final String LOG_TAG = "CordovaPermissionHelper";

    /**
     * Requests a "dangerous" permission for the application at runtime. This is a helper method
     * alternative to cordovaInterface.requestPermission() that does not require the project to be
     * built with cordova-android 5.0.0+
     *
     * @param plugin        The plugin the permission is being requested for
     * @param requestCode   A requestCode to be passed to the plugin's onRequestPermissionResult()
     *                      along with the result of the permission request
     * @param permission    The permission to be requested
     */
    public static void requestPermission(CordovaPlugin plugin, int requestCode, String permission) {
        PermissionHelper.requestPermissions(plugin, requestCode, new String[] {permission});
    }

    /**
     * Requests "dangerous" permissions for the application at runtime. This is a helper method
     * alternative to cordovaInterface.requestPermissions() that does not require the project to be
     * built with cordova-android 5.0.0+
     *
     * @param plugin        The plugin the permissions are being requested for
     * @param requestCode   A requestCode to be passed to the plugin's onRequestPermissionResult()
     *                      along with the result of the permissions request
     * @param permissions   The permissions to be requested
     */
    public static void requestPermissions(CordovaPlugin plugin, int requestCode, String[] permissions) {
        try {
            Method requestPermission = CordovaInterface.class.getDeclaredMethod(
                    "requestPermissions", CordovaPlugin.class, int.class, String[].class);

            // If there is no exception, then this is cordova-android 5.0.0+
            requestPermission.invoke(plugin.cordova, plugin, requestCode, permissions);
        } catch (NoSuchMethodException noSuchMethodException) {
            // cordova-android version is less than 5.0.0, so permission is implicitly granted
            LOG.d(LOG_TAG, "No need to request permissions " + Arrays.toString(permissions));

            // Notify the plugin that all were granted by using more reflection
            deliverPermissionResult(plugin, requestCode, permissions);
        } catch (IllegalAccessException illegalAccessException) {
            // Should never be caught; this is a public method
            LOG.e(LOG_TAG, "IllegalAccessException when requesting permissions " + Arrays.toString(permissions), illegalAccessException);
        } catch(InvocationTargetException invocationTargetException) {
            // This method does not throw any exceptions, so this should never be caught
            LOG.e(LOG_TAG, "invocationTargetException when requesting permissions " + Arrays.toString(permissions), invocationTargetException);
        }
    }

    /**
     * Checks at runtime to see if the application has been granted a permission. This is a helper
     * method alternative to cordovaInterface.hasPermission() that does not require the project to
     * be built with cordova-android 5.0.0+
     *
     * @param plugin        The plugin the permission is being checked against
     * @param permission    The permission to be checked
     *
     * @return              True if the permission has already been granted and false otherwise
     */
    public static boolean hasPermission(CordovaPlugin plugin, String permission) {
        try {
            Method hasPermission = CordovaInterface.class.getDeclaredMethod("hasPermission", String.class);

            // If there is no exception, then this is cordova-android 5.0.0+
            return (Boolean) hasPermission.invoke(plugin.cordova, permission);
        } catch (NoSuchMethodException noSuchMethodException) {
            // cordova-android version is less than 5.0.0, so permission is implicitly granted
            LOG.d(LOG_TAG, "No need to check for permission " + permission);
            return true;
        } catch (IllegalAccessException illegalAccessException) {
            // Should never be caught; this is a public method
            LOG.e(LOG_TAG, "IllegalAccessException when checking permission " + permission, illegalAccessException);
        } catch(InvocationTargetException invocationTargetException) {
            // This method does not throw any exceptions, so this should never be caught
            LOG.e(LOG_TAG, "invocationTargetException when checking permission " + permission, invocationTargetException);
        }
        return false;
    }

    private static void deliverPermissionResult(CordovaPlugin plugin, int requestCode, String[] permissions) {
        // Generate the request results
        int[] requestResults = new int[permissions.length];
        Arrays.fill(requestResults, PackageManager.PERMISSION_GRANTED);

        try {
            Method onRequestPermissionResult = CordovaPlugin.class.getDeclaredMethod(
                    "onRequestPermissionResult", int.class, String[].class, int[].class);

            onRequestPermissionResult.invoke(plugin, requestCode, permissions, requestResults);
        } catch (NoSuchMethodException noSuchMethodException) {
            // Should never be caught since the plugin must be written for cordova-android 5.0.0+ if it
            // made it to this point
            LOG.e(LOG_TAG, "NoSuchMethodException when delivering permissions results", noSuchMethodException);
        } catch (IllegalAccessException illegalAccessException) {
            // Should never be caught; this is a public method
            LOG.e(LOG_TAG, "IllegalAccessException when delivering permissions results", illegalAccessException);
        } catch(InvocationTargetException invocationTargetException) {
            // This method may throw a JSONException. We are just duplicating cordova-android's
            // exception handling behavior here; all it does is log the exception in CordovaActivity,
            // print the stacktrace, and ignore it
            LOG.e(LOG_TAG, "InvocationTargetException when delivering permissions results", invocationTargetException);
        }
    }
}
