package com.selfservit.util;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ActivityNotFoundException;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.PowerManager;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.provider.OpenableColumns;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.util.Base64;
import android.util.Log;
import android.view.KeyEvent;
import android.webkit.MimeTypeMap;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResult;
import com.google.android.gms.location.LocationSettingsStatusCodes;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PermissionHelper;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Stack;
import java.util.TimeZone;

import static android.app.Activity.RESULT_OK;

public class mInterface extends CordovaPlugin implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, ResultCallback<LocationSettingsResult> {
    public Stack<ProgressDialog> spinnerDialogStack = new Stack<ProgressDialog>();
    private static final int PICK_FILE_REQUEST = 1;
    CallbackContext callback;
    private static JSONArray arguments = null;
    private String pictureFilePath;
    private static final int REQUEST_IMAGE_CAPTURE = 111;
    private static final int PICK_IMAGE_FROM_GALLERY = 112;
    private static final int REQUEST_LIVE_IMAGE_CAPTURE = 113;
    private static final int LOCATION_ACCURACY_REQUEST_NEW = 115;
    private static final String ANY = "any";
    private static final String PORTRAIT_PRIMARY = "portrait-primary";
    private static final String PORTRAIT_SECONDARY = "portrait-secondary";
    private static final String LANDSCAPE_PRIMARY = "landscape-primary";
    private static final String LANDSCAPE_SECONDARY = "landscape-secondary";
    private static final String PORTRAIT = "portrait";
    private static final String LANDSCAPE = "landscape";
    private static final String ANDROID_PLATFORM = "Android";
    /* START SERVICE WHEN USER COMES FROM INACTIVE TO ACTIVE STATE IF SERVICE NOT RUNNING */
    @ Override
    public void onResume(boolean multitasking) {
        super.onResume(multitasking);
        if (!isServiceRunning(mInterfaceService.class) || !isProcessRunning()) {
            cordova.getActivity().startService(new Intent(cordova.getActivity().getApplicationContext(), mInterfaceService.class));
        }
    }
    @RequiresApi(api = Build.VERSION_CODES.O)
    @ Override
    public boolean execute(final String action, JSONArray args, final CallbackContext callbackContext)throws JSONException {
        /* START BACKGROUND SERVICE IF NOT RUNNING ALREADY */
        if (action.equals("StartService")) {
            //if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            cordova.getActivity().startForegroundService(new Intent(cordova.getActivity().getApplicationContext(), mInterfaceService.class));
            callbackContext.success("Success");
        } else if (action.equals("GetPermissions")) {
            getPermissions(args, callbackContext);
            return true;
        }else if (action.equals("AppVersion")) {
            appVersion(callbackContext);
            return true;
        } else if (action.equals("DeviceInfo")) {
            deviceInfo(callbackContext);
            return true;
        } else if (action.equals("GetStorageRoot")) {
            getStorageRoot(callbackContext);
            return true;
        } else if (action.equals("RotateScreen")) {
            rotateScreen(args, callbackContext);
            return true;
        } else if (action.equals("UnZip")) {
            File root = Environment.getExternalStorageDirectory();
            String filePath = root + "/" + args.getJSONObject(0).optString("filePath");
            String fileLocation = root + "/" + args.getJSONObject(0).optString("destination");
            new mInterfaceUtil().unzip(filePath, fileLocation,callbackContext);
            return true;
        } else if(action.equals("EnableGPSService")) {
            EnableGPSAutoMatically(callbackContext);
        } else if ("GoHome".equals(action)) {
            try {
                Intent i = new Intent(Intent.ACTION_MAIN);
                i.addCategory(Intent.CATEGORY_HOME);
                this.cordova.getActivity().startActivity(i);
            } catch (Exception e) {
                return false;
            }
            callbackContext.success();
            return true;
        } else if ("GoBack".equals(action)) {
            try {
                // try to send it back and back to previous app
                boolean sentAppToBackground = this.cordova.getActivity().moveTaskToBack(true);
                // if not possible jump to home
                if (!sentAppToBackground) {
                    Intent i = new Intent(Intent.ACTION_MAIN);
                    i.setAction(Intent.ACTION_MAIN);
                    i.addCategory(Intent.CATEGORY_HOME);
                    this.cordova.getActivity().startActivity(i);
                }
            } catch (Exception e) {
                return false;
            }
            callbackContext.success();
            return true;
        } else if (action.equals("Spinner")) {
            if(args.getJSONObject(0).optString("show").equals("true")){

                final boolean isFixed = true;
                Runnable runnable = new Runnable() {
                    public void run() {

                        DialogInterface.OnCancelListener onCancelListener = new DialogInterface.OnCancelListener() {
                            public void onCancel(DialogInterface dialog) {
                                if (!isFixed) {
                                    while (!mInterface.this.spinnerDialogStack.empty()) {
                                        mInterface.this.spinnerDialogStack.pop().dismiss();
                                        callbackContext.success();
                                    }
                                }
                            }
                        };

                        ProgressDialog dialog;
                        if (isFixed) {
                            //If there is a progressDialog yet change the text
                            if (!mInterface.this.spinnerDialogStack.empty()) {
                                dialog = mInterface.this.spinnerDialogStack.peek();
                            }
                            else{
                                dialog = CallbackProgressDialog.show(cordova.getActivity(),true, false, null, callbackContext);
                                mInterface.this.spinnerDialogStack.push(dialog);
                            }
                        } else {
                            //If there is a progressDialog yet change the text
                            if (!mInterface.this.spinnerDialogStack.empty()) {
                                dialog = mInterface.this.spinnerDialogStack.peek();
                            }
                            else{
                                dialog = ProgressDialog.show(cordova.getActivity(), "", "", true, true, onCancelListener);
                                mInterface.this.spinnerDialogStack.push(dialog);
                            }
                        }
                        dialog.setContentView(new ProgressBar(cordova.getActivity()));
                    }
                };
                this.cordova.getActivity().runOnUiThread(runnable);
            }else{
                Runnable runnable = new Runnable() {
                    public void run() {

                        if (!mInterface.this.spinnerDialogStack.empty()) {
                            mInterface.this.spinnerDialogStack.pop().dismiss();
                        }

                    }
                };
                this.cordova.getActivity().runOnUiThread(runnable);
            }
            callbackContext.success("success");
        } else if (action.equals("GetPackageName")){
            callbackContext.success(cordova.getActivity().getApplicationContext().getPackageName());
        } else if (action.equals("GetLocation")) {
            /* SEND CURRENT LOCATION VIA PLUGIN CALLBACK */
            callbackContext.success(new mInterfaceUtil().getLocation(cordova.getActivity().getApplicationContext()));
        } else if (action.equals("CheckLocation")) {
            /* SEND CURRENT LOCATION SETTING STATUS VIA PLUGIN CALLBACK */
            callbackContext.success(new mInterfaceUtil().checkLocation(cordova.getActivity().getApplicationContext()));
        } else if (action.equals("GetSyncIndicator")) {
            try {
                File newQueueFolder, oldQueueFolder;
                Boolean syncIndication = false;
                BufferedReader readerObj;
                String currentLine, sendData = "";
                URL requestPath;
                HttpURLConnection urlConObj;
                OutputStreamWriter oStreamObj;
                String currentLinedata = "";
                String client_id = args.getJSONObject(0).optString("client_id");
                String country_code = args.getJSONObject(0).optString("country_code");
                String user_id = args.getJSONObject(0).optString("user_id");
                String client_url = args.getJSONObject(0).optString("client_url");
                String requestUrl = client_url + "/common/components/QueueManager/GetSyncInd.aspx?client_id=" + client_id + "&country_code=" + country_code + "&user_id=" + user_id;

                try {
                    oldQueueFolder = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + mInterfaceUtil.packageName + "/database/queue");
                    newQueueFolder = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + mInterfaceUtil.packageName + "/" + client_id + "/" + country_code + "/database/queue");
                    if(oldQueueFolder.exists()) {
                        if(oldQueueFolder.listFiles().length == 0){
                            syncIndication = true;
                        }
                    } else{
                        syncIndication = true;
                    }
                    if(syncIndication) {
                        if(newQueueFolder.exists()){
                            if(newQueueFolder.listFiles().length != 0){
                                syncIndication = false;
                            }
                        }
                    }
                    if(syncIndication) {
                        requestPath = new URL(requestUrl);
                        urlConObj = (HttpURLConnection)requestPath.openConnection();
                        urlConObj.setDoOutput(true);
                        urlConObj.setRequestMethod("POST");
                        urlConObj.setRequestProperty("CONTENT-TYPE", "application/text");
                        urlConObj.connect();
                        oStreamObj = new OutputStreamWriter(urlConObj.getOutputStream());
                        oStreamObj.write(sendData);
                        oStreamObj.flush();
                        oStreamObj.close();

                        /* GET RESPONSE FROM SERVER*/
                        readerObj = new BufferedReader(new InputStreamReader(urlConObj.getInputStream()));
                        currentLine = readerObj.readLine();
                        readerObj.close();
                        currentLinedata = currentLine.toString();
                        urlConObj.disconnect();
                        if(currentLinedata.equals("true")) {
                            syncIndication = true;
                        } else {
                            syncIndication = false;
                        }
                    }
                    callbackContext.success(String.valueOf(syncIndication));
                }catch(Exception e){
                    callbackContext.success(e.getMessage());
                }
            } catch (Exception e) {
                callbackContext.success(e.getMessage());
            }
        } else if (action.equals("FileChooser")) {
            chooseFile(callbackContext);
            return true;
        } else if (action.equals("ReadFile")) {
            new mInterfaceUtil().readFile(args, callbackContext);
            return true;
        } else if (action.equals("DeleteFile")) {
            new mInterfaceUtil().deleteFile(args, callbackContext);
            return true;
        } else if (action.equals("CreateFile")) {
            new mInterfaceUtil().createFile(args, callbackContext);
            return true;
        }else if (action.equals("ValidateFile")) {
            new mInterfaceUtil().validateFile(args, callbackContext);
            return true;
        }else if (action.equals("CreateDirectory")) {
            new mInterfaceUtil().createDirectory(args, callbackContext);
            return true;
        }else if (action.equals("DeleteDirectory")) {
            new mInterfaceUtil().deleteDirectory(args, callbackContext);
            return true;
        }else if (action.equals("UploadFile")) {
            String filePath =args.getJSONObject(0).optString("filePath");
            String fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
            String url = args.getJSONObject(0).optString("url");
            new mInterfaceUtil().sendFilesToServer(filePath,fileName,url);
            return true;
        } else if (action.equals("CopyFile")) {
            arguments = args;
            new mInterfaceUtil().copyFile(callbackContext, arguments);
        }else if(action.equals("GetNewDate")){
            new mInterfaceUtil().getNewDate(callbackContext);
        } else if(action.equals("RefreshTimeProfile")) {
            JSONObject timeObj = args.getJSONObject(0);
            String date,hour,minute;
            date = timeObj.optString("serverDate").toString();
            hour = timeObj.optString("serverHour").toString();
            minute = timeObj.optString("serverMinute").toString();
            String returnStatus=new mInterfaceUtil().refreshTimeProfile(date,hour,minute);
            if(returnStatus.equals("true")){
                callbackContext.success("success");
            }else {
                callbackContext.error("failure");
            }
        } else if (action.equals("UpdateChoice")) {
            /* OPEN THE PLAYSTORE MSERVICE APP */
            String appVersion,softwareProductVersion,softwareProductSubVersion;
            JSONObject versionObj;
            AlertDialog.Builder builder= new AlertDialog.Builder(cordova.getActivity(),AlertDialog.THEME_HOLO_DARK);
            AlertDialog alertDialog;
            versionObj = args.getJSONObject(0);
            appVersion = versionObj.optString("appVersion").toString();
            softwareProductVersion= versionObj.optString("softwareProductVersion").toString();
            softwareProductSubVersion = versionObj.optString("softwareProductSubVersion").toString();
            builder.setTitle("New Update");
            builder.setMessage("Your mservice version is " + appVersion + ". There is an updated version  " + softwareProductVersion + "." + softwareProductSubVersion + " available. Please update.");
            builder.setPositiveButton("Update", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    cordova.getActivity().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" +cordova.getActivity().getApplicationContext().getPackageName())));
                    callbackContext.error("failure");
                }
            });
            builder.setNegativeButton("Not Now", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.cancel();
                    callbackContext.success("Success");
                }
            });
            alertDialog= builder.create();
            alertDialog.setCanceledOnTouchOutside(false);
            alertDialog.show();
            alertDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {

                @Override
                public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                    if (keyCode == KeyEvent.KEYCODE_BACK) {
                        dialog.dismiss();
                        callbackContext.error("failure");
                    }
                    return true;
                }

            });
        } else if (action.equals("UpdateConfirm")) {
            /* OPEN THE PLAYSTORE MSERVICE APP */
            String appVersion,softwareProductVersion,softwareProductSubVersion;
            JSONObject versionObj;
            AlertDialog alertDialog;
            AlertDialog.Builder builder= new AlertDialog.Builder(cordova.getActivity(),AlertDialog.THEME_HOLO_DARK);
            versionObj = args.getJSONObject(0);
            appVersion = versionObj.optString("appVersion").toString();
            softwareProductVersion= versionObj.optString("softwareProductVersion").toString();
            softwareProductSubVersion = versionObj.optString("softwareProductSubVersion").toString();
            builder.setTitle("New Update");
            builder.setMessage("Your mservice version is " + appVersion + ". Please upgrade the app to " + softwareProductVersion + "." + softwareProductSubVersion + " to proceed.");
            builder.setPositiveButton("Update", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    cordova.getActivity().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" +cordova.getActivity().getApplicationContext().getPackageName())));
                    callbackContext.error("failure");
                }
            });
            alertDialog= builder.create();
            alertDialog.setCanceledOnTouchOutside(false);
            alertDialog.show();
            alertDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {

                @Override
                public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                    if(keyCode == KeyEvent.KEYCODE_BACK){
                        dialog.dismiss();
                        callbackContext.error("failure");
                    }
                    return true;
                }
            });
        } else if (action.equals("UpdateNew")) {
            cordova.getActivity().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" +cordova.getActivity().getApplicationContext().getPackageName())));
            callbackContext.error("failure");
        } else if(action.equals("OpenFileWithViewer")) {
            Context context = cordova.getActivity().getApplicationContext();
            File baseDirectory = Environment.getExternalStorageDirectory();
            String filePath = baseDirectory + "/" + args.optString(0);
            File imageFilePath = new File(filePath);
            try {
                Intent intent = new Intent(Intent.ACTION_VIEW);
                Uri contentUri = FileProvider.getUriForFile(context, context.getPackageName()+".provider", imageFilePath);
                intent.setDataAndType(contentUri, getMimeType(filePath));
                intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_NO_HISTORY);
                cordova.getActivity().startActivity(intent);
                callbackContext.success();
            } catch (ActivityNotFoundException e) {
                callbackContext.error(1);
            }
        } else if(action.equals("CaptureImageFromCamera")) {
            try {
                captureImage(callbackContext);
                return true;
            } catch (Exception e) {
                callbackContext.error(1);
            }
        } else if(action.equals("PickImageFromGallery")) {
            try {
                pickImageFromGallery(callbackContext);
                return true;
            } catch (Exception e) {
                callbackContext.error(1);
            }
        } else if(action.equals("CaptureFromCamera")) {
            try {
                captureImageLiveCamera(callbackContext);
                return true;
            } catch (Exception e) {
                callbackContext.error(1);
            }
        } else if(action.equals("DeleteSrcFile")) {
            try {
                String filePath = args.getJSONObject(0).optString("filePath");
                String fileName = args.getJSONObject(0).optString("fileName");
                File fullPath = new File(filePath + "/" + fileName);
                if(fullPath.exists()) {
                    fullPath.delete();
                    callbackContext.success();
                } else {
                    callbackContext.error("Expected file is not there to delete..");
                }
            } catch (Exception e) {
                callbackContext.error(1);
            }
        } else if (action.equals("DownloadFile")) {
            callback = callbackContext;
            final DownloadTask downloadTask = new DownloadTask(cordova.getActivity());
            downloadTask.execute(args.optJSONObject(0).optString("url"),args.optJSONObject(0).optString("filePath"));
            return true;
        } else if ("QueueProcessor".equals(action)) {
            new mInterfaceUtil().queueProcessor(callbackContext);
            return true;
        }
        return true;
    }

    private void getStorageRoot(CallbackContext callbackContext) {
        File root = Environment.getExternalStorageDirectory();
        callbackContext.success("file://"+root+"/");
    }
    private void getPermissions(JSONArray args, CallbackContext callbackContext) {
        try {
            callback = callbackContext;
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                String[] permissions = args.optJSONObject(0).optString("permissions").split(",");
                PermissionHelper.requestPermissions(this, 1, permissions);
            }else {
                callback.success("success");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void captureImageLiveCamera(CallbackContext callbackContext) {
        callback = callbackContext;
        Context context = cordova.getActivity().getApplicationContext();
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        File photoFile = null;
        try {
            photoFile = createImageFile();
        } catch (IOException ex) {
            callback.error("there is error in create image");
        }
        //Continue only if the File was successfully created
        if (photoFile != null) {
            Uri photoURISample ;
            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT){
            photoURISample = Uri.fromFile(photoFile);
            } else {
            photoURISample = FileProvider.getUriForFile(context, context.getPackageName() + ".provider", photoFile);
            }
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURISample);
            cordova.startActivityForResult(this, takePictureIntent, REQUEST_LIVE_IMAGE_CAPTURE);
            PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
            pluginResult.setKeepCallback(true);
            callbackContext.sendPluginResult(pluginResult);
        }
    }
    public void captureImage(CallbackContext callbackContext) {
        callback = callbackContext;
        Context context = cordova.getActivity().getApplicationContext();
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        File photoFile = null;
        try {
            photoFile = createImageFile();
        } catch (IOException ex) {
            callback.error("there is error in create image");
        }
        // Continue only if the File was successfully created
        if (photoFile != null) {
            Uri photoURISample ;
            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT){
            photoURISample = Uri.fromFile(photoFile);
            } else {
            photoURISample = FileProvider.getUriForFile(context, context.getPackageName() + ".provider", photoFile);
            }            
			takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURISample);
            cordova.startActivityForResult(this, takePictureIntent, REQUEST_IMAGE_CAPTURE);
            PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
            pluginResult.setKeepCallback(true);
            callbackContext.sendPluginResult(pluginResult);
        }
    }
    public void pickImageFromGallery(CallbackContext callbackContext) {
        Intent openFile,
                selectFile;
        PluginResult pluginResult;
        callback = callbackContext;
        if (Build.MANUFACTURER.equals("samsung")) {
            /* SELECT FILE FOR SAMSUNG DEVICES */
            openFile = new Intent("com.sec.android.app.myfiles.PICK_DATA");
            openFile.putExtra("CONTENT_TYPE", "*/*");
        } else {
            /* SELECT FILE FOR EXCEPT SAMSUNG DEVICES */
            openFile = new Intent(Intent.ACTION_GET_CONTENT);
            openFile.setType("*/*");
            openFile.addCategory(Intent.CATEGORY_OPENABLE);
            openFile.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
        }
        selectFile = Intent.createChooser(openFile, "Select File");
        cordova.startActivityForResult(this, selectFile, PICK_IMAGE_FROM_GALLERY);
        pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
        pluginResult.setKeepCallback(true);
        callbackContext.sendPluginResult(pluginResult);
    }
    private static String getMimeType(String path) {
        String mimeType = null;
        String extension = MimeTypeMap.getFileExtensionFromUrl(path);
        if (extension != null) {
            MimeTypeMap mime = MimeTypeMap.getSingleton();
            mimeType = mime.getMimeTypeFromExtension(extension.toLowerCase());
        }
        return mimeType;
    }
    private File createImageFile() throws IOException {
        File baseDirectory = Environment.getExternalStorageDirectory();
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        String filePath = baseDirectory + "/" + mInterfaceUtil.packageName + "/images";
        File storageDir = new File(filePath);
        if(!storageDir.exists()) {
            storageDir.mkdirs();
        }
        File image = File.createTempFile(imageFileName, /* prefix */".jpg", /* suffix */storageDir /* directory */);
        pictureFilePath = image.getAbsolutePath();
        return image;
    }
    public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        final float totalPixels = width * height;
        final float totalReqPixelsCap = reqWidth * reqHeight * 2;
        while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
            inSampleSize++;
        }
        return inSampleSize;
    }

    public void convertImageTo64BaseString(CallbackContext callbackContext, String imageSourcePath, String imgSrcType) {
        String compressedImagePathStr = "";
        String compressedImageName = "";
        String filePath = imageSourcePath;
        Bitmap scaledBitmap = null;
        BitmapFactory.Options options = new BitmapFactory.Options();
        //by setting this field as true, the actual bitmap pixels are not loaded in the memory. Just the bounds are loaded. If
        //you try the use the bitmap here, you will get null.
        options.inJustDecodeBounds = true;
        Bitmap bmp = BitmapFactory.decodeFile(filePath, options);
        int actualHeight = options.outHeight;
        int actualWidth = options.outWidth;
        //max Height and width values of the compressed image is taken as 816x612
        float maxHeight = 816.0f;
        float maxWidth = 612.0f;
        float imgRatio = actualWidth / actualHeight;
        float maxRatio = maxWidth / maxHeight;
        //width and height values are set maintaining the aspect ratio of the image
        if (actualHeight > maxHeight || actualWidth > maxWidth) {
            if (imgRatio < maxRatio) {
                imgRatio = maxHeight / actualHeight;
                actualWidth = (int) (imgRatio * actualWidth);
                actualHeight = (int) maxHeight;
            } else if (imgRatio > maxRatio) {
                imgRatio = maxWidth / actualWidth;
                actualHeight = (int) (imgRatio * actualHeight);
                actualWidth = (int) maxWidth;
            } else {
                actualHeight = (int) maxHeight;
                actualWidth = (int) maxWidth;
            }
        }
        //setting inSampleSize value allows to load a scaled down version of the original image
        options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);
        //inJustDecodeBounds set to false to load the actual bitmap
        options.inJustDecodeBounds = false;
        //this options allow android to claim the bitmap memory if it runs low on memory
        options.inPurgeable = true;
        options.inInputShareable = true;
        options.inTempStorage = new byte[16 * 1024];
        try {
            //load the bitmap from its path
            bmp = BitmapFactory.decodeFile(filePath, options);
        } catch (OutOfMemoryError exception) {
            exception.printStackTrace();
        }
        try {
            scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
        } catch (OutOfMemoryError exception) {
            exception.printStackTrace();
        }
        float ratioX = actualWidth / (float) options.outWidth;
        float ratioY = actualHeight / (float) options.outHeight;
        float middleX = actualWidth / 2.0f;
        float middleY = actualHeight / 2.0f;

        Matrix scaleMatrix = new Matrix();
        scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);

        Canvas canvas = new Canvas(scaledBitmap);
        canvas.setMatrix(scaleMatrix);
        canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));

        //check the rotation of the image and display it properly
        ExifInterface exif;
        try {
            exif = new ExifInterface(filePath);
            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
            Log.d("EXIF", "Exif: " + orientation);
            Matrix matrix = new Matrix();
            if (orientation == 6) {
                matrix.postRotate(90);
                Log.d("EXIF", "Exif: " + orientation);
            } else if (orientation == 3) {
                matrix.postRotate(180);
                Log.d("EXIF", "Exif: " + orientation);
            } else if (orientation == 8) {
                matrix.postRotate(270);
                Log.d("EXIF", "Exif: " + orientation);
            }
            scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        //String filename = getFilename();
        try {
            //write the compressed bitmap at the destination specified by filename.
            if(imgSrcType.equals("compress")) {
                File file = Environment.getExternalStorageDirectory();
                String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
                compressedImagePathStr = file + "/" + mInterfaceUtil.packageName + "/" + "images";
                compressedImageName = compressedImagePathStr + "/" + timeStamp + ".jpg";
                File fileSavedPath = new File(compressedImagePathStr);
                if(!fileSavedPath.exists()) {
                    fileSavedPath.mkdirs();
                }
                FileOutputStream out = new FileOutputStream(compressedImageName);
                scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 30, out);
            } else {
                scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 30, baos);
            }
            String encodedImage = null;
            byte[] byteArray;
            try {
                byteArray = baos.toByteArray();
                encodedImage = Base64.encodeToString(byteArray, Base64.NO_WRAP);
                imgSrcType = imgSrcType;
                if(imgSrcType.equals("camera")) {
                    File file = new File(imageSourcePath);
                    if (file.exists()) {
                        file.delete();
                    }
                    callbackContext.success(encodedImage);
                } else if (imgSrcType.equals("gallery")) {
                    callbackContext.success(encodedImage);
                } else if (imgSrcType.equals("compress")) {
                    try {
                        JSONObject fileProperities = null;
                        String imgFilePath, fileName, fileExtension = "";
                        imgFilePath =  compressedImageName.substring(0, compressedImageName.lastIndexOf("/"));
                        String[] fileName1 = compressedImageName.toString().split("/");
                        fileName = fileName1[fileName1.length-1];
                        File file = new File(compressedImageName);
                        long fileSize = file.length();
                        fileExtension = "." + compressedImageName.substring(compressedImageName.lastIndexOf(".") + 1).toLowerCase();
                        fileProperities = new JSONObject();
                        fileProperities.put("filePath", imgFilePath);
                        fileProperities.put("fileName", fileName);
                        fileProperities.put("fileSize", fileSize);
                        fileProperities.put("fileExtension", fileExtension);
                        callback.success(fileProperities);
                    } catch (Exception e) {
                        callback.error(e.getMessage());
                    }
                }
            } catch (Exception e) {
                callbackContext.error(e.getMessage());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void chooseFile(CallbackContext callbackContext) {
        Intent openFile,
                selectFile;
        PluginResult pluginResult;
        callback = callbackContext;
        if (Build.MANUFACTURER.equals("samsung")) {
            /* SELECT FILE FOR SAMSUNG DEVICES */
            openFile = new Intent("com.sec.android.app.myfiles.PICK_DATA");
            openFile.putExtra("CONTENT_TYPE", "*/*");
        } else {
            /* SELECT FILE FOR EXCEPT SAMSUNG DEVICES */
            openFile = new Intent(Intent.ACTION_GET_CONTENT);
            openFile.setType("*/*");
            openFile.addCategory(Intent.CATEGORY_OPENABLE);
            openFile.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
        }
        selectFile = Intent.createChooser(openFile, "Select File");
        cordova.startActivityForResult(this, selectFile, PICK_FILE_REQUEST);
        pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
        pluginResult.setKeepCallback(true);
        callbackContext.sendPluginResult(pluginResult);
    }
   //App version plugin
    public void appVersion(CallbackContext callbackContext) {
        try {
            PackageManager packageManager = this.cordova.getActivity().getPackageManager();
            JSONObject r = new JSONObject();
            try {
                r.put("version", packageManager.getPackageInfo(this.cordova.getActivity().getPackageName(), 0).versionName);
                r.put("build", packageManager.getPackageInfo(this.cordova.getActivity().getPackageName(), 0).versionCode);
            } catch (JSONException e) {
                e.printStackTrace();
            }

            callbackContext.success(r);
        } catch (PackageManager.NameNotFoundException e) {
            callbackContext.error("Exception thrown");
        }
    }

    //Rotate Screen plugin
    public void rotateScreen(JSONArray args, CallbackContext callbackContext) {
        String orientation = args.optString(0);
        Activity activity = cordova.getActivity();
        if (orientation.equals(ANY)) {
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        } else if (orientation.equals(LANDSCAPE_PRIMARY)) {
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        } else if (orientation.equals(PORTRAIT_PRIMARY)) {
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        } else if (orientation.equals(LANDSCAPE)) {
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
        } else if (orientation.equals(PORTRAIT)) {
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
        } else if (orientation.equals(LANDSCAPE_SECONDARY)) {
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
        } else if (orientation.equals(PORTRAIT_SECONDARY)) {
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
        }
        callbackContext.success();
    }
    public void deviceInfo(CallbackContext callbackContext) throws JSONException {
        String uuid = Settings.Secure.getString(this.cordova.getActivity().getContentResolver(), Settings.Secure.ANDROID_ID);
        JSONObject r = new JSONObject();
        boolean a = android.os.Build.FINGERPRINT.contains("generic") ||
                android.os.Build.PRODUCT.contains("sdk");
        @SuppressWarnings("deprecation")
        String sdkversion = android.os.Build.VERSION.SDK;
        r.put("uuid", uuid);
        r.put("version", android.os.Build.VERSION.RELEASE);
        r.put("platform", ANDROID_PLATFORM);
        r.put("model", android.os.Build.MODEL);
        r.put("manufacturer", android.os.Build.MANUFACTURER);
        r.put("isVirtual", a);
        r.put("serial", android.os.Build.SERIAL);
        r.put( "timeZone",TimeZone.getDefault());
        r.put("sdkVersion" ,sdkversion);
        r.put("productName", android.os.Build.PRODUCT);
        callbackContext.success(r);
    }
    @ Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case LOCATION_ACCURACY_REQUEST_NEW:
                switch (resultCode) {
                    case Activity.RESULT_OK:
                        callback.success();
                        break;
                    case Activity.RESULT_CANCELED:
                        callback.error("oops! you have cancelled...");
                        break;
                }
                break;
        }
        if(requestCode == PICK_IMAGE_FROM_GALLERY && callback != null) {
            if (resultCode == RESULT_OK) {
                String fileName = null, getfilePath = null, filePath = null, fileType, storageDefinition, fileExtension;
                final String docId, type, id;
                final String[] split;
                final String tag, path;
                final int splitIndex;
                Cursor cursor;
                Uri uri = data.getData(); //get uri for selected file
                fileType = this.cordova.getActivity().getContentResolver().getType(uri); // get mimeType for selected file
                File getFileName, file;
                try {
                    //API LEVEL 19 AND ABOVE (TO GET FILEPATH)
                    if (Build.VERSION.SDK_INT >= 19 && !Build.MANUFACTURER.equals("samsung") && DocumentsContract.isDocumentUri(cordova.getActivity(), uri)) {
                        if ("com.android.externalstorage.documents".equals(uri.getAuthority())) { // ExternalStorageProvider
                            docId = DocumentsContract.getDocumentId(uri);
                            split = docId.split(":");
                            type = split[0];
                            if ("primary".equalsIgnoreCase(type)) {
                                getfilePath = Environment.getExternalStorageDirectory() + "/" + split[1];
                            } else {
                                if (Environment.isExternalStorageRemovable()) {
                                    storageDefinition = System.getenv("EXTERNAL_STORAGE");
                                    getfilePath = storageDefinition;
                                } else {
                                    splitIndex = docId.indexOf(':', 1);
                                    tag = docId.substring(0, splitIndex);
                                    path = docId.substring(splitIndex + 1);
                                    if (new mInterfaceUtil().getPathToNonPrimaryVolume(cordova.getActivity(), tag) != null) {
                                        storageDefinition = new mInterfaceUtil().getPathToNonPrimaryVolume(cordova.getActivity(), tag) + "/" + path;
                                        file = new File(storageDefinition);
                                        if (file.exists() && file.canRead()) {
                                            getfilePath = storageDefinition;
                                        }
                                    }
                                }
                            }
                        } else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) { // DownloadsProvider
                            id = DocumentsContract.getDocumentId(uri);
                            final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
                            getfilePath = new mInterfaceUtil().getDataColumn(cordova.getActivity(), contentUri, null, null);
                        } else if ("com.android.providers.media.documents".equals(uri.getAuthority())) { // MediaProvider
                            docId = DocumentsContract.getDocumentId(uri);
                            split = docId.split(":");
                            type = split[0];
                            Uri contentUri = null;
                            if ("image".equals(type)) {
                                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                            } else if ("video".equals(type)) {
                                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                            } else if ("audio".equals(type)) {
                                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                            }
                            final String selection = "_id=?";
                            final String[]selectionArgs = new String[]{
                                    split[1]
                            };
                            getfilePath = new mInterfaceUtil().getDataColumn(cordova.getActivity(), contentUri, selection, selectionArgs);
                        }
                        // *** API Level 19 and Above (To Get FileName,FileExtension and FileSize)**** //
                        cursor = cordova.getActivity().getContentResolver().query(uri, null, null, null, null, null);
                        try {
                            if (cursor != null && cursor.moveToFirst()) {
                                fileName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
                            }
                        }
                        finally {
                            cursor.close();
                        }
                        // *** API Level 19 below and SAMSUNG (To Get FileProperties of MediaFiles)**** //
                    } else {
                        if (fileType != null) {
                            String[]projection = {
                                    MediaStore.Images.Media.DATA,
                                    MediaStore.Images.Media.SIZE,
                                    MediaStore.Images.Media.DISPLAY_NAME
                            };
                            cursor = cordova.getActivity().getContentResolver().query(uri, projection, null, null, null);
                            if (cursor.moveToFirst()) {
                                getfilePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
                                fileName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME));
                            }
                            cursor.close();
                            // API LEVEL 19 BELOW AND SAMSUNG (TO GET FILEPROPERTIES OF NORMAL FILES(EX:txt,.pdf,etc..,))
                        } else {
                            getfilePath = data.getData().getPath();
                            filePath = getfilePath.substring(0, getfilePath.lastIndexOf(File.separator));
                            getFileName = new File(getfilePath);
                            fileName = getFileName.getName();
                        }
                    }
                    filePath = getfilePath.substring(0, getfilePath.lastIndexOf(File.separator));
                    fileExtension = "." + getfilePath.substring(getfilePath.lastIndexOf(".") + 1).toLowerCase();
                    if (filePath != null) {
                        try {
                            if(fileExtension.equals(".jpeg") || fileExtension.equals(".jpg") || fileExtension.equals(".png")) {
                                convertImageTo64BaseString(callback,filePath + "/" + fileName, "gallery");
                            } else {
                                callback.error("Only JPEG or PNG file extensions are allowed to attach.");
                            }
                        } catch (Exception e) {
                            callback.error("Only JPEG or PNG file extensions are allowed to attach.");
                        }
                    } else {
                        callback.error("File path was null");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else if (resultCode == Activity.RESULT_CANCELED) {
                callback.error("failure");
            } else {
                callback.error(resultCode);
            }
        } else if (requestCode == REQUEST_IMAGE_CAPTURE && callback != null) {
            if (resultCode == RESULT_OK) {
                convertImageTo64BaseString(callback,pictureFilePath, "camera");
            } else if (resultCode == Activity.RESULT_CANCELED) {
                // TODO NO_RESULT or error callback?
				File file = new File(pictureFilePath);
                if (file.exists()) {
                    file.delete();
                }
                callback.error("failure");
            } else {
                callback.error(resultCode);
            }
        } else if (requestCode == REQUEST_LIVE_IMAGE_CAPTURE && callback != null) {
            if (resultCode == RESULT_OK) {
                convertImageTo64BaseString(callback,pictureFilePath, "compress");
            } else if (resultCode == Activity.RESULT_CANCELED) {
                // TODO NO_RESULT or error callback?
				File file = new File(pictureFilePath);
                if (file.exists()) {
                    file.delete();
                }
                callback.error("failure");
            } else {
                callback.error(resultCode);
            }
        } else if (requestCode == PICK_FILE_REQUEST && callback != null) {
            if (resultCode == RESULT_OK) {
                String fileName = null,
                        getfilePath = null,
                        filePath = null,
                        fileExtension,
                        fileType,
                        fileSize = null,
                        storageDefinition; ;
                final String docId,
                        type,
                        id;
                final String[]split;
                final String tag,
                        path;
                final int splitIndex;
                Cursor cursor;
                long getSize;
                JSONObject fileProperities = null;
                Uri uri = data.getData(); //get uri for selected file
                fileType = this.cordova.getActivity().getContentResolver().getType(uri); // get mimeType for selected file
                File getFileName,
                        file;
                try {
                    //API LEVEL 19 AND ABOVE (TO GET FILEPATH)
                    if (Build.VERSION.SDK_INT >= 19 && !Build.MANUFACTURER.equals("samsung") && DocumentsContract.isDocumentUri(cordova.getActivity(), uri)) {
                        if ("com.android.externalstorage.documents".equals(uri.getAuthority())) { // ExternalStorageProvider
                            docId = DocumentsContract.getDocumentId(uri);
                            split = docId.split(":");
                            type = split[0];
                            if ("primary".equalsIgnoreCase(type)) {
                                getfilePath = Environment.getExternalStorageDirectory() + "/" + split[1];
                            } else {
                                if (Environment.isExternalStorageRemovable()) {
                                    storageDefinition = System.getenv("EXTERNAL_STORAGE");
                                    getfilePath = storageDefinition;
                                } else {
                                    splitIndex = docId.indexOf(':', 1);
                                    tag = docId.substring(0, splitIndex);
                                    path = docId.substring(splitIndex + 1);
                                    if (new mInterfaceUtil().getPathToNonPrimaryVolume(cordova.getActivity(), tag) != null) {
                                        storageDefinition = new mInterfaceUtil().getPathToNonPrimaryVolume(cordova.getActivity(), tag) + "/" + path;
                                        file = new File(storageDefinition);
                                        if (file.exists() && file.canRead()) {
                                            getfilePath = storageDefinition;
                                        }
                                    }
                                }
                            }
                        } else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) { // DownloadsProvider

                            id = DocumentsContract.getDocumentId(uri);
                            final Uri contentUri = ContentUris.withAppendedId(
                                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                            getfilePath = new mInterfaceUtil().getDataColumn(cordova.getActivity(), contentUri, null, null);

                        } else if ("com.android.providers.media.documents".equals(uri.getAuthority())) { // MediaProvider
                            docId = DocumentsContract.getDocumentId(uri);
                            split = docId.split(":");
                            type = split[0];

                            Uri contentUri = null;
                            if ("image".equals(type)) {
                                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                            } else if ("video".equals(type)) {
                                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                            } else if ("audio".equals(type)) {
                                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                            }

                            final String selection = "_id=?";
                            final String[]selectionArgs = new String[]{
                                    split[1]
                            };
                            getfilePath = new mInterfaceUtil().getDataColumn(cordova.getActivity(), contentUri, selection, selectionArgs);
                        }
                        // *** API Level 19 and Above (To Get FileName,FileExtension and FileSize)**** //
                        cursor = cordova.getActivity().getContentResolver().query(uri, null, null, null, null, null);
                        try {
                            if (cursor != null && cursor.moveToFirst()) {
                                fileName = cursor.getString(
                                        cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
                                if (!cursor.isNull(cursor.getColumnIndex(OpenableColumns.SIZE))) {
                                    fileSize = cursor.getString(cursor.getColumnIndex(OpenableColumns.SIZE));
                                }
                            }
                        }
                        finally {
                            cursor.close();
                        }
                        // *** API Level 19 below and SAMSUNG (To Get FileProperties of MediaFiles)**** //
                    } else {
                        if (fileType != null) {
                            String[]projection = {
                                    MediaStore.Images.Media.DATA,
                                    MediaStore.Images.Media.SIZE,
                                    MediaStore.Images.Media.DISPLAY_NAME
                            };
                            cursor = cordova.getActivity().getContentResolver().query(uri, projection, null, null, null);
                            if (cursor.moveToFirst()) {
                                getfilePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
                                fileName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME));
                                fileSize = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE));
                            }
                            cursor.close();

                            // API LEVEL 19 BELOW AND SAMSUNG (TO GET FILEPROPERTIES OF NORMAL FILES(EX:txt,.pdf,etc..,))
                        } else {
                            getfilePath = data.getData().getPath();
                            filePath = getfilePath.substring(0, getfilePath.lastIndexOf(File.separator));
                            getFileName = new File(getfilePath);
                            fileName = getFileName.getName();
                            getSize = getFileName.length();
                            fileSize = String.valueOf(getSize);
                        }
                    }
                    filePath = getfilePath.substring(0, getfilePath.lastIndexOf(File.separator));
                    fileExtension = "." + getfilePath.substring(getfilePath.lastIndexOf(".") + 1).toLowerCase();
                    // SEND BELOW JSON OBJECT TO PLUGIN CALLBACK
                    if (filePath != null) {
                        try {
                            if(fileExtension.equals(".jpeg") || fileExtension.equals(".jpg") || fileExtension.equals(".png")) {
                                convertImageTo64BaseString(callback,filePath + "/" + fileName, "compress");
                            } else {
                                fileProperities = new JSONObject();
                                fileProperities.put("filePath", filePath);
                                fileProperities.put("fileName", fileName);
                                fileProperities.put("fileSize", fileSize);
                                fileProperities.put("fileExtension", fileExtension);
                                callback.success(fileProperities);
                            }
                        } catch (Exception e) {
                            callback.error("Failed to process PICK_FILE_REQUEST");
                        }
                    } else {
                        callback.error("File path was null");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else if (resultCode == Activity.RESULT_CANCELED) {
                // TODO NO_RESULT or error callback?
                callback.error("failure");
            } else {
                callback.error(resultCode);
            }
        } else {
            callback.error("failure");
        }
    }
    @Override
    public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) {
        try {
            boolean indicator = true;
            for (int i = 0; i < grantResults.length; i++) {
                if (grantResults[i] != 0) {
                    indicator = false;
                    break;
                }
            }
            if (indicator) {
                callback.success("success");
            } else {
                callback.error("failure");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /* CHECKING THE BACKGROUND SERVICE RUNNING OR NOT */
    private boolean isServiceRunning(Class <  ?  > serviceClass) {
        ActivityManager manager = (ActivityManager)cordova.getActivity().getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service: manager.getRunningServices(Integer.MAX_VALUE)) {
            if (serviceClass.getName().equals(service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }
    private boolean isProcessRunning() {
        ActivityManager manager1 = (ActivityManager)cordova.getActivity().getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningAppProcessInfo processInfo : manager1.getRunningAppProcesses()) {
            if (processInfo.processName.equals(cordova.getActivity().getPackageName())) {
                return true;
            }
        }
        return false;
    }
    private void EnableGPSAutoMatically(CallbackContext callbackContext) {
        callback = callbackContext;
        GoogleApiClient googleApiClient = null;
        if (googleApiClient == null) {
            googleApiClient = new GoogleApiClient.Builder(cordova.getActivity())
                    .addApi(LocationServices.API).addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this).build();
            googleApiClient.connect();
            LocationRequest locationRequest = LocationRequest.create();
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            locationRequest.setInterval(30 * 1000);
            locationRequest.setFastestInterval(5 * 1000);
            LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                    .addLocationRequest(locationRequest);

            // **************************
            builder.setAlwaysShow(true); // this is the key ingredient
            // **************************

            PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi
                    .checkLocationSettings(googleApiClient, builder.build());
            result.setResultCallback(this);
        }
    }
    @Override
    public void onConnected(@Nullable Bundle bundle) {

    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

    }
    @Override
    public void onResult(LocationSettingsResult locationSettingsResult) {
        final Status status = locationSettingsResult.getStatus();
        switch (status.getStatusCode()) {
            case LocationSettingsStatusCodes.SUCCESS:
                break;
            case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                try {
                    this.cordova.setActivityResultCallback(this);
                    status.startResolutionForResult(this.cordova.getActivity(), LOCATION_ACCURACY_REQUEST_NEW);
                } catch (IntentSender.SendIntentException e) {
                    System.out.println("PendingIntent unable to execute request: ");
                }
                break;
            case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                System.out.println("Location settings are inadequate, and cannot be fixed here. Dialog not created.");
                break;
        }
    }
    private class DownloadTask extends AsyncTask<String, Integer, String> {

        private Context context;
        private PowerManager.WakeLock mWakeLock;

        public DownloadTask(Context context) {
            this.context = context;
        }

        @Override
        protected String doInBackground(String... sUrl) {
            InputStream input = null;
            OutputStream output = null;
            HttpURLConnection connection = null;
            try {
                URL url = new URL(sUrl[0]);
                connection = (HttpURLConnection) url.openConnection();
                connection.connect();

                // expect HTTP 200 OK, so we don't mistakenly save error report
                // instead of the file
                if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                    return "Server returned HTTP " + connection.getResponseCode() + " " + connection.getResponseMessage();
                }

                // this will be useful to display download percentage
                // might be -1: server did not report the length
                int fileLength = connection.getContentLength();

                // download the file
                input = connection.getInputStream();
                String[] fileName = sUrl[0].split("/");
                File rootPath = Environment.getExternalStorageDirectory();
                String fileFolder = sUrl[1];
                String fileFullPath =   fileFolder + "/" + fileName[fileName.length-1];
                File sourceDirecory = new File(rootPath + "/" + fileFolder);
                if(!sourceDirecory.exists()) {
                    sourceDirecory.mkdirs();
                }

                File fileSavePath = new File(rootPath + "/" + fileFullPath);
                output = new FileOutputStream(fileSavePath);

                byte data[] = new byte[4096];
                long total = 0;
                int count;
                while ((count = input.read(data)) != -1) {
                    // allow canceling with back button
                    if (isCancelled()) {
                        input.close();
                        return null;
                    }
                    total += count;
                    // publishing the progress....
                    if (fileLength > 0) // only if total length is known
                        publishProgress((int) (total * 100 / fileLength));
                    output.write(data, 0, count);
                }
                callback.success(fileFullPath);
            } catch (Exception e) {
                callback.error("Failure..." + e.getMessage());
            }
            return null;
        }
    }
}
