package com.app.simplitend.apputils;

import static android.content.Context.NOTIFICATION_SERVICE;
import static com.app.simplitend.apputils.AppUtil.NOTIFICATION_ACTION;
import static com.app.simplitend.apputils.Constants.ACTIVITY_TIME;
import static com.app.simplitend.apputils.Constants.BATTERY_LOW;
import static com.app.simplitend.apputils.Constants.MEDICATION_REFILL;
import static com.app.simplitend.apputils.Constants.MEDICINE_TIME;
import static com.app.simplitend.apputils.Constants.NEW_SUBSCRIPTION;
import static com.app.simplitend.patientgeofencing.GeoFenceHelper.GEOFENCE_TAG;

import android.app.NotificationManager;
import android.content.Intent;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;

import com.app.simplitend.patient_dashboard.PatientMainViewModel;
import com.onesignal.OneSignal;
import com.onesignal.notifications.INotificationReceivedEvent;
import com.onesignal.notifications.INotificationServiceExtension;

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

import java.util.Arrays;
import java.util.List;

public class NotificationService implements INotificationServiceExtension {

    public static final String CONTENT_TYPE_KEY = "content_type_key";
    public static final String NOTIFICATION_BODY_KEY = "notification_body_key";
    public static final String NOTIFICATION_TITLE_KEY = "notification_title_key";
    public static final String NOTIFICATION_CONTENT_ID_KEY = "notification_title_key";

    public static final String NOTIFICATION_SENIOR_ADDRESS_KEY = "notification_senior_address";

    public static final String NOTIFICATION_MEAL_TYPE_KEY = "notification_meal_type_key";

