package com.reactlibrary.vishwamdkyclib.Networking;

/*
 * Vishwam Corp CONFIDENTIAL

 * Vishwam Corp 2018
 * All Rights Reserved.

 * NOTICE:  All information contained herein is, and remains
 * the property of Vishwam Corp. The intellectual and technical concepts contained
 * herein are proprietary to Vishwam Corp
 * and are protected by trade secret or copyright law of U.S.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Vishwam Corp
 */

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.os.AsyncTask;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;

import com.microsoft.appcenter.analytics.Analytics;
import com.reactlibrary.R;
import com.reactlibrary.vishwamdkyclib.APICompletionCallback;
import com.reactlibrary.vishwamdkyclib.CrashProof;
import com.reactlibrary.vishwamdkyclib.VishwamError;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.CertificatePinner;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;

import static com.reactlibrary.vishwamdkyclib.Activities.VishwamDocActivity.aadhaarAnalysis;
import static com.reactlibrary.vishwamdkyclib.Tracker.FaceDect.Rx_L;
import static com.reactlibrary.vishwamdkyclib.Tracker.FaceDect.Rx_U;
import static com.reactlibrary.vishwamdkyclib.Tracker.FaceDect.Ry_L;
import static com.reactlibrary.vishwamdkyclib.Tracker.FaceDect.Ry_U;
import static com.reactlibrary.vishwamdkyclib.Tracker.FaceDect.slope_T;
import static okhttp3.Protocol.HTTP_1_1;

/**
 * This is helper class used all network operations using okhttp.
 * **/
public class VishwamNetworkHelper {
    private APICompletionCallback onResponseReceived;
    private String docPath, facePath;
    public static String path224llll, pathHalfDoc;
    public Context context;
    public static JSONObject frontJSON = null, rearJSON = null;
    private boolean frontOrNot, allowDataLogging;
    public static boolean isFront = false, isBack = false;
    public static String ocrFrontBlock = "", ocrBackBlock = "", docfaceCoordinates = "", liveFaceCoordinates = "", ocrBackPlots = "", ocrFrontPlots = "";
    private int env, matchType;
    private String referenceId, app_id;
    private static String frontResponse = "";
    private String authTok = "", secretKey = "" , storeID = "";
    private SharedPreferences prefs;
    private String sdk_version;
    public static JSONObject paramBE = null;
    public static boolean doSuccessLogs;
    /**
     * Constructor to initialise with context and string appid and type of environment.
     * This is also used to get auth token by generating jwt token for passing on all network calls.
     * **/
    public VishwamNetworkHelper(Context context1, String appId, int env, String secureKey) {
        this.context = context1;
        this.app_id = appId;
        this.env = env;
        this.secretKey = secureKey;
        this.sdk_version = context1.getString(R.string.sdk_version);
        doSuccessLogs = true;

        prefs = PreferenceManager.getDefaultSharedPreferences(context);
        String previousDateString = prefs.getString("date_string", "");
//        Log.e("authdateString", previousDateString);

        authTok = prefs.getString("auth_token", "");
//        Log.e("prefesAuthTOken1", authTok);

        String currentDate = getDateString();

        if (!previousDateString.equals("")) {
            if (!currentDate.equals(previousDateString)) {
                if (checkInternetConnection()) {
                    new ApiCallForAuthToken().execute();
                } else {
                    Toast.makeText(context, "No Active Internet Connection found", Toast.LENGTH_SHORT).show();
                }
            }
        } else {
            if (checkInternetConnection()) {
                new ApiCallForAuthToken().execute();
            } else {
                Toast.makeText(context, "No Active Internet Connection found", Toast.LENGTH_SHORT).show();
            }
        }
    }

    /**
     * This is generate log ocr network call on  to aws pinpoint analytics.
     * **/
    public void logOcrNetworkEvent(String eventName,Boolean isFront,String referenceId) {
        if(doSuccessLogs){
            Map<String, String> properties = new HashMap<>();
            if (isFront) {
                properties.put("DocType", "Front");
            } else {
                properties.put("DocType", "Back");
            }
            properties.put("ReferenceId",referenceId);

            Analytics.trackEvent(eventName, properties);
        }

    }
    /**
     * This is generate log no internet on to aws pinpoint analytics.
     * **/
    public  void logNoInternetEvent(String ActivityName,String referenceId) {
        Map<String, String> properties = new HashMap<>();
        properties.put("Activity", ActivityName);

        properties.put("ReferenceId",referenceId);

        Analytics.trackEvent("No Internet", properties);

    }


