package com.joker.api;

import android.app.Activity;
import android.content.pm.PackageManager;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;

import com.joker.api.apply.ForceApplyPermissions;
import com.joker.api.apply.NormalApplyPermissions;
import com.joker.api.wrapper.AbstractWrapper;
import com.joker.api.wrapper.ActivityWrapper;
import com.joker.api.wrapper.FragmentWrapper;
import com.joker.api.wrapper.PermissionWrapper;
import com.joker.api.wrapper.SupportFragmentWrapper;
import com.joker.api.wrapper.Wrapper;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;

import static com.joker.api.Permissions4M.PageType.ANDROID_SETTING_PAGE;
import static com.joker.api.Permissions4M.PageType.MANAGER_PAGE;

/**
 * Created by joker on 2017/8/5.
 */

public class Permissions4M {
    public static Wrapper get(Activity activity) {
        return new ActivityWrapper(activity);
    }

    public static Wrapper get(android.app.Fragment fragment) {
        return new FragmentWrapper(fragment);
    }

    public static Wrapper get(android.support.v4.app.Fragment fragment) {
        return new SupportFragmentWrapper(fragment);
    }

    @SuppressWarnings("unchecked")
    /**
     * in {@link android.app.Activity}, once permission request only call this method once
     */
    public static void onRequestPermissionsResult(Activity activity, int
            requestCode, @NonNull int[] grantResults) {
        onPrivateRequestPermissionsResult(activity, requestCode, grantResults);
    }

    @SuppressWarnings("unchecked")
    /**
     * in {@link android.app.Fragment}, once permission request only call this method once
     */
    public static void onRequestPermissionsResult(android.app.Fragment fragment, int
            requestCode, @NonNull int[] grantResults) {
        onPrivateRequestPermissionsResult(fragment, requestCode, grantResults);
    }

    @SuppressWarnings("unchecked")
    /**
     * in {@link android.support.v4.app.android.support.v4.app.Fragment}, once permission request
     * will call this method **twice**
     */
    public static void onRequestPermissionsResult(android.support.v4.app.Fragment fragment, int
            requestCode, @NonNull int[] grantResults) {
        onPrivateRequestPermissionsResult(fragment, requestCode, grantResults);
    }

    private static void onPrivateRequestPermissionsResult(Object object, int
            requestCode, @NonNull int[] grantResults) {
        AbstractWrapper.Key key = new AbstractWrapper.Key(object, requestCode);
        WeakReference<PermissionWrapper> reference = AbstractWrapper.getWrapperMap().get(key);
        // because SupportFragment request permissions will call Activity callback first
        // and then call SupportFragment callback
        // and the first time will throw NullPointerException
        if (reference == null) {
            return;
        }
        PermissionWrapper wrapper = reference.get();
        // because SupportFragment request permissions will call Activity callback first
        // and then call SupportFragment callback
        // and the first time will throw NullPointerException
        if (wrapper == null) {
            return;
        }
        Wrapper.PermissionRequestListener requestListener = wrapper
                .getPermissionRequestListener();
        // listener callback
        if (requestListener != null) {
            listenerCallback(grantResults, wrapper);
        } else {
            // annotation callback
            annotationCallback(grantResults, wrapper);
        }
    }

    private static void annotationCallback(@NonNull int[] grantResults, PermissionWrapper wrapper) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            if (wrapper.isRequestForce()) {
                ForceApplyPermissions.grantedOnResultWithAnnotation(wrapper);
            } else {
                NormalApplyPermissions.grantedWithAnnotation(wrapper);
            }
        } else {
            NormalApplyPermissions.deniedWithAnnotation(wrapper);
        }
    }

    private static void listenerCallback(@NonNull int[] grantResults, PermissionWrapper wrapper) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            if (wrapper.isRequestForce()) {
                ForceApplyPermissions.grantedOnResultWithListener(wrapper);
            } else {
                NormalApplyPermissions.grantedWithListener(wrapper);
            }
        } else {
            NormalApplyPermissions.deniedOnResultWithListener(wrapper);
        }
    }

    public static void requestPermission(Activity activity, String permission, int requestCode) {
        new ActivityWrapper(activity)
                .requestForce(true)
                .requestPermissions(permission)
                .requestCodes(requestCode)
                .request();
    }

    public static void requestPermission(android.app.Fragment fragment, String
            permission, int requestCode) {
        new FragmentWrapper(fragment)
                .requestForce(true)
                .requestPermissions(permission)
                .requestCodes(requestCode)
                .request();
    }

    public static void requestPermission(android.support.v4.app.Fragment fragment, String permission, int
            requestCode) {
        new SupportFragmentWrapper(fragment)
                .requestForce(true)
                .requestPermissions(permission)
                .requestCodes(requestCode)
                .request();
    }

    @IntDef({MANAGER_PAGE, ANDROID_SETTING_PAGE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface PageType {
        int MANAGER_PAGE = 1;
        int ANDROID_SETTING_PAGE = 0;
    }
}

@@ -405,32 +405,78 @@
 ragmentWrapper;%0A
+import com.joker.api.wrapper.ListenerWrapper;%0A
 import com.joker
@@ -3334,16 +3334,24 @@
         
+Listener
 Wrapper.
@@ -4696,24 +4696,16 @@
 s.denied
-OnResult
 WithList
@@ -4711,32 +4711,32 @@
 tener(wrapper);%0A
+
         %7D%0A    %7D%0A
@@ -4876,44 +4876,8 @@
 ty)%0A
-                .requestForce(true)%0A
     
@@ -5162,44 +5162,8 @@
 nt)%0A
-                .requestForce(true)%0A
     
@@ -5409,32 +5409,32 @@
  requestCode) %7B%0A
+
         new Supp
@@ -5466,44 +5466,8 @@
 nt)%0A
-                .requestForce(true)%0A
     

refactor code