package com.cpm.lorealbaautomation.dailyactivity;

import static com.cpm.lorealbaautomation.constant.CommonFunctions.checkNetIsAvailable;
import static com.cpm.lorealbaautomation.constant.CommonFunctions.getCurrentTime;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Environment;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import android.os.Looper;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import com.google.android.gms.common.api.ResolvableApiException;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.Priority;
import com.google.android.gms.location.SettingsClient;
import com.google.gson.Gson;
import com.cpm.lorealbaautomation.BuildConfig;
import com.cpm.lorealbaautomation.Database.Lorealba_Database;
import com.cpm.lorealbaautomation.DealarBoardActivity;
import com.cpm.lorealbaautomation.R;
import com.cpm.lorealbaautomation.constant.AlertandMessages;
import com.cpm.lorealbaautomation.constant.CommonFunctions;
import com.cpm.lorealbaautomation.constant.CommonString;
import com.cpm.lorealbaautomation.delegates.PrefHelper;
import com.cpm.lorealbaautomation.geotag.GeoTaggingActivity;
import com.cpm.lorealbaautomation.gsonGetterSetter.JCPGetterSetter;
import com.cpm.lorealbaautomation.gsonGetterSetter.JourneyPlan;
import com.cpm.lorealbaautomation.gsonGetterSetter.NotificationData;
import com.cpm.lorealbaautomation.retrofit.PostApi;
import com.cpm.lorealbaautomation.timer.TimerActivity;
import com.cpm.lorealbaautomation.utils.AppUtils;
import com.cpm.lorealbaautomation.utils.DistanceUtils;

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

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class StoreImageActivity extends AppCompatActivity implements View.OnClickListener {
    private static final int PERMISSION_ALL = 99;
    Button btn_save;
    ImageView img_cam, img_clicked;
    String _pathforcheck, _path, str, img_str, selfie_imge, visit_date, username, counter_id, userType;
    private Lorealba_Database db;
    Runnable run;
    Toolbar toolbar;
    ProgressDialog loading;
    private Retrofit adapter;
    private Integer versionCode, mid=0, bid=0, storeId=0;
    private double lat = 0.0;
    private double lon = 0.0;
    private static final int REQUEST_LOCATION = 1;
    boolean clickFlag = false, success_geoTag = true;
    private FusedLocationProviderClient fusedLocationClient = null;
    private LocationCallback locationCallback = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_store_image);
        db = new Lorealba_Database(this);
        db.open();
        SharedPreferences preferences = PrefHelper.getPrefs(this);
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
        img_cam = (ImageView) findViewById(R.id.img_selfie);
        img_clicked = (ImageView) findViewById(R.id.img_cam_selfie);
        btn_save = (Button) findViewById(R.id.btn_save_selfie);
        toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        if (!CommonFunctions.isTablet(this)) {
            toolbar.setTitleTextAppearance(this, R.style.changestext_sizefor_mobile);
        }
        counter_id = preferences.getString(CommonString.KEY_COUNTER_ID, "");
        visit_date = preferences.getString(CommonString.KEY_DATE, "");
        username = preferences.getString(CommonString.KEY_USERNAME, "");
        userType = preferences.getString(CommonString.KEY_USER_TYPE, "");
        try {
            downloadRequiredData();
            versionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            e.fillInStackTrace();
        }

        Objects.requireNonNull(getSupportActionBar()).setHomeButtonEnabled(true);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        setTitle(getString(R.string.counter_selfie) + " - " + username);
        str = CommonString.getImagesFolder(this);
        img_cam.setOnClickListener(this);
        img_clicked.setOnClickListener(this);
        btn_save.setOnClickListener(this);
        run = () -> {
            if (selfie_imge != null && !selfie_imge.isEmpty()) {
                File image1 = new File(str + selfie_imge);
                if (image1.exists()) {
                    image1.delete();
                }
            }
        };
        ////delete old imge from folder
        CommonFunctions.delete_old_imge_from_folder(this, visit_date, db);
        try {
            checkdates();
        } catch (Exception e) {
            e.fillInStackTrace();
        }

        checkAndRequestPermissions();
        getLastLocation();
    }

    private void checkdates() {
        try {
            db.open();
            ArrayList<NotificationData> notiList = db.getNotificationList();
            if (!notiList.isEmpty()) {
                for (int k = 0; k < notiList.size(); k++) {
                    Calendar cal1 = new GregorianCalendar();
                    Calendar cal2 = new GregorianCalendar();
                    @SuppressLint("SimpleDateFormat") SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
                    Date date = sdf.parse(visit_date);
                    assert date != null;
                    cal1.setTime(date);
                    date = sdf.parse(notiList.get(k).getVisited_date());
                    assert date != null;
                    cal2.setTime(date);
                    if (daysBetween(cal1.getTime(), cal2.getTime()) > 7) {
                        db.open();
                        db.deleteNotificationTableafterOneWeek();
                        break;
                    }
                }
            }
        } catch (ParseException e) {
            e.fillInStackTrace();
        }
    }

    public int daysBetween(Date d1, Date d2) {
        return (int) ((d2.getTime() - d1.getTime()) / (1000 * 60 * 60 * 24));
    }

    @SuppressLint("NonConstantResourceId")
    @Override
    public void onClick(View v) {
        int id = v.getId();

        if (id == R.id.img_cam_selfie) {
            clickFlag = true;
            _pathforcheck = counter_id + "_Counter_Selfie_img_" + username + "_" + visit_date.replace("/", "") + "_" + getCurrentTime().replace(":", "") + ".jpg";
            _path = CommonString.getImagesFolder(this) + _pathforcheck;
            if (CommonFunctions.isTablet(this)) {
                CommonFunctions.startAnncaCameraActivity(this, _path, null, false, CommonString.CAMERA_FACE_REAR);
            } else {
                CommonFunctions.startAnncaCameraActivity(this, _path, null, false, CommonString.CAMERA_FACE_FRONT);
            }

        } else if (id == R.id.btn_save_selfie) {
            if (img_str != null) {
                if (checkNetIsAvailable(this)) {
                    AlertDialog.Builder builder = new AlertDialog.Builder(this).setTitle(R.string.parinaam);
                    builder.setMessage("Do you want to save the image ?").setCancelable(false).setPositiveButton(android.R.string.ok, (dialog, id1) -> {
                        getMid();
                        AttempConterCoverage(this);
                    }).setNegativeButton("Cancel", (dialog, id12) -> dialog.cancel());
                    builder.show();
                } else {
                    AlertandMessages.showToastMsg(this, CommonString.MESSAGE_INTERNET_NOT_AVALABLE);
                }
            } else {
                AlertandMessages.showToastMsg(this, "Please click Counter Selfie Image");
            }

        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Log.i("MakeMachine", "resultCode: " + resultCode);
        switch (resultCode) {
            case 0:
                Log.i("MakeMachine", "User cancelled");
                break;
            case -1:
                if (_pathforcheck != null && !_pathforcheck.isEmpty()) {
                    if (new File(str + _pathforcheck).exists()) {
                        try {
                            Bitmap bmp = convertBitmap(str + _pathforcheck);
                            img_cam.setImageBitmap(bmp);
                        } catch (OutOfMemoryError ex) {
                            CommonFunctions.setScaledImage(img_cam, str + _pathforcheck);
                        }
                        img_clicked.setVisibility(View.GONE);
                        img_cam.setVisibility(View.VISIBLE);
                        img_str = _pathforcheck;
                        _pathforcheck = "";
                    }
                }

                break;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    public static Bitmap convertBitmap(String path) {
        Bitmap bitmap = null;
        BitmapFactory.Options ourOptions = new BitmapFactory.Options();
        ourOptions.inPreferredConfig = Bitmap.Config.RGB_565;
        ourOptions.inDither = false;
        ourOptions.inPurgeable = true;
        ourOptions.inInputShareable = true;
        ourOptions.inTempStorage = new byte[32 * 1024];
        File file = new File(path);
        FileInputStream fs = null;
        try {
            fs = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            e.fillInStackTrace();
        }
        try {
            if (fs != null) {
                bitmap = BitmapFactory.decodeFileDescriptor(fs.getFD(), null, ourOptions);
            }
        } catch (IOException e) {
            e.fillInStackTrace();
        } finally {
            if (fs != null) {
                try {
                    fs.close();
                } catch (IOException e) {
                    e.fillInStackTrace();
                }
            }
        }

        return bitmap;
    }

    @Override
    public void onBackPressed() {
        if (clickFlag) {
            AlertDialog.Builder builder = new AlertDialog.Builder(this).setMessage(CommonString.ONBACK_ALERT_MESSAGE).setCancelable(false).setPositiveButton("Ok", (dialog, id) -> {
                overridePendingTransition(R.anim.activity_back_in, R.anim.activity_back_out);
                StoreImageActivity.this.finish();
            }).setNegativeButton("Cancel", (dialog, id) -> dialog.cancel());
            AlertDialog alert = builder.create();
            alert.show();
        } else {
            overridePendingTransition(R.anim.activity_back_in, R.anim.activity_back_out);
            StoreImageActivity.this.finish();
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == android.R.id.home) {
            if (clickFlag) {
                AlertDialog.Builder builder = new AlertDialog.Builder(this).setMessage(CommonString.ONBACK_ALERT_MESSAGE).setCancelable(false).setPositiveButton("Ok", (dialog, id1) -> {
                    overridePendingTransition(R.anim.activity_back_in, R.anim.activity_back_out);
                    StoreImageActivity.this.finish();
                }).setNegativeButton("Cancel", (dialog, id12) -> dialog.cancel());
                AlertDialog alert = builder.create();
                alert.show();
            } else {
                overridePendingTransition(R.anim.activity_back_in, R.anim.activity_back_out);
                StoreImageActivity.this.finish();
            }
        }

        return super.onOptionsItemSelected(item);
    }


    private void AttempBaCoverage(final ProgressDialog loading, Context context) {
        try {
            getMid();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("Mid", mid);
            jsonObject.put("Bid", bid);
            jsonObject.put("Latitude", lat);
            jsonObject.put("Longitude", lon);
            jsonObject.put("ImageName", img_str);
            jsonObject.put("UserName", username);
            String jsonString = jsonObject.toString();
            try {
                final OkHttpClient okHttpClient = new OkHttpClient.Builder().readTimeout(CommonString.TIMEOUT, TimeUnit.SECONDS).writeTimeout(CommonString.TIMEOUT, TimeUnit.SECONDS).connectTimeout(CommonString.TIMEOUT, TimeUnit.SECONDS).build();
                RequestBody jsonData = RequestBody.create(MediaType.parse("application/json"), jsonString);
                adapter = new Retrofit.Builder().baseUrl(CommonString.URL).client(okHttpClient).addConverterFactory(GsonConverterFactory.create()).build();
                PostApi api = adapter.create(PostApi.class);
                Call<ResponseBody> call = api.getBaCoverage(jsonData);
                call.enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
                        ResponseBody responseBody = response.body();
                        String data = null;
                        if (responseBody != null && response.isSuccessful()) {
                            try {
                                assert response.body() != null;
                                data = response.body().string();
                                data = data.substring(1, data.length() - 1).replace("\\", "");
                                if (!data.equals(0)) {
                                    db.open();
                                    db.updateImageLoginData(username, img_str);
                                    db.open();
                                    if (db.isCheck_Old_Product(visit_date)) {
                                        startActivity(new Intent(context, TimerActivity.class));
                                    } else {
                                        startActivity(new Intent(context, DealarBoardActivity.class));
                                    }
                                    overridePendingTransition(R.anim.activity_in, R.anim.activity_out);
                                    StoreImageActivity.this.finish();
                                } else {
                                    AlertandMessages.showAlertlogin((Activity) context, CommonString.KEY_FAILURE + ". Please try again");
                                }
                                if (loading != null && loading.isShowing()) loading.dismiss();
                            } catch (Exception e) {
                                e.fillInStackTrace();
                                if (loading != null && loading.isShowing()) loading.dismiss();
                                AlertandMessages.showAlertlogin((Activity) context, CommonString.MESSAGE_SOCKETEXCEPTION + "(" + e + ")");
                            }
                        } else {
                            if (loading != null && loading.isShowing()) loading.dismiss();
                            AlertandMessages.showToastMsg(context, CommonString.MESSAGE_NO_RESPONSE_SERVER);
                        }
                    }

                    @Override
                    public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
                        if (loading != null && loading.isShowing()) loading.dismiss();
                        AlertandMessages.showAlertlogin((Activity) context, CommonString.MESSAGE_SOCKETEXCEPTION);
                    }
                });
            } catch (Exception e) {
                if (loading != null && loading.isShowing()) loading.dismiss();
                AlertandMessages.showAlertlogin((Activity) context, CommonString.MESSAGE_SOCKETEXCEPTION + "(" + e + ")");
            }
        } catch (JSONException e) {
            if (loading != null && loading.isShowing()) loading.dismiss();
            AlertandMessages.showAlertlogin((Activity) context, CommonString.MESSAGE_INVALID_JSON);
        }
    }


    private void AttempTBajourneyCoverage(final Context context) {
        try {
            loading = ProgressDialog.show(context, "Processing", "Please wait...", false, false);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("CounterId", counter_id);
            jsonObject.put("VisitDate", visit_date);
            jsonObject.put("UserName", username);
            String jsonString = jsonObject.toString();
            try {
                final OkHttpClient okHttpClient = new OkHttpClient.Builder().readTimeout(CommonString.TIMEOUT, TimeUnit.SECONDS).writeTimeout(CommonString.TIMEOUT, TimeUnit.SECONDS).connectTimeout(CommonString.TIMEOUT, TimeUnit.SECONDS).build();
                RequestBody jsonData = RequestBody.create(MediaType.parse("application/json"), jsonString);
                adapter = new Retrofit.Builder().baseUrl(CommonString.URL).client(okHttpClient).addConverterFactory(GsonConverterFactory.create()).build();
                PostApi api = adapter.create(PostApi.class);
                Call<ResponseBody> call = api.getTabjourneyCoverage(jsonData);
                call.enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
                        ResponseBody responseBody = response.body();
                        String data = null;
                        if (responseBody != null && response.isSuccessful()) {
                            try {
                                assert response.body() != null;
                                data = response.body().string();
                                data = data.substring(1, data.length() - 1).replace("\\", "");
                                if (data.equalsIgnoreCase(CommonString.KEY_FAILURE)) {
                                    AlertandMessages.showAlert((Activity) context, CommonString.KEY_FAILURE + " Please try again", true);
                                } else {
                                    DownloadJCP(context, loading);
                                }
                                if (loading != null && loading.isShowing()) loading.dismiss();
                            } catch (Exception e) {
                                e.fillInStackTrace();
                                if (loading != null && loading.isShowing()) loading.dismiss();
                                AlertandMessages.showAlert((Activity) context, CommonString.MESSAGE_SOCKETEXCEPTION + "(" + e + ")", true);
                            }
                        } else {
                            if (loading != null && loading.isShowing()) loading.dismiss();
                            AlertandMessages.showAlert((Activity) context, CommonString.MESSAGE_NO_RESPONSE_SERVER, true);
                        }
                    }

                    @Override
                    public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
                        if (loading != null && loading.isShowing()) loading.dismiss();
                        AlertandMessages.showAlert((Activity) context, CommonString.MESSAGE_SOCKETEXCEPTION, true);
                    }
                });
            } catch (Exception e) {
                e.fillInStackTrace();
                if (loading != null && loading.isShowing()) loading.dismiss();
                AlertandMessages.showAlert((Activity) context, CommonString.MESSAGE_SOCKETEXCEPTION + "(" + e + ")", true);
            }
        } catch (JSONException e) {
            if (loading != null && loading.isShowing()) loading.dismiss();
            AlertandMessages.showAlert((Activity) context, CommonString.MESSAGE_SOCKETEXCEPTION + "(" + e + ")", true);
        }
    }

    private void AttempConterCoverage(final Context context) {
        try {
            getMid();
            loading = ProgressDialog.show(context, "Processing", "Please wait...", false, false);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("Mid", mid);
            jsonObject.put("CounterId", counter_id);
            jsonObject.put("VisitDate", visit_date);
            jsonObject.put("Latitude", lat);
            jsonObject.put("Longitude", lon);
            jsonObject.put("ImageName", "");
            jsonObject.put("Appversion", versionCode);
            jsonObject.put("UserName", username);

            String jsonString = jsonObject.toString();
            try {
                final OkHttpClient okHttpClient = new OkHttpClient.Builder().readTimeout(CommonString.TIMEOUT, TimeUnit.SECONDS).writeTimeout(CommonString.TIMEOUT, TimeUnit.SECONDS).connectTimeout(CommonString.TIMEOUT, TimeUnit.SECONDS).build();
                RequestBody jsonData = RequestBody.create(MediaType.parse("application/json"), jsonString);
                adapter = new Retrofit.Builder().baseUrl(CommonString.URL).client(okHttpClient).addConverterFactory(GsonConverterFactory.create()).build();
                PostApi api = adapter.create(PostApi.class);
                Call<ResponseBody> call = api.getCounterCoverage(jsonData);
                call.enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
                        ResponseBody responseBody = response.body();
                        String data = null;
                        if (responseBody != null && response.isSuccessful()) {
                            try {
                                assert response.body() != null;
                                data = response.body().string();
                                data = data.substring(1, data.length() - 1).replace("\\", "");
                                if (data.equalsIgnoreCase(CommonString.KEY_FAILURE)) {
                                    AlertandMessages.showAlertlogin((Activity) context, CommonString.KEY_FAILURE + ". Please try again");
                                    loading.dismiss();
                                } else {
                                    AttempBaCoverage(loading, context);
                                }
                                if (loading != null && loading.isShowing()) loading.dismiss();
                            } catch (Exception e) {
                                if (loading != null && loading.isShowing()) loading.dismiss();
                                AlertandMessages.showAlertlogin((Activity) context, CommonString.MESSAGE_SOCKETEXCEPTION + "(" + e + ")");
                            }
                        } else {
                            if (loading != null && loading.isShowing()) loading.dismiss();
                            AlertandMessages.showToastMsg(context, CommonString.MESSAGE_NO_RESPONSE_SERVER);
                        }
                    }

                    @Override
                    public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
                        if (loading != null && loading.isShowing()) loading.dismiss();
                        AlertandMessages.showAlertlogin((Activity) context, CommonString.MESSAGE_SOCKETEXCEPTION);
                    }
                });
            } catch (Exception e) {
                if (loading != null && loading.isShowing()) loading.dismiss();
                AlertandMessages.showAlertlogin((Activity) context, CommonString.MESSAGE_SOCKETEXCEPTION + "(" + e.toString() + ")");
            }
        } catch (JSONException e) {
            if (loading != null && loading.isShowing()) loading.dismiss();
            AlertandMessages.showAlertlogin((Activity) context, CommonString.MESSAGE_INVALID_JSON);
        }
    }

    private void downloadRequiredData() {
        if (userType == null) {
            return;
        }
        Log.d("userType", userType + "--" + username + "---" + counter_id);
        if (db.getStoreData(visit_date, username, counter_id).isEmpty()) {
            if (CommonFunctions.checkNetIsAvailable(this)) {
                if (userType.equalsIgnoreCase(CommonString.TAG_FROM_BA)) {
                    loading = ProgressDialog.show(this, "Processing", "Please wait...", false, false);
                    DownloadJCP(this, loading);
                } else {
                    AttempTBajourneyCoverage(this);
                }
            } else {
                AlertandMessages.showAlert(this, getString(R.string.nonetwork), true);
            }
        } else {
            /// checking GeoFencing
            getLastLocation();
            checkingGeoFencing(getMid());
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (!db.getinsertGeotaggingData(storeId.toString(), counter_id, username, null).isEmpty()) {
            success_geoTag = true;
        }
        if (!success_geoTag) {
            getLastLocation();
            checkingGeoFencing(getMid());
        }
        checkgpsEnableDevice();
        getMid();
    }

    private void checkgpsEnableDevice() {
        if (!hasGPSDevice(this)) {
            Toast.makeText(this, "Gps not Supported", Toast.LENGTH_SHORT).show();
        }
        final LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && hasGPSDevice(this)) {
            enableLocationSettings();
        } else {
            if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                hasGPSDevice(this);
            }
        }
    }

    private void enableLocationSettings() {
        LocationRequest locationRequest = new LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, // priority
                5000                             // intervalMillis: 5 seconds
        ).setMinUpdateIntervalMillis(3000)       // fastest interval
                .build();
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest).setAlwaysShow(true); // show dialog if GPS is off

        SettingsClient settingsClient = LocationServices.getSettingsClient(this);
        settingsClient.checkLocationSettings(builder.build()).addOnSuccessListener(locationSettingsResponse -> {
            // All location settings are satisfied. You can request location updates here.
        }).addOnFailureListener(e -> {
            if (e instanceof ResolvableApiException) {
                try {
                    ResolvableApiException resolvable = (ResolvableApiException) e;
                    resolvable.startResolutionForResult((Activity) this, REQUEST_LOCATION);
                } catch (IntentSender.SendIntentException sendEx) {
                    // Ignore the error.
                    sendEx.fillInStackTrace();
                }
            }
        });
    }

    private boolean hasGPSDevice(Context context) {
        final LocationManager mgr = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        if (mgr == null) return false;
        final List<String> providers = mgr.getAllProviders();
        if (providers == null) return false;
        return providers.contains(LocationManager.GPS_PROVIDER);
    }

    private void DownloadJCP(final Context context, final ProgressDialog loading) {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("Downloadtype", "Mapping_JourneyPlan");
            jsonObject.put("Username", username);
            jsonObject.put("Param1", counter_id);
            jsonObject.put("Param2", "");
            String jsonString = jsonObject.toString();

            try {
                final OkHttpClient okHttpClient = new OkHttpClient.Builder().readTimeout(CommonString.TIMEOUT, TimeUnit.SECONDS).writeTimeout(CommonString.TIMEOUT, TimeUnit.SECONDS).connectTimeout(CommonString.TIMEOUT, TimeUnit.SECONDS).build();
                RequestBody jsonData = RequestBody.create(MediaType.parse("application/json"), jsonString);
                adapter = new Retrofit.Builder().baseUrl(CommonString.URL).client(okHttpClient).addConverterFactory(GsonConverterFactory.create()).build();
                PostApi api = adapter.create(PostApi.class);
                Call<ResponseBody> call = api.getTabjournePlan(jsonData);
                call.enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
                        ResponseBody responseBody = response.body();
                        String data = null;
                        if (responseBody != null && response.isSuccessful()) {
                            try {
                                assert response.body() != null;
                                data = response.body().string();
                                data = data.substring(1, data.length() - 1).replace("\\", "");
                                if (data.equalsIgnoreCase(CommonString.KEY_FAILURE)) {
                                    AlertandMessages.showAlert((Activity) context, CommonString.KEY_FAILURE + " Please try again", true);
                                } else if (!data.contains("No Data")) {
                                    JCPGetterSetter jcpObject;
                                    jcpObject = new Gson().fromJson(data, JCPGetterSetter.class);
                                    if (jcpObject != null && !db.insertJCPData(jcpObject)) {
                                        AlertandMessages.showAlert((Activity) context, "Mapping_JCP data not saved.", true);
                                    } else {
                                        /// checking GeoFencing
                                        getLastLocation();
                                        checkingGeoFencing(getMid());
                                        AlertandMessages.showToastMsg(context, "Journey Plan Download Successfully.");
                                    }
                                } else {
                                    AlertandMessages.showAlert((Activity) context, "No Journey Plan", true);
                                }
                                if (loading != null && loading.isShowing()) loading.dismiss();
                            } catch (Exception e) {
                                e.fillInStackTrace();
                                if (loading != null && loading.isShowing()) loading.dismiss();
                                AlertandMessages.showAlert((Activity) context, CommonString.MESSAGE_SOCKETEXCEPTION + "(" + e + ")", true);
                            }
                        } else {
                            if (loading != null && loading.isShowing()) loading.dismiss();
                            AlertandMessages.showAlert((Activity) context, CommonString.MESSAGE_NO_RESPONSE_SERVER, true);
                        }
                    }

                    @Override
                    public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
                        if (loading != null && loading.isShowing()) loading.dismiss();
                        AlertandMessages.showAlert((Activity) context, CommonString.MESSAGE_SOCKETEXCEPTION, true);
                    }
                });
            } catch (Exception e) {
                e.fillInStackTrace();
                if (loading != null && loading.isShowing()) loading.dismiss();
                AlertandMessages.showAlert((Activity) context, CommonString.MESSAGE_SOCKETEXCEPTION + "(" + e + ")", true);
            }
        } catch (JSONException e) {
            if (loading != null && loading.isShowing()) loading.dismiss();
            AlertandMessages.showAlertlogin((Activity) context, CommonString.MESSAGE_INVALID_JSON);
        }
    }

    private JourneyPlan getMid() {
        db.open();
        JourneyPlan journeyPlan = new JourneyPlan();
        ArrayList<JourneyPlan> jcp = db.getStoreData(visit_date, username, counter_id);
        try {
            if (!jcp.isEmpty()) {
                mid = jcp.get(0).getMID();
                bid = jcp.get(0).getBID();
                storeId = jcp.get(0).getStoreId();
                journeyPlan = jcp.get(0);
                Log.d("jcp_data", journeyPlan.toString());
            }
        } catch (Exception e) {
            e.fillInStackTrace();
        }

        return journeyPlan;
    }

    public void showExportDialog() {
        AlertDialog.Builder builder1 = new AlertDialog.Builder(this).setTitle(R.string.dialog_title);
        builder1.setMessage(R.string.Areyou_sure_take_backup).setCancelable(false).setPositiveButton(R.string.ok, (dialog, id) -> {
            try {
                File sd = AppUtils.getExterDir(this);
                File data = Environment.getDataDirectory();
                assert sd != null;
                if (sd.canWrite()) {
                    long date = System.currentTimeMillis();
                    @SuppressLint("SimpleDateFormat") SimpleDateFormat sdf = new SimpleDateFormat("MMM/dd/yy");
                    String dateString = sdf.format(date);
                    String currentDBPath = "//data//" + BuildConfig.APPLICATION_ID + "//databases//" + Lorealba_Database.DATABASE_NAME;
                    String backupDBPath = username + CommonString.BACKUP_FOLDER_NAME + dateString.replace('/', '_') + CommonFunctions.getCurrentTime_only().replace(":", "") + ".db";
                    String path = CommonString.getBackupFolder(this);
                    File currentDB = new File(data, currentDBPath);
                    File backupDB = new File(path, backupDBPath);
                    if (currentDB.exists()) {
                        @SuppressWarnings("resource") FileChannel src = new FileInputStream(currentDB).getChannel();
                        FileChannel dst = new FileOutputStream(backupDB).getChannel();
                        dst.transferFrom(src, 0, src.size());
                        src.close();
                        dst.close();
                    }
                }
            } catch (Exception e) {
                e.fillInStackTrace();
                AlertandMessages.showAlert((Activity) this, this.getString(R.string.errordatabase_not_exporting), true);
            }
        }).setNegativeButton(android.R.string.cancel, (dialog, id) -> dialog.cancel());
        AlertDialog alert1 = builder1.create();
        alert1.show();
    }

    @Override
    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
        showExportDialog();
        return super.onKeyLongPress(keyCode, event);
    }

    private void checkAndRequestPermissions() {
        int CAMERA = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
        int ACCESS_NETWORK_STATE = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE);
        int ACCESS_COARSE_LOCATION = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
        int locationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
        int READ_PHONE_STATE = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE);
        List<String> listPermissionsNeeded = new ArrayList<>();

        if (CAMERA != PackageManager.PERMISSION_GRANTED) {
            listPermissionsNeeded.add(Manifest.permission.CAMERA);
        }

        if (ACCESS_NETWORK_STATE != PackageManager.PERMISSION_GRANTED) {
            listPermissionsNeeded.add(Manifest.permission.ACCESS_NETWORK_STATE);
        }
        if (ACCESS_COARSE_LOCATION != PackageManager.PERMISSION_GRANTED) {
            listPermissionsNeeded.add(Manifest.permission.ACCESS_COARSE_LOCATION);
        }
        if (locationPermission != PackageManager.PERMISSION_GRANTED) {
            listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
        }

        if (READ_PHONE_STATE != PackageManager.PERMISSION_GRANTED) {
            listPermissionsNeeded.add(Manifest.permission.READ_PHONE_STATE);
        }


        if (!listPermissionsNeeded.isEmpty()) {
            ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), PERMISSION_ALL);
        }
    }

    private void showDialogOK(DialogInterface.OnClickListener okListener) {
        new AlertDialog.Builder(this).setMessage("Location,File,Call and Camera Services Permission required for this app").setPositiveButton("OK", okListener).setNegativeButton("Cancel", okListener).create().show();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        //test("", "Permission callback called-------");
        if (requestCode == PERMISSION_ALL) {
            Map<String, Integer> perms = new HashMap<>();
            // Initialize the map with both permissions
            perms.put(Manifest.permission.CAMERA, PackageManager.PERMISSION_GRANTED);
            perms.put(Manifest.permission.ACCESS_NETWORK_STATE, PackageManager.PERMISSION_GRANTED);
            perms.put(Manifest.permission.ACCESS_COARSE_LOCATION, PackageManager.PERMISSION_GRANTED);
            perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
            perms.put(Manifest.permission.READ_PHONE_STATE, PackageManager.PERMISSION_GRANTED);
            // Fill with actual results from user
            if (grantResults.length > 0) {
                for (int i = 0; i < permissions.length; i++)
                    perms.put(permissions[i], grantResults[i]);
                // Check for both permissions
                boolean allPermissionsGranted = Integer.valueOf(PackageManager.PERMISSION_GRANTED).equals(perms.get(Manifest.permission.CAMERA)) && Integer.valueOf(PackageManager.PERMISSION_GRANTED).equals(perms.get(Manifest.permission.ACCESS_NETWORK_STATE)) && Integer.valueOf(PackageManager.PERMISSION_GRANTED).equals(perms.get(Manifest.permission.ACCESS_COARSE_LOCATION)) && Integer.valueOf(PackageManager.PERMISSION_GRANTED).equals(perms.get(Manifest.permission.ACCESS_FINE_LOCATION)) && Integer.valueOf(PackageManager.PERMISSION_GRANTED).equals(perms.get(Manifest.permission.READ_PHONE_STATE));

                if (allPermissionsGranted) {
                    getLastLocation();
                } else {
                    //test("", "Some permissions are not granted ask again ");
                    if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_NETWORK_STATE) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_PHONE_STATE)) {
                        showDialogOK((dialog, which) -> {
                            switch (which) {
                                case DialogInterface.BUTTON_POSITIVE:
                                    checkAndRequestPermissions();
                                    break;
                                case DialogInterface.BUTTON_NEGATIVE:
                                    // proceed with logic by disabling the related features or quit the app.
                                    Intent startMain = new Intent(Intent.ACTION_MAIN);
                                    startMain.addCategory(Intent.CATEGORY_HOME);
                                    startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                    startActivity(startMain);
                                    break;
                            }
                        });
                    } else {
                        Toast.makeText(this, "Go to settings and enable permissions", Toast.LENGTH_LONG).show();
                    }
                }
            }
        }
    }

    private void getLastLocation() {
        if (fusedLocationClient == null) {
            fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
        }
        // fastest interval
        LocationRequest locationRequest = new LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 5000).setMinUpdateIntervalMillis(3000) // fastest interval
                .build();
        locationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(@NonNull LocationResult locationResult) {
                for (Location location : locationResult.getLocations()) {
                    if (location != null) {
                        lat = location.getLatitude();
                        lon = location.getLongitude();
                        Log.d("Location", "Lat: " + lat + ", Lng: " + lon);
                    }
                }
            }
        };
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // Request permissions if not granted
            return;
        }
        fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper());
    }

    private void stopLocationUpdates() {
        if (fusedLocationClient != null && locationCallback != null) {
            fusedLocationClient.removeLocationUpdates(locationCallback);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        stopLocationUpdates();
        if (loading != null && loading.isShowing()) {
            loading.dismiss();
        }
    }

    private void checkingGeoFencing(JourneyPlan jcp) {
        if (jcp != null && jcp.getBID() != null) {
            if (jcp.getGeoTag() != null && !jcp.getGeoTag().equalsIgnoreCase(CommonString.KEY_N) && jcp.getGeoFencingAllow() != null && jcp.getGeoFencingAllow() == 1) {
                int distance = jcp.getGeoFencingRadius() != null ? jcp.getGeoFencingRadius() : 0;
                int current_dist_from_store_using_lat = 0;
                if (jcp.getLatitude() != 0.0 && jcp.getLongitude() != 0.0 && jcp.getGeoFencingRadius() != 0 && lat != 0.0 && lon != 0.0) {
                    current_dist_from_store_using_lat = DistanceUtils.calculateDistanceInMeters(lat, lon, jcp.getLatitude(), jcp.getLongitude());
                    Log.d("TagLoc", "Radius " + distance + "\nCurrent dist " + current_dist_from_store_using_lat);
                    if (current_dist_from_store_using_lat > distance) {
                        String msg = getString(R.string.you_need_to_be_within) + " " + distance + " metres " + getString(R.string.you_need_to_be_in_the_store) +
                                "\n\n" + getString(R.string.distance_from_the_store) + " " + current_dist_from_store_using_lat + " " + getString(R.string.meters);
                        AlertDialog.Builder builder = new AlertDialog.Builder(this);
                        builder.setTitle(getResources().getString(R.string.alert));
                        builder.setMessage(msg).setCancelable(false).setPositiveButton(getResources().getString(R.string.ok), (dialog1, id) -> {
                            dialog1.cancel();
                            finishAffinity();
                        });
                        AlertDialog alert = builder.create();
                        alert.show();
                    }
                }
            } else {
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle(getResources().getString(R.string.dialog_title));
                builder.setMessage(getString(R.string.first_geotag_the_store)).setCancelable(false).setPositiveButton(getResources().getString(R.string.ok), (dialog1, id) -> {
                    dialog1.cancel();
                    success_geoTag = false;
                    Intent in = new Intent(this, GeoTaggingActivity.class);
                    startActivity(in);
                });
                AlertDialog alert = builder.create();
                alert.show();
            }
        }
    }
}