    /**
     * Method used making ocr read document network call by passing  different parameters and APICompletionCallback to handover the response to other activity.
     * **/
    public void makeOCRCall(int env, String imgPath, JSONObject apiDocParams, JSONObject headers, APICompletionCallback onResponseReceived) {
        this.onResponseReceived = onResponseReceived;
        try {
            this.env = env;
            this.docPath = imgPath;
            this.frontOrNot = apiDocParams.getBoolean("front_view");

            this.referenceId = headers.getString("referenceId");

            if (apiDocParams.has("allowDataLogging")){
                this.allowDataLogging = apiDocParams.getBoolean("allowDataLogging");
            }else{
                this.allowDataLogging = false;
            }
            if (apiDocParams.has("store_id")){
                this.storeID = apiDocParams.getString("store_id");
            }else{
                this.storeID = " ";
            }
            if (apiDocParams.has("app_id")) {
                this.app_id = apiDocParams.getString("app_id");
                if (checkInternetConnection()) {
                    new ApiCallForDocCheck().execute();
                } else {
                    this.onResponseReceived.onResponse(new VishwamError(VishwamError.NO_INTERNET, "No Active Internet Connection found"), null, null);
                    logNoInternetEvent("OnOcrCall",referenceId);

                }
            } else {
                this.onResponseReceived.onResponse(new VishwamError(VishwamError.NO_APP_ID, "app_id not found"), null, null);
                logNoInternetEvent("OnOcrCall",referenceId);

            }

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    /**
     * Method used making face match network call by passing  different parameters and APICompletionCallback to handover the response to other activity.
     * **/
    public void makeFaceMatchCall(int env, String customerUri, String docUri, JSONObject apiFMParams, JSONObject headers, APICompletionCallback onResponseReceived) {
        this.onResponseReceived = onResponseReceived;
        try {
            this.docPath = docUri;
            this.facePath = customerUri;
            this.env = env;
            this.matchType = apiFMParams.getInt("match_type");
            this.referenceId = headers.getString("referenceId");
            if (apiFMParams.has("allowDataLogging")){
                this.allowDataLogging = apiFMParams.getBoolean("allowDataLogging");
            }else{
                this.allowDataLogging = false;
            }
            if (apiFMParams.has("store_id")){
                this.storeID = apiFMParams.getString("store_id");
            }else{
                this.storeID = " ";
            }
            if (apiFMParams.has("app_id")) {
                this.app_id = apiFMParams.getString("app_id");
                if (checkInternetConnection()) {
                    new ApiCallForFaceMatch().execute();
                } else {
                    logNoInternetEvent("OnFaceMatchCall",referenceId);
                    this.onResponseReceived.onResponse(new VishwamError(VishwamError.NO_INTERNET, "No Active Internet Connection found"), null, null);

                }
            } else {
                this.onResponseReceived.onResponse(new VishwamError(VishwamError.NO_APP_ID, "app_id not found"), null, null);
                logEvent("NoAppId");

            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    /**
     * This is generate log facematch call on to aws pinpoint analytics.
     * **/
    public void logFaceMatchNetworkEvent(Boolean isDocCustomerType,String orn) {
        if(doSuccessLogs){
            Map<String, String> properties = new HashMap<>();
            properties.put("ReferenceId",orn);
            if (isDocCustomerType) {
                properties.put("CallType", "Doc_Customer");
            } else {
                properties.put("CallType", "Customer_Agent");
            }
            Analytics.trackEvent("OnFaceMatchCall", properties);
        }

    }
    /**
     * This is generate log ocr document error event on to aws pinpoint analytics.
     * **/
    public void logDocApiErrorEvent(String orn,String error) {
        Map<String, String> properties = new HashMap<>();
        properties.put("ReferenceId",orn);


        Analytics.trackEvent("OCR"+limitTo50Chars(error), properties);
    }
    /**
     * This is generate log ocr document success event on to aws pinpoint analytics.
     * **/
    public void logDocApiSuccessEvent(String orn) {
        if(doSuccessLogs){
            Map<String, String> properties = new HashMap<>();
            properties.put("ReferenceId",orn);

            Analytics.trackEvent("OnOcrApiSuccess", properties);
        }

    }

    /**
     * This is AsyncTask to make read document network call creating new thread and passing on the response to main Ui thread
     * This uses okhttp lib with multipart builder to build with  ocr documents images.
     * **/
    @SuppressLint("StaticFieldLeak")
    public class ApiCallForDocCheck extends AsyncTask<String, String, CrashProof> {

        @Override
        protected CrashProof doInBackground(String... strings) {

            String url = null, server = null;
            switch (env) {
                case 0:
                    server = context.getString(R.string.staging_server);
                    url = "https://" + server + "/v1/read_document";
                    break;
                case 1:
                    server = context.getString(R.string.prod_server);
                    url = "https://" + server + "/v1/read_document";
                    break;

                case 2:
                    server = context.getString(R.string.replica_server);
                    url = "https://" + server + "/v1/read_document";
                    break;
            }
            //Log.e("vishwamSukshiUrl", url);

            CertificatePinner certificatePinner = new CertificatePinner.Builder()
                    .add(server, "sha256/" + context.getString(R.string.certificateKey))
                    .build();

            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(20, TimeUnit.SECONDS)
                    .writeTimeout(20, TimeUnit.SECONDS)
                    .readTimeout(20, TimeUnit.SECONDS)
                    .protocols(Collections.singletonList(HTTP_1_1))
                    .certificatePinner(certificatePinner)
                    .build();

            final File imageFile = new File(docPath);
            final File imageFile224 = new File(path224llll);
            //Log.e("fullDocImageSize", String.valueOf(Integer.parseInt(String.valueOf(imageFile.length()/1024))));

            MultipartBody.Builder multipartBodyBuilder = new MultipartBody.Builder();
            multipartBodyBuilder.setType(MultipartBody.FORM); //this may not be needed
            String decision;
            //Log.e("vishwamSukshiORN",referenceId);

            logOcrNetworkEvent("OnOCRCall",frontOrNot,referenceId);


            if (frontOrNot) {
                String delay = aadhaarAnalysis.getAadhaarIndex();
                if (isFront) decision = "1";
                else decision = "0";
                multipartBodyBuilder.addFormDataPart("image", imageFile.getName(), RequestBody.create(MediaType.parse("image/jpg"), imageFile));
                multipartBodyBuilder.addFormDataPart("image2", imageFile224.getName(), RequestBody.create(MediaType.parse("image/jpg"), imageFile224));
                multipartBodyBuilder.addFormDataPart("app_id", app_id);
                multipartBodyBuilder.addFormDataPart("is_back", "0");
                multipartBodyBuilder.addFormDataPart("decision", decision);
                multipartBodyBuilder.addFormDataPart("ocr_block", ocrFrontBlock);
                multipartBodyBuilder.addFormDataPart("plots", ocrFrontPlots);
                //Log.e("shankPlots", ocrFrontPlots);
                multipartBodyBuilder.addFormDataPart("referenceId", referenceId);
                multipartBodyBuilder.addFormDataPart("store_id", storeID);
                multipartBodyBuilder.addFormDataPart("version", sdk_version);
                multipartBodyBuilder.addFormDataPart("delay", delay);
//                Log.e("vishwamOBDFront1", delay);
//                Log.d("ASDversion",sdk_version);?

                if (frontJSON != null) {
                    multipartBodyBuilder.addFormDataPart("ocr_result", frontJSON.toString());
                    //Log.e("frontJSONShank", frontJSON.toString());
                } else {
                    multipartBodyBuilder.addFormDataPart("ocr_result", "");
                }
            } else {
                String delay = aadhaarAnalysis.getAadhaarIndex();
                if (isBack) decision = "1";
                else decision = "0";

                multipartBodyBuilder.addFormDataPart("image", imageFile.getName(), RequestBody.create(MediaType.parse("image/jpg"), imageFile));
                multipartBodyBuilder.addFormDataPart("image2", imageFile224.getName(), RequestBody.create(MediaType.parse("image/jpg"), imageFile224));
                multipartBodyBuilder.addFormDataPart("app_id", app_id);
                multipartBodyBuilder.addFormDataPart("is_back", "1");
                multipartBodyBuilder.addFormDataPart("decision", decision);
                multipartBodyBuilder.addFormDataPart("ocr_block", ocrBackBlock);
                multipartBodyBuilder.addFormDataPart("check_info", frontResponse);
                //Log.e("vishwamSukshiCheckInfo", frontResponse);
                multipartBodyBuilder.addFormDataPart("plots", ocrBackPlots);
                //Log.e("shankPlotsNetwork", ocrBackPlots);
                multipartBodyBuilder.addFormDataPart("referenceId", referenceId);
                multipartBodyBuilder.addFormDataPart("store_id", storeID);
                multipartBodyBuilder.addFormDataPart("version", sdk_version);
                multipartBodyBuilder.addFormDataPart("delay", delay);
//                Log.e("vishwamOBDBack1", delay);

                if (rearJSON != null) {
                    multipartBodyBuilder.addFormDataPart("ocr_result", rearJSON.toString());
                    //Log.e("rearJSONShank", rearJSON.toString());
                } else multipartBodyBuilder.addFormDataPart("ocr_result", "");
            }

            authTok = prefs.getString("auth_token", "");
//            Log.e("prefesAuthTOken1", authTok);

            Request request = new Request.Builder()
                    .header("Authorization", "Bearer " + authTok)
                    .url(url)
                    .post(multipartBodyBuilder.build())
                    .build();

            Response docResponse;
            CrashProof crashProof;

            try {
                docResponse = client.newCall(request).execute();
//                Log.e("vishwamSukshiDocResp", String.valueOf(docResponse));

                if (docResponse.code() == 400) {
                    return new CrashProof("Bad Request", null);
                } else if (docResponse.code() == 401) {
                    return new CrashProof("Unathorised request", null);
                } else if (docResponse.code() == 500 || docResponse.code() == 502) {
                    return new CrashProof("Internal Server Error", null);
                } else {
                    Headers headers = docResponse.headers();
                    String refID = headers.get("referenceid");
                    String reqId = headers.get("requestid");
                    //Log.e("xcall", reqId);

                    ResponseBody responseBody = docResponse.body();
                    JSONObject jsonObject = new JSONObject(responseBody.string());
                    String statusCode = jsonObject.getString("statusCode");

                    crashProof = new CrashProof(null, docResponse);
                    crashProof.setReferenceid(refID);
                    crashProof.setRequestid(reqId);
                    crashProof.setHeaderStatusCode(docResponse.code());
                    crashProof.setBodyStatusCode(statusCode);
                    crashProof.setResponseBodyJson(jsonObject);
                    return crashProof;
                }
            } catch (IOException e) {
//                Log.e("vishwamSukshiIO", e.toString());
                return new CrashProof("Request timed out", null);
            } catch (JSONException e) {
//                Log.e("vishwamSukshiJ", e.toString());
                return new CrashProof("Json Exception", null);
            }
        }

        @Override
        protected void onPostExecute(CrashProof crashProof) {
            super.onPostExecute(crashProof);
            if (crashProof.getErrorType() != null) {
                logDocApiErrorEvent(referenceId,"RequestTimeout");


                onResponseReceived.onResponse(new VishwamError(VishwamError.REQUEST_TIME_OUT, crashProof.getErrorType()), null, null);
            } else if (crashProof.getResponse() != null) {

                if (crashProof.getHeaderStatusCode() == 502 || crashProof.getHeaderStatusCode() == 500) {
                    logDocApiErrorEvent(crashProof.getReferenceid(),"Internal Server Error");

                    onResponseReceived.onResponse(new VishwamError(VishwamError.INTERNAL_SERVER_ERROR, "Internal Server Error"), null, null);
                } else if (crashProof.getHeaderStatusCode() == 400) {
                    logDocApiErrorEvent(crashProof.getReferenceid(),"Bad request");

                    onResponseReceived.onResponse(new VishwamError(VishwamError.BAD_REQUEST, "Bad request"), null, null);
                } else if (crashProof.getHeaderStatusCode() == 401) {
                    logDocApiErrorEvent(crashProof.getReferenceid(),"Unathorised request");

                    onResponseReceived.onResponse(new VishwamError(VishwamError.UN_AUTH, "Unathorised request"), null, null);
                } else {
                    try {
                        JSONObject header = new JSONObject();
                        header.put("Reference-Id", crashProof.getReferenceid());
                        header.put("Request-Id", crashProof.getRequestid());

                        ResponseBody responseBody = crashProof.getResponse().body();
                        JSONObject jsonObject = crashProof.getResponseBodyJson();

                        if (responseBody != null) {
                            logDocApiSuccessEvent(crashProof.getReferenceid());

                            if (crashProof.getBodyStatusCode().equals("200")) {



                                if (jsonObject.has("config")){
                                    paramBE = jsonObject.getJSONObject("config");

                                    Log.e("santhuConfig", paramBE.toString());

                                     jsonObject.remove("config");

                                    Log.e("santhuConfig2", jsonObject.toString());

                                    if (paramBE != null) {

                                        if (paramBE.has("Rx_L")) {
                                            try {
                                                Rx_L =  paramBE.getDouble("Rx_L");
                                            } catch (JSONException e) {
                                                e.printStackTrace();
                                                Rx_L = 0.7;
                                            }
                                        }
                                        if (paramBE.has("Rx_U")) {
                                            try {
                                                Rx_U =  paramBE.getDouble("Rx_U");
                                            } catch (JSONException e) {
                                                e.printStackTrace();
                                                Rx_U = 1.4;
                                            }
                                        }
                                        if (paramBE.has("Ry_L")) {
                                            try {
                                                Ry_L =  paramBE.getDouble("Ry_L");
                                            } catch (JSONException e) {
                                                e.printStackTrace();
                                                Ry_L = 0.8;
                                            }

                                        }
                                        if (paramBE.has("Ry_U")) {
                                            try {
                                                Ry_U =  paramBE.getDouble("Ry_U");
                                            } catch (JSONException e) {
                                                e.printStackTrace();
                                                Ry_U = 1.7;
                                            }

                                        }

                                        if (paramBE.has("slope")) {
                                            try {
                                                slope_T = paramBE.getDouble("slope");
                                            } catch (JSONException e) {
                                                e.printStackTrace();
                                                slope_T = 0.0556;
                                            }

                                        }
                                    }


                                }/*else {
                                    Rx_L = 0.7f;
                                    Rx_U = 1.4f;
                                    Ry_L = 0.8f;
                                    Ry_U = 1.7f;
                                    slope_T = 1 / 18;
                                }*/

                                onResponseReceived.onResponse(null, jsonObject, header);
                                if (frontOrNot) {
                                    frontResponse = jsonObject.toString();
                                }

                            } else if (crashProof.getBodyStatusCode().equals("422")) {
                                logDocApiErrorEvent(crashProof.getReferenceid(),jsonObject.getString("error"));

                                onResponseReceived.onResponse(new VishwamError(VishwamError.PROPER_AADHAAR_NOT_FOUND, jsonObject.getString("error")), null, null);
                            } else {
                                logDocApiErrorEvent(crashProof.getReferenceid(),"Bad Request");

                                onResponseReceived.onResponse(new VishwamError(VishwamError.BAD_REQUEST, "Bad Request!"), null, null);
                            }
                        } else {
                            logDocApiErrorEvent(crashProof.getReferenceid(),"Bad Request");

                            onResponseReceived.onResponse(new VishwamError(VishwamError.BAD_REQUEST, "Bad Request!"), null, null);
                        }
                    } catch (JSONException e) {
                        logDocApiErrorEvent(crashProof.getReferenceid(),"Json Exception");

                        onResponseReceived.onResponse(new VishwamError(VishwamError.RESPONSE_JSON_E, "JSON Exception"), null, null);
                        e.printStackTrace();
                    }
                }
            } else {
                logDocApiErrorEvent(crashProof.getReferenceid(),"Request Failed");

                onResponseReceived.onResponse(new VishwamError(VishwamError.RESPONSE_NULL, "Request Failed"), null, null);
            }
        }
    }

    /**
     * This is to log facematch error  event on aws pinpoint analytics.
     * **/
    public void logFaceMatchApiErrorEvent(String orn,String error) {
        Map<String, String> properties = new HashMap<>();
        properties.put("ReferenceId", orn);
        Analytics.trackEvent("FM"+limitTo50Chars(error), properties);
    }
    /**
     * This is to log facematch success  event on aws pinpoint analytics.
     * **/
    public void logFaceMatchApiSuccesEvent(String orn) {
        if(doSuccessLogs){
            Map<String, String> properties = new HashMap<>();
            properties.put("ReferenceId",orn);

            Analytics.trackEvent("OnFaceMatchApiSuccess", properties);
        }
    }
    /**
     * This is to log facematch error  event on aws pinpoint analytics.
     * **/
    File imageFile2;


    /**
     * This is AsyncTask to make face match network call creating new thread and passing on the response to main Ui thread
     * This uses okhttp lib with multipart builder to build with  faces images.
     * **/
    @SuppressLint("StaticFieldLeak")
    public class ApiCallForFaceMatch extends AsyncTask<String, String, CrashProof> {

        @SuppressLint("LongLogTag")
        @Override
        protected CrashProof doInBackground(String... strings) {

            String url = "", server = "";

            switch (env) {
                case 0:
                    server = context.getString(R.string.staging_server);
                    url = "https://" + server + "/v1/face_match";
                    break;
                case 1:
                    server = context.getString(R.string.prod_server);
                    url = "https://" + server + "/v1/face_match";
                    break;

                case 2:
                    server = context.getString(R.string.replica_server);
                    url = "https://" + server + "/v1/face_match";
                    break;
            }

            //Log.e("vishwamSukshiUrl", url);

            CertificatePinner certificatePinner = null;

            if (!server.equals("")){
                 certificatePinner = new CertificatePinner.Builder()
                        .add(server, "sha256/" + context.getString(R.string.certificateKey))
                        .build();
            }else {
                return new CrashProof("Bad Request params", null);
            }

            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(20, TimeUnit.SECONDS)
                    .writeTimeout(20, TimeUnit.SECONDS)
                    .readTimeout(20, TimeUnit.SECONDS)
                    .protocols(Collections.singletonList(HTTP_1_1))
                    .certificatePinner(certificatePinner)
                    .build();

            final File imageFile = new File(facePath);
            if (matchType == 0) {
                imageFile2 = new File(pathHalfDoc);
            } else {
                imageFile2 = new File(docPath);
            }

            //Log.e("faceMatchImageSize", String.valueOf(Integer.parseInt(String.valueOf(imageFile.length() / 1024))));
            //Log.e("faceMatchImageSize2", String.valueOf(Integer.parseInt(String.valueOf(imageFile2.length() / 1024))));
            //Log.e("imageSizereferenceId", referenceId);

            MultipartBody.Builder multipartBodyBuilder = new MultipartBody.Builder();
            multipartBodyBuilder.setType(MultipartBody.FORM);

            multipartBodyBuilder.addFormDataPart("image", imageFile.getName(), RequestBody.create(MediaType.parse("image/jpg"), imageFile));
            multipartBodyBuilder.addFormDataPart("image2", imageFile2.getName(), RequestBody.create(MediaType.parse("image/jpg"), imageFile2));
            /*if (env == 4){
                multipartBodyBuilder.addFormDataPart("app_id", "vishwamdkyc");
                multipartBodyBuilder.addFormDataPart("user_id", referenceId);
            }else{*/
                multipartBodyBuilder.addFormDataPart("app_id", app_id);
            //}
            multipartBodyBuilder.addFormDataPart("referenceId", referenceId);
            multipartBodyBuilder.addFormDataPart("store_id", storeID);
            multipartBodyBuilder.addFormDataPart("version", sdk_version);
            if (matchType == 0) {
                //String coordinates = docfaceCoordinates + "|" + liveFaceCoordinates;
                multipartBodyBuilder.addFormDataPart("coordinates", docfaceCoordinates);
                multipartBodyBuilder.addFormDataPart("vectors", liveFaceCoordinates);
                //Log.e("vishwamSukshicoords", docfaceCoordinates);
                //Log.e("vishwamSukshivects", liveFaceCoordinates);
            }
            multipartBodyBuilder.addFormDataPart("match_type", String.valueOf(matchType));
            //Log.e("matchType", String.valueOf(matchType));

            authTok = prefs.getString("auth_token", "");
//            Log.e("prefesAuthTOken1", authTok);

            Request request = null;
            if (!url.equals("")){
                     request = new Request.Builder()
                        .header("Authorization", "Bearer " + authTok)
                        .url(url)
                        .post(multipartBodyBuilder.build())
                        .build();
            }else {
                return new CrashProof("Bad Request params", null);
            }

            Response matchResponse;
            CrashProof crashProof;

            try {
                matchResponse = client.newCall(request).execute();
//                Log.e("vishwamSukshiMatchResp", String.valueOf(matchResponse));

                if (matchResponse.code() == 400) {
                    return new CrashProof("Bad Request", null);
                } else if (matchResponse.code() == 401) {
                    return new CrashProof("Unauthorized Request", null);
                } else if (matchResponse.code() == 500 || matchResponse.code() == 502) {
                    return new CrashProof("Internal Server Error", null);
                } else {
                    Headers headers = matchResponse.headers();
                    String refID = headers.get("referenceid");
                    String reqId = headers.get("requestid");
//                    Log.e("vishwamSukshiMatchXcall", String.valueOf(headers));

                    ResponseBody responseBody = matchResponse.body();
                    JSONObject jsonObject = new JSONObject(responseBody.string());
//                    Log.e("vishwamSukshiRespBody", jsonObject.toString());
                    String statusCode = jsonObject.getString("statusCode");

                    crashProof = new CrashProof(null, matchResponse);
                    crashProof.setReferenceid(referenceId);
                    crashProof.setRequestid(reqId);
                    crashProof.setHeaderStatusCode(matchResponse.code());
                    crashProof.setBodyStatusCode(statusCode);
                    crashProof.setResponseBodyJson(jsonObject);
                    return crashProof;
                }
            } catch (IOException e) {
                return new CrashProof("Request timed out", null);
            } catch (JSONException e) {
//                Log.e("vishwamSukshiJSONE", e.toString());
                return new CrashProof("Json Exception", null);
            }
        }

        @Override
        protected void onPostExecute(CrashProof crashProof) {
            super.onPostExecute(crashProof);

            try {
                logFaceMatchNetworkEvent(matchType == 0,crashProof.getReferenceid());

                if (crashProof.getErrorType() != null) {
                    logFaceMatchApiErrorEvent(referenceId,"Request Timeout");

                    onResponseReceived.onResponse(new VishwamError(VishwamError.REQUEST_TIME_OUT, crashProof.getErrorType()), null, null);
                } else if (crashProof.getResponse() != null) {

                    if (crashProof.getHeaderStatusCode() == 502 || crashProof.getHeaderStatusCode() == 500) {
                        logFaceMatchApiErrorEvent(referenceId,"Internal Server Error");

                        onResponseReceived.onResponse(new VishwamError(VishwamError.INTERNAL_SERVER_ERROR, "Internal Server Error"), null, null);
                    } else if (crashProof.getResponse().code() == 400) {
                        logFaceMatchApiErrorEvent(referenceId,"Bad Request");

                        onResponseReceived.onResponse(new VishwamError(VishwamError.BAD_REQUEST, "Bad request"), null, null);
                    } else if (crashProof.getHeaderStatusCode() == 401) {
                        logFaceMatchApiErrorEvent(referenceId,"Unauthorised Request");

                        onResponseReceived.onResponse(new VishwamError(VishwamError.UN_AUTH, "Unauthorised request"), null, null);
                    } else {

                        JSONObject header = new JSONObject();
                        header.put("Reference-Id", crashProof.getReferenceid());
                        header.put("Request-Id", crashProof.getRequestid());

                        JSONObject jsonObject = crashProof.getResponseBodyJson();
                        //Log.e("vishwamDocResult", bodyString);

                        if (crashProof.getBodyStatusCode().equals("200")) {
                            logFaceMatchApiSuccesEvent(crashProof.getReferenceid());

                            onResponseReceived.onResponse(null, jsonObject, header);
                        } else {
                            logFaceMatchApiErrorEvent(referenceId,"Face Not Found");

                            onResponseReceived.onResponse(new VishwamError(VishwamError.FACE_NOT_FOUND, jsonObject.getString("error")), null, null);
                        }
                    }
                } else {
                    logFaceMatchApiErrorEvent(referenceId,"Request Failed");

                    onResponseReceived.onResponse(new VishwamError(VishwamError.RESPONSE_NULL, "Request Failed"), null, null);
                }

            } catch (JSONException e) {
                logFaceMatchApiErrorEvent(referenceId,"Json Exception");

                onResponseReceived.onResponse(new VishwamError(VishwamError.RESPONSE_JSON_E, "JSON Exception"), null, null);
                e.printStackTrace();
            }
        }
    }
    /**
     * This is AsyncTask to make auth token network call creating new thread and passing on the response to main Ui thread.
     * **/
    @SuppressLint("StaticFieldLeak")
    public class ApiCallForAuthToken extends AsyncTask<String, String, Response> {

        @Override
        protected Response doInBackground(String... strings) {

            String url = null, server = null;
            switch (env) {
                case 0:
                    server = context.getString(R.string.staging_server);
                    url = "https://" + server + "/v1/auth_token";
                    break;
                case 1:
                    server = context.getString(R.string.prod_server);
                    url = "https://" + server + "/v1/auth_token";
                    break;
                case 2:
                    server = context.getString(R.string.replica_server);
                    url = "https://" + server + "/v1/auth_token";
                    break;
            }
            //Log.e("vishwamSukshiUrl", url);

            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(15, TimeUnit.SECONDS)
                    .writeTimeout(15, TimeUnit.SECONDS)
                    .readTimeout(15, TimeUnit.SECONDS)
                    .protocols(Collections.singletonList(HTTP_1_1))
                    .build();

            MultipartBody.Builder multipartBodyBuilder = new MultipartBody.Builder();
            multipartBodyBuilder.setType(MultipartBody.FORM);
            multipartBodyBuilder.addFormDataPart("app_id", app_id);
            multipartBodyBuilder.addFormDataPart("version", sdk_version);
            multipartBodyBuilder.addFormDataPart("store_id", storeID);

            String jwtToken = JwtGenerator.getToken(app_id, secretKey);

//            Log.e("vishwamSukshiTokenURL", url);
//            Log.e("vishwamSukshiTokenIn", jwtToken);

            Request request = new Request.Builder()
                    .url(url)
                    .header("Authorization", "Bearer " + jwtToken)
                    .post(multipartBodyBuilder.build())
                    .build();

            Response response = null;
            CrashProof crashProof;
            try {

                response = client.newCall(request).execute();
//                Log.e("vishwamSukshiTokenResp", response.toString());

                if (response.code() == 200) {

                    Headers headers = response.headers();
//                    Log.e("vishwamSukshiHead", headers.toString());
                    String authTOken = headers.get("Auth-Token");
//                    Log.e("vishwamSukshiTokenOut", authTOken);

                    String formattedDate = getDateString();
//                    Log.e("vishwamSukshiDate", formattedDate);

                    SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
                    editor.putString("date_string", formattedDate);
                    editor.putString("auth_token", authTOken);
                    editor.apply();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            return response;
        }
    }
    /**
     * Helper method to log event with string as eventname.
     * **/
    public void logEvent(String eventName) {

        Analytics.trackEvent(eventName);

    }
    /**
     * Return a boolean to detect internet.
     * **/
    private boolean checkInternetConnection() {
        ConnectivityManager conMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        return conMgr.getActiveNetworkInfo() != null
                && conMgr.getActiveNetworkInfo().isAvailable()
                && conMgr.getActiveNetworkInfo().isConnected();
    }
    /**
     * Returns string with current date.
     * **/
    private String getDateString() {

        Date date = Calendar.getInstance().getTime();
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy", Locale.getDefault());

        return dateFormat.format(date);
    }


    public String limitTo50Chars(String string){
       // Log.e("ASD",string);
        string =  string.replaceAll("[^a-zA-Z0-9]", "");
        //Log.d("ASDXCV",string);
       // Log.d("ASD",String.valueOf(string.length()));
        if(string.length() > 49 ){

           return  string.substring(0, 40);
        }else {
            return string;
        }
    }
}
