package com.bangk.payyap;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.content.res.AssetManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.ConnectivityManager;
import android.net.MailTo;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.http.SslError;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.provider.ContactsContract;
import android.provider.MediaStore;
import android.provider.MediaStore.Images.ImageColumns;
import android.support.annotation.NonNull;

import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.InputType;
import android.util.Base64;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.JsResult;
import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.EditText;
import android.widget.Toast;


import com.bangk.payyap.AndroidMultiPartEntity.ProgressListener;
import com.bangk.payyap.R;
import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.gson.Gson;


import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;


public class MainActivity extends AppCompatActivity {

    private String API_DOMAIN = "payyap.network";
    private String API_HOST = "https://payyap.network";
    private String SITE_TITLE = "payYap";
    private String SITE_SCHEMA = "payyap";

    String mediaAction = "selectPhoto";
    private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
    private static final int SELECT_IMAGE_ACTIVITY_REQUEST_CODE = 101;
    private static final int PICK_CONTACT = 102;
    private static final int MY_PERMISSIONS_REQUEST_READ_CONTACTS = 103;
    public static final int MEDIA_TYPE_IMAGE = 1;
    private Uri fileUri;
    private int imageNo = 0;
    private String selectedFile = "";

    private ProgressDialog progressDialog;
    private WebView webView;

    private Activity mainActivity = null;
    /**
     * ATTENTION: This was auto-generated to implement the App Indexing API.
     * See https://g.co/AppIndexing/AndroidStudio for more information.
     */
    private GoogleApiClient client;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        registerForContextMenu(findViewById(R.id.webView));

        webView = (WebView) findViewById(R.id.webView);
        webView.setWebViewClient(new PayYapWebApp());

        webView.getSettings().setLoadsImagesAutomatically(true);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setSupportZoom(false);
        webView.requestFocus(View.FOCUS_DOWN);
        webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
        webView.getSettings().setAllowFileAccessFromFileURLs(true);
        webView.getSettings().setAllowUniversalAccessFromFileURLs(true);

        webView.setWebChromeClient(new WebChromeClient() {
                                       @Override
                                       public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                                           //Required functionality here
                                           return super.onJsAlert(view, url, message, result);
                                       }
                                   }
        );

        //DEEP LINK START
        Intent intent = getIntent();
        String action = intent.getAction();
        Uri deepLink = intent.getData();
        if (deepLink != null) {
            //showAlert(deepLink.toString());
            String account_hash = deepLink.getQueryParameter("account_hash");
            if (account_hash.length() > 0) {
                saveUserHash(account_hash);
            }
        }
        //DEEP LINK END


        //webView.loadUrl("file:///android_asset/HTML/index.html");

        String url = "photobangk://index.html";
        url = "file:///android_asset/HTML/";
        String data = getHtmlFromTemplate("HTML/index.html");
        Log.d("URL", url);
        webView.loadDataWithBaseURL(url, data, "text/html", "utf-8", null);

        mainActivity = this;
        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
    }

    private void printKeyHash() {
        // Add code to print out the key hash
        try {
            PackageInfo info = getPackageManager().getPackageInfo("com.bangk.payyap", PackageManager.GET_SIGNATURES);
            for (Signature signature : info.signatures) {
                MessageDigest md = MessageDigest.getInstance("SHA");
                md.update(signature.toByteArray());
                Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
            }
        } catch (PackageManager.NameNotFoundException e) {
            Log.e("KeyHash:", e.toString());
        } catch (NoSuchAlgorithmException e) {
            Log.e("KeyHash:", e.toString());
        }
    }

    /**
     * This will be invoked when an item in the listview is long pressed
     */
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);

        getMenuInflater().inflate(R.menu.popup_menu, menu);
    }

    JSONObject photoBANGK_data = null;
    int selectedItemId = 0;

    /**
     * This will be invoked when a menu item is selected
     */
    @Override
    public boolean onContextItemSelected(MenuItem item) {

        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
        photoBANGK_data = null;
        selectedItemId = item.getItemId();
        switch (item.getItemId()) {
            case R.id.keep_photo:
                startUpload();
                break;
            case R.id.delete_photo:
                //Don't remove their stored photo, remove only captured photo if they want
                if (mediaAction == "takePhoto") {
                    File sourceFile = new File(selectedFile);
                    sourceFile.delete();
                }
                callJavaScript("deleteSelectedImage", imageNo);
                break;

        }
        return true;
    }

    @Override
    public void onContextMenuClosed(Menu menu) {
        super.onContextMenuClosed(menu);
        //showAlert("Closed");
    }

    /**
     * Checking device has camera hardware or not
     */
    private boolean isDeviceSupportCamera() {
        if (getApplicationContext().getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_CAMERA)) {
            // this device has a camera
            return true;
        } else {
            // no camera on this device
            return false;
        }
    }

    /**
     * Check if this device has a camera
     */
    private boolean checkCameraHardware(Context context) {
        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
            // this device has a camera
            return true;
        } else {
            // no camera on this device
            return false;
        }
    }

    private boolean isNetworkAvailable() {
        ConnectivityManager connectivityManager
                = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null;
    }

    private void showNetworkNotAvailable() {
        if (!isNetworkAvailable()) {
            showAlert("Device has no internet connection");
            try {
                JSONObject obj = new JSONObject();
                obj.put("msg", "Device has no internet connection");
                final String json = obj.toString(); // <-- JSON string
            } catch (Exception e) {
            }
        }
    }

