package com.app.simplitend.patientgeofencing;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.os.AsyncTask;
import android.util.Log;

import androidx.annotation.NonNull;

import com.app.simplitend.apputils.AppUtil;
import com.app.simplitend.apputils.RetrofitHelper;
import com.app.simplitend.chats.SocketHelper;
import com.app.simplitend.patientprofile.PatientProfileAPIService;
import com.app.simplitend.welcome.welcomepatient.mvvm.models.CallResponse;
import com.google.maps.model.LatLng;

import java.util.HashMap;
import java.util.Map;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class PatientLocationUpdatesReceiver extends BroadcastReceiver {

    public static final String LOCATION_REQUEST_TAG = "LOCATION_UPDATE_TAG";
    public static final String LOCATION_EXTRA_KEY = "com.google.android.location.LOCATION";
    public static final int LOCATION_UPDATES_REQUEST_CODE = 1010;

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(LOCATION_REQUEST_TAG, "LOCATION UPDATE RECEIVED");
        Location location = intent.getParcelableExtra(LOCATION_EXTRA_KEY);
        if (location != null) {
            LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
            Log.d(LOCATION_REQUEST_TAG, "lat/lng: " + latLng);

            int patient_id = AppUtil.getPatientUid(context);
            String token = AppUtil.getPatientToken(context);
            if (patient_id != -1 && token != null) {
                updateRemoteCurrLocation(location, patient_id,
                        "Bearer " + token);
            } else {
                Log.e(LOCATION_REQUEST_TAG, "CANNOT UPDATE REMOTE LOCATION AS PATIENT_ID OR TOKEN IS -1 OR NULL RESP.");
            }
        } else {
            Log.e(LOCATION_REQUEST_TAG, "LOCATION RECEIVED IS NULL");
        }
    }

    private void updateRemoteCurrLocation(@NonNull Location location, int patient_id,
                                          @NonNull String token) {
        PatientProfileAPIService apiService = RetrofitHelper.getRetrofit().create(PatientProfileAPIService.class);

        Map<String, String> body = new HashMap<>();
        body.put("patient_id", patient_id + "");
        body.put("lat", location.getLatitude() + "");
        body.put("lng", location.getLongitude() + "");

        apiService.updatePatientCurrLocation(body, token)
                .enqueue(new Callback<CallResponse<Object>>() {
                    @Override
                    public void onResponse(Call<CallResponse<Object>> call, Response<CallResponse<Object>> response) {
                        if (response.body() != null) {
                            if (response.code() == 200 && response.body().error_code == 0) {
                                Log.d(LOCATION_REQUEST_TAG, "LOCATION REMOTE UPDATED.");
                            } else {
                                Log.e(LOCATION_REQUEST_TAG, "LOCATION REMOTE UPDATE FAILED" + response.body().message);
                            }
                        } else {
                            Log.e(LOCATION_REQUEST_TAG, "LOCATION REMOTE UPDATE FAILED" + response.message());
                        }
                    }

                    @Override
                    public void onFailure(Call<CallResponse<Object>> call, Throwable t) {
                        Log.e(LOCATION_REQUEST_TAG, "LOCATION REMOTE UPDATE FAILED", t);
                    }
                });

        new UpdateRemoteLocationTask(patient_id + "").execute(location);
    }

    public static class UpdateRemoteLocationTask extends AsyncTask<Location, Void, Void> {
        @NonNull
        private final String patientId;

        public UpdateRemoteLocationTask(@NonNull String patientId) {
            this.patientId = patientId;
        }

        @Override
        protected Void doInBackground(Location... locations) {
            SocketHelper socketHelper = SocketHelper.getInstance();

            Log.d(LOCATION_REQUEST_TAG, "doInBackground: CONNECTING TO SOCKET");

            socketHelper.getLocationUpdates(patientId, new SocketHelper.Callback<Location>() {
                @Override
                public void onMessageReceived(Location result) {
                    Log.d(LOCATION_REQUEST_TAG, "LOCATION SENT " + result);
                    socketHelper.removeLocationUpdateListener(patientId);
                }

                @Override
                public void onMessageSentSuccessfully() {
                    socketHelper.removeLocationUpdateListener(patientId);
                }

                @Override
                public void onError(Exception e) {
                    Log.e(LOCATION_REQUEST_TAG, "LOCATION SENDING PROBLEM", e);
                    socketHelper.removeLocationUpdateListener(patientId);
                }
            });

            socketHelper.establishConnection(new SocketHelper.SockCallBack() {
                @Override
                public void onSocketConnected() {
                    Log.d(LOCATION_REQUEST_TAG, "doInBackground: SOCKET CONNECTED");
                    socketHelper.sendLocationUpdates(locations[0], patientId);
                }

                @Override
                public void onConnectionError(Exception e) {
                    Log.d(LOCATION_REQUEST_TAG, "doInBackground: SOCKET CONNECTION ERROR" + e);
                }

                @Override
                public void onDisconnected() {
                    Log.d(LOCATION_REQUEST_TAG, "doInBackground: SOCKET DISCONNECTED");
                }
            });

            return null;
        }
    }
}
