package org.opendatakit.activities;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v13.app.ActivityCompat;
import android.widget.Toast;

import org.opendatakit.androidcommon.R;
import org.opendatakit.consts.IntentConsts;
import org.opendatakit.consts.RequestCodeConsts;
import org.opendatakit.dependencies.DependencyChecker;
import org.opendatakit.utilities.RuntimePermissionUtils;


public abstract class BaseLauncherActivity extends BaseActivity implements ActivityCompat.OnRequestPermissionsResultCallback {
  protected static final int REQUIRED_PERMISSIONS_REQ_CODE = 0;

  protected static final String[] REQUIRED_PERMISSIONS = new String[] {
      Manifest.permission.READ_EXTERNAL_STORAGE,
      Manifest.permission.WRITE_EXTERNAL_STORAGE
  };

  protected Bundle savedInstanceState;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    this.savedInstanceState = savedInstanceState;

    if (!DependencyChecker.checkDependencies(this)) {
      return;
    }

    // 1. check if Services has the right permissions
    //      if not, launch Services
    // 2. check if this app has the right permissions

    if (!RuntimePermissionUtils.checkPackageAllPermission(
        this, IntentConsts.Services.PACKAGE_NAME, REQUIRED_PERMISSIONS)) {
      Intent launchIntent = new Intent();
      launchIntent.setComponent(
          new ComponentName(IntentConsts.Services.PACKAGE_NAME, IntentConsts.Services.MAIN_ACTIVITY));
      launchIntent.setAction(Intent.ACTION_VIEW);
      launchIntent.putExtra(IntentConsts.INTENT_KEY_PERMISSION_ONLY, true);

      startActivityForResult(launchIntent, RequestCodeConsts.RequestCodes.LAUNCH_MAIN_ACTIVITY);
    } else {
      if (!RuntimePermissionUtils.checkSelfAllPermission(this, REQUIRED_PERMISSIONS)) {
        ActivityCompat.requestPermissions(
            this, REQUIRED_PERMISSIONS, REQUIRED_PERMISSIONS_REQ_CODE);
      } else {
        onCreateWithPermission(savedInstanceState);
      }
    }
  }

  protected abstract void onCreateWithPermission(Bundle savedInstanceState);

  @Override
  public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    if (requestCode != REQUIRED_PERMISSIONS_REQ_CODE) {
      return;
    }

    AlertDialog.Builder builder =
        RuntimePermissionUtils.createPermissionRationaleDialog(this, requestCode, permissions);

    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
      onCreateWithPermission(savedInstanceState);
    } else {
      if (RuntimePermissionUtils.shouldShowAnyPermissionRationale(this, permissions)) {
        builder
            .setMessage(R.string.required_permission_rationale)
            .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
              @Override
              public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
                finish();
              }
            })
            .show();
      } else {
        Toast
            .makeText(this, R.string.required_permission_perm_denied, Toast.LENGTH_LONG)
            .show();
        finish();
      }
    }
  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if(requestCode != RequestCodeConsts.RequestCodes.LAUNCH_MAIN_ACTIVITY) {
      return;
    }

    if (resultCode != Activity.RESULT_OK) {
      System.exit(0); // cannot properly shutdown without Services having proper permissions
    }

    if (!RuntimePermissionUtils.checkSelfAllPermission(this, REQUIRED_PERMISSIONS)) {
      ActivityCompat.requestPermissions(
          this, REQUIRED_PERMISSIONS, REQUIRED_PERMISSIONS_REQ_CODE);
    } else {
      onCreateWithPermission(savedInstanceState);
    }
  }
}

@@ -659,16 +659,75 @@
 Utils;%0A%0A
+import java.util.ArrayList;%0Aimport java.util.Collections;%0A%0A
 %0Apublic 
@@ -1103,33 +1103,174 @@
 ted 
-Bundle savedInstanceState
+ArrayList%3CString%3E appSpecific_Required_Permissions = new ArrayList%3CString%3E();%0A%0A  protected Bundle savedInstanceState;%0A%0A  protected abstract void setAppSpecificPerms()
 ;%0A%0A 
@@ -2206,48 +2206,346 @@
     
-if (!RuntimePermissionUtils.checkSelfAll
+setAppSpecificPerms();%0A      if (appSpecific_Required_Permissions.size() %3E 0) %7B%0A        for (String perm : REQUIRED_PERMISSIONS) %7B%0A          if (!appSpecific_Required_Permissions.contains(perm)) %7B%0A            appSpecific_Required_Permissions.add(perm);%0A          %7D%0A        %7D%0A      %7D else %7B%0A        Collections.addAll(appSpecific_Required_
 Perm
@@ -2542,36 +2542,32 @@
 uired_Permission
-(thi
 s, REQUIRED_PERM
@@ -2566,32 +2566,267 @@
 RED_PERMISSIONS)
+;%0A      %7D%0A%0A      String%5B%5D appSpecPermArray = appSpecific_Required_Permissions.toArray(%0A              new String%5BappSpecific_Required_Permissions.size()%5D);%0A      if (!RuntimePermissionUtils.checkSelfAllPermission(this, appSpecPermArray)
 ) %7B%0A        Acti
@@ -2874,36 +2874,32 @@
   this, 
-REQUIRED_PERMISSIONS
+appSpecPermArray
 , REQUIR

Add app specific permissions for Scan and possibly other apps to take advantage of in the future