//    @Override
//    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
//        if (requestCode == 0) {
//            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED
//                    && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
//
//            }
//        }
//    }

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

        //showAlert("requestCode=" + requestCode + "resultCode=" + resultCode + "intent=" + intent.getDataString());

        if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
            if (resultCode == RESULT_OK) {
                try {
                    selectedFile = fileUri.toString().substring(7);

                    new ImageSaver(getApplicationContext()).save(rotateImage(selectedFile));

                    callJavaScript("showSelectedImage", selectedFile, imageNo);
                } catch (Exception ex) {
                    showErrorMessage(ex);
                }

            } else if (resultCode == RESULT_CANCELED) {
                // User cancelled the image capture
            } else {
                // Image capture failed, advise user
            }
        } else if (requestCode == SELECT_IMAGE_ACTIVITY_REQUEST_CODE) {
            if (intent != null) {
                try {
                    //Log.d(LOG_TAG, "idButSelPic Photopicker: " + intent.getDataString());
                    Cursor cursor = getContentResolver().query(intent.getData(), null, null, null, null);
                    cursor.moveToFirst();
                    int idx = cursor.getColumnIndex(ImageColumns.DATA);
                    String fileSrc = cursor.getString(idx);
                    //Log.d(LOG_TAG, "Picture:" + fileSrc);
                    //flashMessage("Image selected:" + fileSrc);
                    selectedFile = fileSrc;

                    new ImageSaver(getApplicationContext()).save(rotateImage(selectedFile));

                    callJavaScript("showSelectedImage", selectedFile, imageNo);
                    //Bitmap bitmapPreview = BitmapFactory.decodeFile(fileSrc); //load preview image
                    //BitmapDrawable bmpDrawable = new BitmapDrawable(bitmapPreview);
                    //m_Image.setBackgroundDrawable(bmpDrawable);
                } catch (Exception ex) {
                    showErrorMessage(ex);
                }

            } else {
                //Log.d(LOG_TAG, "idButSelPic Photopicker canceled");
                flashMessage("Image selection canceled!");
            }//
        } else if (requestCode == PICK_CONTACT) {
            if (resultCode == Activity.RESULT_OK && intent != null) {
                //showAlert("ddd");
                Cursor cur = getContentResolver().query(intent.getData(), null, null, null, null);

                //Uri contactData = intent.getData();
                //Cursor cur = managedQuery(contactData, null, null, null, null);
                ContentResolver content_resolver = getContentResolver();

                if (cur.moveToFirst()) {
                    String id = cur.getString(cur.getColumnIndexOrThrow(ContactsContract.Contacts._ID));
                    String name = "";
                    String no = "";
                    String email = "";
                    String emailType = "";

                    Cursor phoneCur = content_resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
                            ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[]{id}, null);

                    if (phoneCur.moveToFirst()) {
                        name = phoneCur.getString(phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                        no = phoneCur.getString(phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                    }
                    phoneCur.close();
                    Log.e("Phone, name:", no + " : " + name);


                    Cursor emailCur = content_resolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", new String[]{id}, null);
                    while (emailCur.moveToNext()) {
                        // This would allow you get several email addresses
                        // if the email addresses were stored in an array
                        email = emailCur.getString(
                                emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
                        emailType = emailCur.getString(
                                emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));
                        Log.e("Email, emailType:", emailType + " : " + email);
                        if (Integer.valueOf(emailType) == 2) {
                            break;
                        }
                    }
                    emailCur.close();
                    Log.e("Email, emailType:", emailType + " : " + email);

                    callJavaScript("fillFormDataFromContact", email, name, no);

                    id = null;
                    name = null;
                    no = null;
                    email = null;
                    phoneCur = null;
                    emailCur = null;
                }
                content_resolver = null;
                cur = null;
                //populateContacts();
            }
        }

    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    // permission was granted, yay! Do the
                    // contacts-related task you need to do.

                    openContactPicker();
                } else {

                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                }
                return;
            }

            // other 'case' lines to check for other
            // permissions this app might request
        }
    }

    private void openContactPicker() {
        try {
            Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
            startActivityForResult(intent, PICK_CONTACT);
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("Error in intent : ", e.toString());
        }
    }

    private static final String CONTACT_ID = ContactsContract.Contacts._ID;
    private static final String HAS_PHONE_NUMBER = ContactsContract.Contacts.HAS_PHONE_NUMBER;

    private static final String PHONE_NUMBER = ContactsContract.CommonDataKinds.Phone.NUMBER;
    private static final String PHONE_CONTACT_ID = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;

    public String getAllContacts(Context context) {
        //Context context = getApplicationContext();

        List<Map<String, String>> contacts = new ArrayList<>();
        int i = 0;

        ContentResolver cr = context.getContentResolver();
        Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);

        if (cur.getCount() > 0) {
            while (cur.moveToNext()) {
                Map<String, String> contact = new HashMap<String, String>();

                String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
                String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

                String Phone = "";
                String email = "";
                String emailType = "";

                //Log.d("name", "" + name);

                Cursor phoneCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
                        ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[]{id}, null);

                if (phoneCur.moveToFirst()) {
                    name = phoneCur.getString(phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                    Phone = phoneCur.getString(phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                }
                phoneCur.close();
                //Log.e("Phone, name:", Phone + " : " + name);

                Cursor emailCur = cr.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", new String[]{id}, null);
                while (emailCur.moveToNext()) {
                    // This would allow you get several email addresses
                    // if the email addresses were stored in an array
                    email = emailCur.getString(
                            emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
                    emailType = emailCur.getString(
                            emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));
                    Log.e("Email, emailType:", emailType + " : " + email);
                    if (Integer.valueOf(emailType) == 2) {
                        break;
                    }
                }
                emailCur.close();
                //Log.e("Email, emailType:", emailType + " : " + email);


                contact.put("name", name);
                contact.put("email", email);
                contact.put("phone", Phone);

                contacts.add(i, contact);
                i++;
            }
        }

        String jsonString = new Gson().toJson(contacts);
        Log.d("Contacts", jsonString);
        //uploadContacts(jsonString);
        return jsonString;
    }

    private Bitmap rotateImage(final String path) {

        Bitmap scaledBitmap = BitmapFactory.decodeFile(path);
        Bitmap rotatedBitmap = null;
        try {
            ExifInterface ei = new ExifInterface(path);
            int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
            Matrix matrix = new Matrix();
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    matrix.postRotate(90);
                    rotatedBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
                            scaledBitmap.getWidth(), scaledBitmap.getHeight(),
                            matrix, true);
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    matrix.postRotate(180);
                    rotatedBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
                            scaledBitmap.getWidth(), scaledBitmap.getHeight(),
                            matrix, true);
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    matrix.postRotate(270);
                    rotatedBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
                            scaledBitmap.getWidth(), scaledBitmap.getHeight(),
                            matrix, true);
                    break;
                default:
                    rotatedBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
                            scaledBitmap.getWidth(), scaledBitmap.getHeight(),
                            matrix, true);
                    break;
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return rotatedBitmap;
    }

    @Override
    public void onStart() {
        super.onStart();

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        client.connect();
        Action viewAction = Action.newAction(
                Action.TYPE_VIEW, // TODO: choose an action type.
                "Main Page", // TODO: Define a title for the content shown.
                // TODO: If you have web page content that matches this app activity's content,
                // make sure this auto-generated web page URL is correct.
                // Otherwise, set the URL to null.
                Uri.parse("http://deeplink/path"),
                // TODO: Make sure this auto-generated app URL is correct.
                Uri.parse("android-app://com.bangk.payyap/payyap/deeplink/path")
        );
        AppIndex.AppIndexApi.start(client, viewAction);
    }

    @Override
    public void onStop() {
        super.onStop();

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        Action viewAction = Action.newAction(
                Action.TYPE_VIEW, // TODO: choose an action type.
                "Main Page", // TODO: Define a title for the content shown.
                // TODO: If you have web page content that matches this app activity's content,
                // make sure this auto-generated web page URL is correct.
                // Otherwise, set the URL to null.
                Uri.parse("http://deeplink/path"),
                // TODO: Make sure this auto-generated app URL is correct.
                Uri.parse("android-app://com.bangk.payyap/payyap/deeplink/path")
        );
        AppIndex.AppIndexApi.end(client, viewAction);
        client.disconnect();
    }

    public class ImageSaver {

        private String directoryName = "images";
        private String fileName = "image.png";
        private Context context;

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

        public ImageSaver setFileName(String fileName) {
            this.fileName = fileName;
            return this;
        }

        public ImageSaver setDirectoryName(String directoryName) {
            this.directoryName = directoryName;
            return this;
        }

        public void save(Bitmap bitmapImage) {
            FileOutputStream fileOutputStream = null;
            try {
                fileOutputStream = new FileOutputStream(createFile());
                //bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
                bitmapImage.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (fileOutputStream != null) {
                        fileOutputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @NonNull
        private File createFile() {
            File file = new File(selectedFile);

            this.fileName = "ROTATED_" + file.getName();

            if (file.exists()) file.delete();
            //File directory = context.getDir(directoryName, Context.MODE_PRIVATE);
            File directory = new File(Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_PICTURES), Config.IMAGE_DIRECTORY_NAME);
            File newFile = new File(directory, fileName);
            selectedFile = newFile.getAbsolutePath();
            return newFile;
        }

        public Bitmap load() {
            FileInputStream inputStream = null;
            try {
                inputStream = new FileInputStream(createFile());
                return BitmapFactory.decodeStream(inputStream);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }
    }

    private void startUpload() {
        callJavaScript("startUploading", imageNo);
    }

    /**
     * Create a file Uri for saving an image or video
     */
    private static Uri getOutputMediaFileUri(int type) {
        return Uri.fromFile(getOutputMediaFile(type));
    }

    /**
     * Create a File for saving an image or video
     */
    private static File getOutputMediaFile(int type) {
        // To be safe, you should check that the SDCard is mounted
        // using Environment.getExternalStorageState() before doing this.

        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES), Config.IMAGE_DIRECTORY_NAME);
        // This location works best if you want the created images to be shared
        // between applications and persist after your app has been uninstalled.

        // Create the storage directory if it does not exist
        if (!mediaStorageDir.exists()) {
            if (!mediaStorageDir.mkdirs()) {
                Log.d("photoBLAST", "failed to create directory");
                return null;
            }
        }

        // Create a media file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        File mediaFile;
        if (type == MEDIA_TYPE_IMAGE) {
            mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
        } else {
            return null;
        }

        return mediaFile;
    }


    boolean loadingFinished = true;
    boolean redirect = false;

    private class PayYapWebApp extends WebViewClient {

        private String action = "";
        private int running = 0; // Could be public if you want a timer to check.

//        @Override
//        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
//            handler.proceed(); // Ignore SSL certificate errors
//        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView webView, String url) {
            webView.stopLoading();
            try {
                Uri uri = Uri.parse(url);
                action = uri.getHost();

                if (uri.getScheme().equals(SITE_SCHEMA)) {
                    if (action.equals("login")) {
                        webView.stopLoading();
                        String account_hash = uri.getQueryParameter("account_hash");
                        if (account_hash.length() > 0) {
                            saveUserHash(account_hash);
                            callJavaScript("showHome", account_hash);
                            callJavaScript("showHideLoader", false);
                        }
                        return false;
                    } else if (action.equals("logout")) {
                        webView.stopLoading();
                        saveUserHash("");

                        callJavaScript("showLogin");
                        return false;
                    } else if (action.equals("selectPhoto")) {
                        imageNo = Integer.valueOf(uri.getQueryParameter("imageNo"));
                        mediaAction = "selectPhoto";
                        webView.stopLoading();

                        Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
                        getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
                        photoPickerIntent.setType("image/*");
                        startActivityForResult(photoPickerIntent, SELECT_IMAGE_ACTIVITY_REQUEST_CODE);

                        return false;
                    } else if (action.equals("takePhoto")) {
                        imageNo = Integer.valueOf(uri.getQueryParameter("imageNo"));
                        mediaAction = "takePhoto";
                        webView.stopLoading();

                        if (!isDeviceSupportCamera()) {
                            showAlert("Device has no camera");
                            return false;
                        }
                        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                            showAlert("Device has no camera permission");
                            return false;
                        }

                        // create Intent to take a picture and return control to the calling application
                        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

                        fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image
                        intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name

                        // start the image capture Intent
                        startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
                        return false;
                    } else if (action.equals("openConfirmModal")) {
                        webView.stopLoading();
                        if (mediaAction == "selectPhoto") startUpload();
                        else webView.showContextMenu();
                        return false;
                    } else if (action.equals("uploadPhoto")) {
                        webView.stopLoading();
                        //new UploadFileToServer().execute();
                        new UploadFileToServer().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
                        return false;
                    } else if (action.equals("startUpdatingPhoto")) {
                        webView.stopLoading();
                        showProgressDialog("Updating...");
                        callJavaScript("updatePhoto");
                        return false;
                    } else if (action.equals("showProgressDialog")) {
                        showProgressDialog("Preparing...");
                        return false;
                    } else if (action.equals("hideProgressDialog")) {
                        hideProgressDialog();
                        return false;
                    } else if (action.equals("openLink")) {
                        String path = uri.getPath();
                        if (path != null) path = path.substring(1);

                        String urlString = "https://photo." + API_DOMAIN + "/" + path;
                        if (path.contains("http://") || path.contains("https://")) {
                            urlString = path;
                        }
                        openWebPage(urlString);
                        return false;
                    } else if (action.equals("showAlert")) {
                        hideProgressDialog();
                        webView.stopLoading();
                        String message = uri.getPath();
                        if (message != null) message = message.substring(1);
                        showAlert(message);
                        return false;
                    } else if (action.equals("confirmAccountVerification")) {
                        hideProgressDialog();
                        webView.stopLoading();
                        confirm("ConfirmAccountVerification", "Before you begin taking MasterCard / VISA payments using this account, we need for you to simply verify your identity. Please continue to begin the Identity Verification Wizard now.");
                        return false;
                    } else if (action.equals("finish")) {
                        finish();
                        return false;
                    } else if (action.equals("openContact")) {
                        String path = uri.getPath();
                        if (path != null) path = path.substring(1);
                        if (path.contains("tell_friends_form")) {
                            //showProgressDialog("Processing...");

                            new UploadContacts().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
                        } else {
                            // Here, thisActivity is the current activity
                            if (ContextCompat.checkSelfPermission(mainActivity,
                                    Manifest.permission.READ_CONTACTS)
                                    != PackageManager.PERMISSION_GRANTED) {

                                // Should we show an explanation?
                                if (ActivityCompat.shouldShowRequestPermissionRationale(mainActivity,
                                        Manifest.permission.READ_CONTACTS)) {

                                    // Show an expanation to the user *asynchronously* -- don't block
                                    // this thread waiting for the user's response! After the user
                                    // sees the explanation, try again to request the permission.

                                } else {

                                    // No explanation needed, we can request the permission.

                                    ActivityCompat.requestPermissions(mainActivity,
                                            new String[]{Manifest.permission.READ_CONTACTS},
                                            MY_PERMISSIONS_REQUEST_READ_CONTACTS);

                                    // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
                                    // app-defined int constant. The callback method gets the
                                    // result of the request.
                                }
                            } else {
                                openContactPicker();
                            }
                        }
                    }
                } else if (uri.getScheme().equals("http") || uri.getScheme().equals("https")) {
                    openWebPage(uri.toString());
                    return false;
                } else if (url.startsWith("mailto:")) {
                    Intent i = new Intent(Intent.ACTION_SENDTO, Uri.parse(url));
                    startActivity(i);
                    return false;
                }


            } catch (Exception ex) {
                showErrorMessage(ex);
            }
            return false;
//            running++;
//            webView.loadUrl(url);
//            return true;
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            running = Math.max(running, 1); // First request move it to 1.
        }

        @Override
        public void onPageFinished(WebView webView, String url) {
            if (action == null) return;
            Log.d("ACTION", action);
            if (--running == 0) {
                if (action.equals("")) {
                    if (getUserHash() == "") {
                        callJavaScript("showLogin");
                    } else {
                        callJavaScript("showHome", getUserHash());
                    }
                }
            }
        }
    }

    @Override
    public void onBackPressed() {
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        //if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
        if ((keyCode == KeyEvent.KEYCODE_BACK)) {
            //webView.goBack();

            //callJavaScript("goBack");

            return false;
        } else {
            finish();
        }
        return super.onKeyDown(keyCode, event);
    }

    /**
     * Open a web page of a specified URL
     *
     * @param url URL to open
     */
    public void openWebPage(String url) {
        Uri webpage = Uri.parse(url);
        Intent intent = new Intent(Intent.ACTION_VIEW, webpage);
        if (intent.resolveActivity(getPackageManager()) != null) {
            startActivity(intent);
        }
    }

    private void showProgressDialog(String message) {
        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.setMessage(message);
        } else {
            progressDialog = ProgressDialog.show(MainActivity.this, "", message);
        }
    }

    private void hideProgressDialog() {
        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.dismiss();
        }
    }


    private void callJavaScript(String methodName, Object... params) {
        callJavaScript(webView, methodName, params);
    }

    private void callJavaScript(WebView view, String methodName, Object... params) {
        try {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("javascript:try{");
            stringBuilder.append(methodName);
            stringBuilder.append("(");
            String separator = "";
            for (Object param : params) {
                stringBuilder.append(separator);
                separator = ",";
                if (param instanceof String) {
                    stringBuilder.append("'");
                }
                stringBuilder.append(param);
                if (param instanceof String) {
                    stringBuilder.append("'");
                }

            }
            stringBuilder.append(")}catch(error){console.error(error.message);}");
            final String call = stringBuilder.toString();
            //Log.i(TAG, "callJavaScript: call="+call);


            view.loadUrl(call);
        } catch (Exception ex) {
            showErrorMessage(ex);
        }
    }

    private String getUserHash() {
        SharedPreferences sharedPref = this.getPreferences(Context.MODE_PRIVATE);
        return sharedPref.getString(getString(R.string.user_hash), "");
    }

    private void saveUserHash(String hash) {
        SharedPreferences sharedPref = this.getPreferences(Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPref.edit();
        editor.putString(getString(R.string.user_hash), hash);
        editor.commit();
    }

    private String getHtmlFromTemplate(String file) {
        AssetManager assetManager = getAssets();
        InputStream inputStream = null;
        try {
            inputStream = assetManager.open(file);
            String text = loadTextFile(inputStream);
            if (file.contains("HTML/index.html")) {
                text = replaceSiteSchemaTemplateVariable(text);
            }
            return text;
        } catch (IOException e) {

        } finally {
            if (inputStream != null)
                try {
                    inputStream.close();
                } catch (IOException e) {

                }
        }
        return "";
    }

    private String replaceSiteSchemaTemplateVariable(String string) {
        string = string.replace("[[SITE_SCHEMA]]", SITE_SCHEMA);
        string = string.replace("[[SITE_TITLE]]", SITE_TITLE);
        string = string.replace("[[API_DOMAIN]]", API_DOMAIN);
        string = string.replace("[[VERIFICATION_FORM]]", getHtmlFromTemplate("HTML/verfication_form.html"));
        string = string.replace("[[VERIFICATION_PHOTO_ID_FORM]]", getHtmlFromTemplate("HTML/verification_form_advanced.html"));
        return string;
    }

    private String loadTextFile(InputStream inputStream) throws IOException {
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        byte[] bytes = new byte[4096];
        int len = 0;
        while ((len = inputStream.read(bytes)) > 0)
            byteStream.write(bytes, 0, len);
        return new String(byteStream.toByteArray(), "UTF8");
    }

    private void showAlert(String message) {
        hideProgressDialog();
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
        alertDialogBuilder.setMessage(message);
        alertDialogBuilder.setPositiveButton("Ok",
                new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface arg0, int arg1) {
                    }
                });

        AlertDialog alertDialog = alertDialogBuilder.create();
        alertDialog.show();
    }

    private void showErrorMessage(Exception ex) {
        showAlert("Something went wrong, please try again!");
        Log.d("APP_EXCEPTION", "ERRPR: " + ex.getMessage());
    }

    private void confirm(final String type, String message) {
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
        alertDialogBuilder.setMessage(message);

        alertDialogBuilder.setPositiveButton("Ok",
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface arg0, int arg1) {
                        if (type == "ConfirmAccountVerification") {
                            callJavaScript("showVerificationForm", getUserHash());
                        }
                    }
                });

        alertDialogBuilder.setNegativeButton("cancel",
                new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface arg0, int arg1) {
                        if (type == "ConfirmAccountVerification") {
                            //
                        }
                    }
                });

        AlertDialog alertDialog = alertDialogBuilder.create();
        alertDialog.show();
    }

    private void flashMessage(String message) {
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
        //showAlert(message);
    }

    private String jsonMessage(String value) {
        String message = "";
        try {
            JSONObject obj = new JSONObject();
            obj.put("msg", value);
            final String json = obj.toString(); // <-- JSON string
            message = json;
        } catch (Exception e) {

        }
        return message;
    }

    public class ExSSLSocketFactory extends SSLSocketFactory {
        SSLContext sslContext = SSLContext.getInstance("TLS");

        public ExSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
            super(truststore);
            TrustManager x509TrustManager = new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] chain, String authType) {
                }

                public void checkServerTrusted(X509Certificate[] chain, String authType) {
                }

                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            };

            sslContext.init(null, new TrustManager[]{x509TrustManager}, null);
        }

        public ExSSLSocketFactory(SSLContext context) throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException {
            super(null);
            sslContext = context;
        }

        @Override
        public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
            return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
        }

        @Override
        public Socket createSocket() throws IOException {
            return sslContext.getSocketFactory().createSocket();
        }
    }

    long totalSize = 0;

    /**
     * Uploading the file to server
     */
    private class UploadFileToServer extends AsyncTask<Void, Integer, String> {
        private int imageSequence = imageNo;

        @Override
        protected void onPreExecute() {
            Log.d("FILE_UPLOAD_URL", Config.FILE_UPLOAD_URL);
            imageSequence = imageNo;
            // setting progress bar to zero
            callJavaScript("setProgress", 0, imageSequence);
            super.onPreExecute();
        }

        @Override
        protected void onProgressUpdate(Integer... progress) {
            Log.d("PROGRESS", "photo " + imageSequence + " > " + progress[0] + "%");
            callJavaScript("setProgress", progress[0], imageSequence);
        }

        @Override
        protected String doInBackground(Void... params) {
            return uploadFile();
        }

        @SuppressWarnings("deprecation")
        private String uploadFile() {
            if (!isNetworkAvailable()) {
                return jsonMessage("Device has no internet connection");
            }

            String responseString = null;


            HttpClient httpclient = new DefaultHttpClient();

//            HttpClient httpclient = getHttpsClient(new DefaultHttpClient());
//            HttpParams params = new BasicHttpParams();
//            HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
//            HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

            HttpPost httppost = new HttpPost(Config.FILE_UPLOAD_URL);

            try {
                AndroidMultiPartEntity entity = new AndroidMultiPartEntity(
                        new ProgressListener() {

                            @Override
                            public void transferred(long num) {
                                publishProgress((int) ((num / (float) totalSize) * 100));
                            }
                        });

                File sourceFile = new File(selectedFile);

                // Adding file data to http body
                entity.addPart("file", new FileBody(sourceFile));

                // Extra parameters if you want to pass to server
                entity.addPart("hash", new StringBody(getUserHash()));
                entity.addPart("device", new StringBody("android"));
                entity.addPart("imageNo", new StringBody(String.valueOf(imageNo)));
                entity.addPart("action", new StringBody("upload"));

                //uploadFor
                String uploadFor = "";
                if (imageNo == 1) uploadFor = "account_identity_manager_photo_id_filename";
                else if (imageNo == 2)
                    uploadFor = "account_identity_manager_proof_of_residence_filename";
                else if (imageNo == 3)
                    uploadFor = "account_identity_manager_banking_statement_filename";
                else if (imageNo == 4)
                    uploadFor = "account_identity_manager_business_certificate_filename";
                else if (imageNo == 5)
                    uploadFor = "account_identity_manager_proof_of_business_location_filename";
                else if (imageNo == 6)
                    uploadFor = "account_identity_manager_banking_statement_filename";

                entity.addPart("uploader_name", new StringBody(uploadFor));


                totalSize = entity.getContentLength();
                httppost.setEntity(entity);

                // Making server call
                HttpResponse response = httpclient.execute(httppost);
                HttpEntity r_entity = response.getEntity();

                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode == 200) {
                    // Server response
                    responseString = EntityUtils.toString(r_entity);
                } else {
                    responseString = "Error occurred! Http Status Code: "
                            + statusCode;
                }

            } catch (ClientProtocolException e) {
                responseString = e.toString();
            } catch (IOException e) {
                responseString = e.toString();
            }

            return responseString;

        }

        @Override
        protected void onPostExecute(String result) {
            Log.d("TAG", "Response from server: " + result);

            // showing the server response in an alert dialog
            //showAlert(result);
            callJavaScript("uploadFinished", result);

            super.onPostExecute(result);
        }

    }

    long totalContactsSize = 0;

    /**
     * Uploading the Contacts to server
     */
    private class UploadContacts extends AsyncTask<Void, Integer, String> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected void onProgressUpdate(Integer... progress) {
            //Log.d("PROGRESS", "photo " + imageSequence + " > " + progress[0] + "%");
        }

        @Override
        protected String doInBackground(Void... params) {
            return uploadContacts();
        }

        @SuppressWarnings("deprecation")
        private String uploadContacts() {
            if (!isNetworkAvailable()) {
                return jsonMessage("Device has no internet connection");
            }


            String contacts = getAllContacts(getApplicationContext());

            String responseString = null;


            HttpClient httpclient = new DefaultHttpClient(); //HttpsClientBuilder.getBelieverHttpsClient();

            HttpPost httppost = new HttpPost(Config.CONTACTS_UPLOAD_URL);

            try {
                AndroidMultiPartEntity entity = new AndroidMultiPartEntity(
                        new ProgressListener() {

                            @Override
                            public void transferred(long num) {
                                publishProgress((int) ((num / (float) totalContactsSize) * 100));
                            }
                        });


                entity.addPart("hash", new StringBody(getUserHash()));
                entity.addPart("contacts", new StringBody(contacts));

                totalContactsSize = entity.getContentLength();
                httppost.setEntity(entity);

                // Making server call
                HttpResponse response = httpclient.execute(httppost);
                HttpEntity r_entity = response.getEntity();

                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode == 200) {
                    // Server response
                    responseString = EntityUtils.toString(r_entity);
                } else {
                    responseString = "Error occurred! Http Status Code: "
                            + statusCode;
                }

            } catch (ClientProtocolException e) {
                responseString = e.toString() + " error line : " + e.getStackTrace()[2].getLineNumber();
            } catch (IOException e) {
                responseString = e.toString() + " error line : " + e.getStackTrace()[2].getLineNumber();
            }

            return responseString;

        }

        @Override
        protected void onPostExecute(String result) {
            Log.d("TAG", "Response from server: " + result);

            // showing the server response in an alert dialog
            //showAlert(result);
            callJavaScript("contactUploadFinished");

            super.onPostExecute(result);
        }


    }
}