    @Override
    public void onNotificationReceived(@NonNull INotificationReceivedEvent iNotificationReceivedEvent) {
//        Log.d("aditya testing", "onNotificationReceived: " + iNotificationReceivedEvent.getNotification());

        // showing maximum 7 notifications due to the limitations enforced by manufacturers
        // Thus, removing the oldest notification to show this new notification
        NotificationManager notificationManager = (NotificationManager) iNotificationReceivedEvent.getContext().getSystemService(NOTIFICATION_SERVICE);
        try {
            int active_notifications_count = notificationManager.getActiveNotifications().length;
            if (active_notifications_count >= 7) // already number is incremented when notification is arrived
            {
                List<StatusBarNotification> active_notifications = Arrays.asList(notificationManager.getActiveNotifications());

                long minPostTime = Long.MAX_VALUE;
                StatusBarNotification notification = null;
                for (StatusBarNotification not: active_notifications){
                    if (not.getPostTime() < minPostTime){
                        notification = not;
                    }
                }

                if (notification != null) {
                    OneSignal.getNotifications().removeNotification(notification.getId());
                }
            }
        } catch (Exception e) {
            // clearing all notifications
            OneSignal.getNotifications().clearAllNotifications();
        }

        JSONObject extras = iNotificationReceivedEvent.getNotification().getAdditionalData();
        String content_type = null, senior_current_address = null;
        int id = -1;
        if (extras != null) {
            try {
                content_type = extras.getString("content_type");
                id = extras.getInt("id");
            } catch (JSONException e) {
                // do nothing
            }

            try {
                senior_current_address = extras.getString("address");
            } catch (JSONException e) {
                // do nothing
            }
        }

        if (Constants.CHATS_NOTIFICATIONS.equals(content_type)){
            // keeping count of chat notifications
            AppUtil.incrementNoOfChatNotification(iNotificationReceivedEvent.getContext());

            // chat notifications doesn't need to be handled for bottom sheet
            // or broadcasts
            return;
        }else{
            // increment notifications count
            AppUtil.incrementNoOfNotification(iNotificationReceivedEvent.getContext());
        }

        if (NEW_SUBSCRIPTION.equals(content_type)){
            // sending local broadcast
            Intent broadcastIntent = new Intent(NOTIFICATION_ACTION);
            broadcastIntent.putExtra(CONTENT_TYPE_KEY, content_type);
            iNotificationReceivedEvent.getContext().sendBroadcast(broadcastIntent);

            return;
        }

        Intent intent = new Intent(iNotificationReceivedEvent.getContext(), BottomNotificationActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setAction(NOTIFICATION_ACTION);
        intent.putExtra(CONTENT_TYPE_KEY, content_type);
        intent.putExtra(NOTIFICATION_BODY_KEY, iNotificationReceivedEvent.getNotification().getBody());
        intent.putExtra(NOTIFICATION_TITLE_KEY, iNotificationReceivedEvent.getNotification().getTitle());
        intent.putExtra(NOTIFICATION_CONTENT_ID_KEY, id);
        intent.putExtra(NOTIFICATION_SENIOR_ADDRESS_KEY, senior_current_address);
        intent.putExtra(NOTIFICATION_MEAL_TYPE_KEY, senior_current_address);

        // showing bottom sheet
        try {
            if (AppUtil.getCgToken(iNotificationReceivedEvent.getContext()) != null){

                // when caregiver is logged in
                iNotificationReceivedEvent.getContext().startActivity(intent);
            }else{
                // when patient is logged in

                if ( (PatientMainViewModel.remindersList != null && MEDICINE_TIME.equals(content_type)) ||
                        (PatientMainViewModel.remindersList != null && MEDICATION_REFILL.equals(content_type)) ||
                        (PatientMainViewModel.activityList != null && ACTIVITY_TIME.equals(content_type)) ||
                        BATTERY_LOW.equals(content_type)){
                    iNotificationReceivedEvent.getContext().startActivity(intent);
                }

            }
        } catch (Exception e) {
            // do nothing
        }

        // sending local broadcast
        Intent broadcastIntent = new Intent(NOTIFICATION_ACTION);
        broadcastIntent.putExtra(CONTENT_TYPE_KEY, content_type);
        broadcastIntent.putExtra(NOTIFICATION_BODY_KEY, iNotificationReceivedEvent.getNotification().getBody());
        broadcastIntent.putExtra(NOTIFICATION_TITLE_KEY, iNotificationReceivedEvent.getNotification().getTitle());
        broadcastIntent.putExtra(NOTIFICATION_CONTENT_ID_KEY, id);
        broadcastIntent.putExtra(NOTIFICATION_SENIOR_ADDRESS_KEY, senior_current_address);

        iNotificationReceivedEvent.getContext().sendBroadcast(broadcastIntent);

        if (Constants.GEOFENCING_RADIUS_ADDED.equals(content_type)
                || Constants.GEOFENCING_RADIUS_UPDATED.equals(content_type)
                || Constants.HOME_LOCATION_UPDATED.equals(content_type)) {

            if (AppUtil.isPatientLoggedIn(iNotificationReceivedEvent.getContext())){
                // Either Geofence radius or Patient's location has changed.
                Log.d(GEOFENCE_TAG, "UPDATING GEOFENCE DETAILS");

                try {
                    double lat = extras.getDouble("lat");
                    double lng = extras.getDouble("lng");
                    double radius = extras.getDouble("radius");
                    String message;
                    try {
                        message = extras.getString("message");
                    } catch (JSONException e) {
                        message = null;
                    }

                    Log.d(GEOFENCE_TAG, "DATA RECEIVED WITH NOTIFICATION : Lat/Lng: " + lat + "," + lng + " Radius: " + radius + " message: " + message);

                    if (radius >= 0){
                        AppUtil.updateSeniorOutOfGeofence(iNotificationReceivedEvent.getContext(), false);

                        AppUtil.updatePatientGeofence(iNotificationReceivedEvent.getContext(),
                                lat+"", lng+"",
                                radius+"", "kms", message);
                    }
                }catch (Exception e){
                    Log.e(GEOFENCE_TAG, "COULDN'T UPDATE GEOFENCE DETAILS FROM THE NOTIFICATION: " + e);
                    Log.e(GEOFENCE_TAG, "EXTRAS FROM NOTIFICATION: " + extras);
                }
            }
        }
    }

}
