package com.app.simplitend.patientprofile.medreminder;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.ProgressDialog;
import android.app.TimePickerDialog;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;

import com.app.simplitend.R;
import com.app.simplitend.apputils.AppUtil;
import com.app.simplitend.databinding.AddReminderFragmentBinding;
import com.app.simplitend.patientprofile.ProfileContracts;
import com.app.simplitend.patientprofile.medreminder.mvvm.ReminderViewModel;
import com.app.simplitend.patientprofile.medreminder.mvvm.models.DosageType;
import com.app.simplitend.patientprofile.medreminder.mvvm.models.FreqNMedTypeResult;
import com.app.simplitend.patientprofile.medreminder.mvvm.models.Frequency;
import com.app.simplitend.patientprofile.medreminder.mvvm.models.MedicationType;
import com.app.simplitend.patientprofile.medreminder.mvvm.models.ReminderResult;
import com.skydoves.powerspinner.OnSpinnerItemSelectedListener;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

public class AddReminderFragment extends Fragment implements CompoundButton.OnCheckedChangeListener,
        ProfileContracts.FreqNMedTypesCallback,
        ProfileContracts.AddReminderCallBack {

    private static final String TAG = "AddReminderFragment";

    // view binding
    protected AddReminderFragmentBinding binding;

    /*
        week day selection states
        true -> selected
        false -> un-selected
     */
    boolean[] week_state;

    private DatePickerDialog datePickerDialog;

    // arguments keys
    public static final String REMINDER_KEY = "reminder_key";

    // model
    private ReminderResult reminder;

    private ProgressDialog progressDialog;

    private ReminderViewModel viewModel;

    private ArrayList<Frequency> frequencyList;
    private ArrayList<MedicationType> medicationTypeList;

    private ArrayList<DosageType> dosageTypeList;

    public AddReminderFragment() {
        // required empty const.
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        binding = AddReminderFragmentBinding.inflate(inflater, container, false);

        viewModel = new ViewModelProvider(requireActivity()).get(ReminderViewModel.class);

        initViews();

        clickEvents();

        return binding.getRoot();
    }

    private void clickEvents() {

        binding.backBtn.setOnClickListener(v -> {
            if (getActivity() != null){
                getActivity().onBackPressed();
            }
        });

        binding.getTime.setOnClickListener(v -> {
            binding.getTime.setError(null);
            AppUtil.closeKeyboard(requireActivity());
            getTime(binding.getTime);
        });

        binding.getTime2.setOnClickListener(v -> {
            binding.getTime.setError(null);
            AppUtil.closeKeyboard(requireActivity());
            getTime(binding.getTime2);
        });

        binding.getTime3.setOnClickListener(v -> {
            binding.getTime.setError(null);
            AppUtil.closeKeyboard(requireActivity());
            getTime(binding.getTime3);
        });

        binding.getDate.setOnClickListener(v -> {
            binding.getDate.setError(null);
            AppUtil.closeKeyboard(requireActivity());
            getDate();
        });

        binding.removeDateBtn.setOnClickListener(v -> {
            binding.getDate.setText(null);
        });

        binding.addReminder.setOnClickListener(v -> {
            AppUtil.closeKeyboard(requireActivity());

            if (allOkay()) {

                if (reminder != null){
                    AppUtil.showSOSDecision(requireContext(), getString(R.string.make_changes),
                            getString(R.string.yes), getString(R.string.no),
                            v1 -> {
                                // yes click
                                adReminder();
                            }, v2 -> {
                                // no click
                            });
                }else{
                    adReminder();
                }
            }

        });

        binding.doseShortName.setOnClickListener(v -> {
            AppUtil.closeKeyboard(requireActivity());
            binding.dosageSpinner.show();
        });

    }

    private void adReminder() {

        progressDialog.setTitle("Please wait...");
        progressDialog.setMessage("while we save your reminder.");
        progressDialog.setCancelable(false);
        progressDialog.show();

        ReminderResult reminderResult = new ReminderResult();

        reminderResult.medicine_name = binding.medicName.getText().toString().trim();
        reminderResult.dosage = binding.dosage.getText().toString();

        try {
            reminderResult.medication_frequency_xid = String.valueOf(frequencyList.get(binding.frequencySpinner.getSelectedIndex()).id);
            reminderResult.medication_type_xid = String.valueOf(medicationTypeList.get(binding.medicationsSpinner.getSelectedIndex()).id);
            reminderResult.dosage_unit = String.valueOf(dosageTypeList.get(binding.dosageSpinner.getSelectedIndex()).id);
        } catch (Exception e) {
            reminderResult.medication_frequency_xid = String.valueOf(frequencyList.get(0).id);
            reminderResult.medication_type_xid = String.valueOf(medicationTypeList.get(0).id);
            reminderResult.dosage_unit = String.valueOf(dosageTypeList.get(0).id);
        }

        ArrayList<String> time_list = new ArrayList<>();

        // saving the actual format of time i.e. HH:mm:ss as hint
        // and saving the formatted time as text i.e. hh:mm a
        time_list.add(binding.getTime.getHint().toString());

        if (binding.getTime2.getVisibility() == View.VISIBLE){
            time_list.add(binding.getTime2.getHint().toString());
        }

        if (binding.getTime3.getVisibility() == View.VISIBLE){
            time_list.add(binding.getTime3.getHint().toString());
        }

        reminderResult.medication_quantity = binding.quantity.getText().toString();
        reminderResult.medication_refill_date = binding.getDate.getText().toString();
        reminderResult.medication_instruction = binding.instructions.getText().toString().trim();

        reminderResult.sun = week_state[0] ? "1" : "0";
        reminderResult.mon = week_state[1] ? "1" : "0";
        reminderResult.tue = week_state[2] ? "1" : "0";
        reminderResult.wed = week_state[3] ? "1" : "0";
        reminderResult.thu = week_state[4] ? "1" : "0";
        reminderResult.fri = week_state[5] ? "1" : "0";
        reminderResult.sat = week_state[6] ? "1" : "0";

        reminderResult.all_days = binding.everydayCheck.isChecked()?1:0;

        if (reminder != null) {
            // this intent is to update the reminder
            reminderResult.is_update = "1";
            reminderResult.patientRemainderId = reminder.id;

            reminderResult.reminder_marked = reminder.reminder_marked;

            // to edit the reminder need to send medicine_time_list
            reminderResult.medicine_time_list = new ArrayList<>();
            reminderResult.medicine_time_list.add(binding.getTime.getHint().toString());
        } else {
            reminderResult.is_update = "0";
            reminderResult.medicine_time_list = time_list;
        }

        String token = "Bearer " + AppUtil.getPatientToken(requireContext());

        viewModel.addReminder(AppUtil.getPatientUid(requireContext()),
                reminderResult,
                token,
                this);

    }

    @SuppressLint("ClickableViewAccessibility")
    private void initViews() {

        progressDialog = new ProgressDialog(requireContext());

        Calendar calendar = Calendar.getInstance();

        datePickerDialog = new DatePickerDialog(requireContext(),
                (datePicker, year, month, dayOfMonth) -> {

                    Calendar cal = Calendar.getInstance();
                    cal.set(Calendar.YEAR, year);
                    cal.set(Calendar.MONTH, month);
                    cal.set(Calendar.DAY_OF_MONTH, dayOfMonth);

                    SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy", Locale.getDefault());

                    String selected_time = sdf.format(cal.getTime());
                    binding.getDate.setText(selected_time);

                }, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));

        datePickerDialog.getDatePicker().setMinDate(System.currentTimeMillis());
        datePickerDialog.setTitle("Select a date");
        datePickerDialog.setMessage("Note: Click on the date, month or year to edit manually");

        frequencyList = new ArrayList<>();
        medicationTypeList = new ArrayList<>();
        dosageTypeList = new ArrayList<>();

        // scrolling instruction edit text
        binding.instructions.setOnTouchListener((v, event) -> {
            if (binding.instructions.hasFocus()) {
                v.getParent().requestDisallowInterceptTouchEvent(true);
                if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_SCROLL) {
                    v.getParent().requestDisallowInterceptTouchEvent(false);
                    return true;
                }
            }
            return false;
        });

        binding.frequencySpinner.setDismissWhenNotifiedItemSelected(true);
        binding.frequencySpinner.setIsFocusable(true);
        binding.frequencySpinner.setLifecycleOwner(this);

        binding.medicationsSpinner.setDismissWhenNotifiedItemSelected(true);
        binding.medicationsSpinner.setIsFocusable(true);
        binding.medicationsSpinner.setLifecycleOwner(this);

        binding.dosageSpinner.setDismissWhenNotifiedItemSelected(true);
        binding.dosageSpinner.setIsFocusable(true);
        binding.dosageSpinner.setLifecycleOwner(this);

        binding.frequencySpinner.setOnSpinnerItemSelectedListener((OnSpinnerItemSelectedListener<String>) (i, s, i1, item) -> {
            AppUtil.closeKeyboard(requireActivity());
            binding.frequencySpinner.setError(null);

            if (item != null){
                if (item.contains("1")){
                    binding.getTime.setVisibility(View.VISIBLE);
                    binding.getTime2.setVisibility(View.GONE);
                    binding.getTime3.setVisibility(View.GONE);
                }else if (item.contains("2")){
                    binding.getTime.setVisibility(View.VISIBLE);
                    binding.getTime2.setVisibility(View.VISIBLE);
                    binding.getTime3.setVisibility(View.GONE);
                }else if (item.contains("3")){
                    binding.getTime.setVisibility(View.VISIBLE);
                    binding.getTime2.setVisibility(View.VISIBLE);
                    binding.getTime3.setVisibility(View.VISIBLE);
                }
            }

        });

        binding.medicationsSpinner.setOnSpinnerItemSelectedListener((OnSpinnerItemSelectedListener<String>) (i, s, i1, item) -> {
            AppUtil.closeKeyboard(requireActivity());
            binding.medicationsSpinner.setError(null);
        });

        binding.dosageSpinner.setOnSpinnerItemSelectedListener((OnSpinnerItemSelectedListener<String>) (i, s, i1, t1) -> {
            String short_name;
            try {
                short_name = String.valueOf(dosageTypeList.get(binding.dosageSpinner.getSelectedIndex()).value);
            } catch (Exception e) {
                short_name = "Other";
            }

            binding.doseShortName.setText(short_name);
        });

        // load into spinner
        loadFreqNMedType();

        setUpWeekSelection();

        binding.everydayCheck.setOnCheckedChangeListener(this);

    }

    private boolean allOkay() {
        boolean allOkay = true;

        if (binding.medicName.getText().toString().trim().isEmpty()) {
            allOkay = false;
            binding.medicName.setError("Required");
        }

        if (binding.dosage.getText().toString().trim().isEmpty()) {
            allOkay = false;
            binding.dosage.setError("Required");
        }else{
            try {
                double dosage = Double.parseDouble(binding.dosage.getText().toString().trim());
                if (dosage <= 0){
                    allOkay = false;
                    binding.dosage.setError("Must be greater than 0");
                }
            }catch (Exception e){
                // do nothing
            }
        }

        if (binding.frequencySpinner.getSelectedIndex() == -1) {
            allOkay = false;
            binding.frequencySpinner.setError("Select frequency");
        }

        if (binding.medicationsSpinner.getSelectedIndex() == -1) {
            allOkay = false;
            binding.medicationsSpinner.setError("Select medication type");
        }

        if (binding.getTime.getText().toString().trim().isEmpty()) {
            allOkay = false;
            binding.getTime.setError("Required");
        }

        if (binding.getTime2.getVisibility() == View.VISIBLE &&
                binding.getTime2.getText().toString().trim().isEmpty()) {
            allOkay = false;
            binding.getTime2.setError("Required");
        }

        if (binding.getTime3.getVisibility() == View.VISIBLE &&
                binding.getTime3.getText().toString().trim().isEmpty()) {
            allOkay = false;
            binding.getTime3.setError("Required");
        }

        boolean timeOk = true;

        // checking if times are equal
        if (binding.getTime2.getVisibility() == View.VISIBLE && binding.getTime3.getVisibility() == View.VISIBLE){
            // all three times are visible
            if (binding.getTime.getText().toString().equals(binding.getTime2.getText().toString())){
                // time 1 and 2 are same
                timeOk = false;
            }else if (binding.getTime.getText().toString().equals(binding.getTime3.getText().toString())){
                // time 1 and 3 are same
                timeOk = false;
            }else if (binding.getTime2.getText().toString().equals(binding.getTime3.getText().toString())){
                // time 2 and 3 are same
                timeOk = false;
            }
        }else if (binding.getTime2.getVisibility() == View.VISIBLE){
            // time 1 and 2 are visible
            if (binding.getTime.getText().toString().equals(binding.getTime2.getText().toString())){
                timeOk = false;
            }
        }

        if (!timeOk){
            allOkay = false;
            Toast.makeText(requireContext(), "Medications times cannot be same.", Toast.LENGTH_SHORT).show();
        }

        if (binding.quantity.getText().toString().trim().isEmpty()) {
            allOkay = false;
            binding.quantity.setError("Required");
        }else{
            try {
                long quantity = Long.parseLong(binding.quantity.getText().toString().trim());
                if (quantity <= 0){
                    allOkay = false;
                    binding.quantity.setError("Must be greater than 0");
                }
            }catch (Exception e){
                // do nothing
            }
        }

//        if (binding.getDate.getText().toString().trim().isEmpty()) {
//            allOkay = false;
//            binding.getDate.setError("Required");
//        }

        if (allOkay) {
            boolean anyOneSelected = false;
            for (int i = 0; i < week_state.length; i++) {
                if (week_state[i]) {
                    // this week day is selected
                    anyOneSelected = true;
                    break;
                }
            }

            if (!anyOneSelected) {
                // none are selected
                allOkay = false;
                Toast.makeText(requireContext(), "Select a week day.", Toast.LENGTH_SHORT).show();
            }
        }

        return allOkay;
    }

    private void setLayoutDetails(ReminderResult reminder) {
        if (reminder != null) {
            // removing medication frequency spinner
            binding.frequencyView.setVisibility(View.GONE);
            binding.frequencyTitleView.setVisibility(View.GONE);

            // intent is to edit the reminder
            binding.title.setText(getString(R.string.edit_reminder));

            binding.medicName.setText(reminder.medicine_name);
            binding.quantity.setText(reminder.medication_quantity);
            binding.dosage.setText(reminder.dosage);
            binding.getDate.setText(formatDate(reminder.medication_refill_date));
            binding.instructions.setText(reminder.medication_instruction);

            String medicine_time = AppUtil.formatDate("HH:mm:ss", "hh:mm a", reminder.medicine_time);
            if (medicine_time != null){
                binding.getTime.setText(medicine_time);
                binding.getTime.setHint(reminder.medicine_time);
            }

            for (int i = 0; i < frequencyList.size(); i++) {
                if (String.valueOf(frequencyList.get(i).id).equals(reminder.medication_frequency_xid)) {
                    binding.frequencySpinner.selectItemByIndex(i);
                    break;
                }
            }

            for (int i = 0; i < medicationTypeList.size(); i++) {
                if (String.valueOf(medicationTypeList.get(i).id).equals(reminder.medication_type_xid)) {
                    binding.medicationsSpinner.selectItemByIndex(i);
                    break;
                }
            }

            for (int i = 0; i < dosageTypeList.size(); i++) {
                if (String.valueOf(dosageTypeList.get(i).id).equals(reminder.dosage_unit)) {
                    binding.dosageSpinner.selectItemByIndex(i);
                    break;
                }
            }

            // week day selection
            setSelectionState(0, week_state[0] = reminder.sun.equals("1"));
            setSelectionState(1, week_state[1] = reminder.mon.equals("1"));
            setSelectionState(2, week_state[2] = reminder.tue.equals("1"));
            setSelectionState(3, week_state[3] = reminder.wed.equals("1"));
            setSelectionState(4, week_state[4] = reminder.thu.equals("1"));
            setSelectionState(5, week_state[5] = reminder.fri.equals("1"));
            setSelectionState(6, week_state[6] = reminder.sat.equals("1"));

            binding.addReminder.setText(getString(R.string.save_reminder));
        }
    }

    private String formatDate(String medication_refill_date) {
        String inputPattern = "yyyy-MM-dd";
        String outputPattern = "MM-dd-yyyy";
        SimpleDateFormat inputFormat = new SimpleDateFormat(inputPattern, Locale.getDefault());
        SimpleDateFormat outputFormat = new SimpleDateFormat(outputPattern, Locale.getDefault());

        Date date = null;
        String str = null;

        try {
            date = inputFormat.parse(medication_refill_date);
            if (date == null) throw new Exception();
            str = outputFormat.format(date);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            if (datePickerDialog != null)
            {
                datePickerDialog.getDatePicker().updateDate(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
            }
        } catch (Exception e) {
            Log.e(TAG, "formatDate: ", e);
        }

        return str;
    }

    // every-dau toggle listener
    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        for (int i = 0; i < 7; i++) {
            setSelectionState(i, week_state[i] = isChecked);
        }
    }

    // set selection and un-selection of week day
    private void setUpWeekSelection() {

        week_state = new boolean[7];

        // week day selections
        binding.sun.setOnClickListener(v -> setSelectionState(0, week_state[0] = !week_state[0]));
        binding.mon.setOnClickListener(v -> setSelectionState(1, week_state[1] = !week_state[1]));
        binding.tue.setOnClickListener(v -> setSelectionState(2, week_state[2] = !week_state[2]));
        binding.wed.setOnClickListener(v -> setSelectionState(3, week_state[3] = !week_state[3]));
        binding.thu.setOnClickListener(v -> setSelectionState(4, week_state[4] = !week_state[4]));
        binding.fri.setOnClickListener(v -> setSelectionState(5, week_state[5] = !week_state[5]));
        binding.sat.setOnClickListener(v -> setSelectionState(6, week_state[6] = !week_state[6]));

    }

    private void setSelectionState(int position, boolean selection) {
        if (selection) {
            // selection has to be made
            switch (position) {
                case 0:
                    // sun
                    binding.sun.setBackgroundTintList(AppCompatResources.getColorStateList(requireContext(), R.color.color_primary));
                    binding.sun.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.white_bg));
                    break;
                case 1:
                    // mon
                    binding.mon.setBackgroundTintList(AppCompatResources.getColorStateList(requireContext(), R.color.color_primary));
                    binding.mon.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.white_bg));
                    break;
                case 2:
                    // tue
                    binding.tue.setBackgroundTintList(AppCompatResources.getColorStateList(requireContext(), R.color.color_primary));
                    binding.tue.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.white_bg));
                    break;
                case 3:
                    // wed
                    binding.wed.setBackgroundTintList(AppCompatResources.getColorStateList(requireContext(), R.color.color_primary));
                    binding.wed.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.white_bg));
                    break;
                case 4:
                    // thu
                    binding.thu.setBackgroundTintList(AppCompatResources.getColorStateList(requireContext(), R.color.color_primary));
                    binding.thu.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.white_bg));
                    break;
                case 5:
                    // fri
                    binding.fri.setBackgroundTintList(AppCompatResources.getColorStateList(requireContext(), R.color.color_primary));
                    binding.fri.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.white_bg));
                    break;
                case 6:
                    // sat
                    binding.sat.setBackgroundTintList(AppCompatResources.getColorStateList(requireContext(), R.color.color_primary));
                    binding.sat.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.white_bg));
                    break;
            }
        } else {
            // un-selection has to be made
            switch (position) {
                case 0:
                    // sun
                    binding.sun.setBackgroundTintList(null);
                    binding.sun.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.black));
                    break;
                case 1:
                    // mon
                    binding.mon.setBackgroundTintList(null);
                    binding.mon.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.black));
                    break;
                case 2:
                    // tue
                    binding.tue.setBackgroundTintList(null);
                    binding.tue.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.black));
                    break;
                case 3:
                    // wed
                    binding.wed.setBackgroundTintList(null);
                    binding.wed.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.black));
                    break;
                case 4:
                    // thu
                    binding.thu.setBackgroundTintList(null);
                    binding.thu.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.black));
                    break;
                case 5:
                    // fri
                    binding.fri.setBackgroundTintList(null);
                    binding.fri.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.black));
                    break;
                case 6:
                    // sat
                    binding.sat.setBackgroundTintList(null);
                    binding.sat.setTextColor(AppCompatResources.getColorStateList(requireContext(), R.color.black));
                    break;
            }
        }

        // checking if all days are selected or not
        // thus, updating the Everyday switch accordingly
        boolean isEveryDay = true;

        for (int i = 0; i < 7; i++) {
            if (!week_state[i]) {
                // some day is not selected thus not everyday selection
                isEveryDay = false;
                break;
            }
        }

        binding.everydayCheck.setOnCheckedChangeListener(null);
        binding.everydayCheck.setChecked(isEveryDay);
        binding.everydayCheck.setOnCheckedChangeListener(this);
    }

    // shows date picker to pick date and set to tv
    private void getDate() {

        if (datePickerDialog == null) return;

        datePickerDialog.show();

        // TODO: 05-07-2023 for lower version

    }

    // shows time picker to pick time and set to textview
    private void getTime(TextView timeText) {
        timeText.setError(null);

        Calendar calendar = Calendar.getInstance(Locale.getDefault());
        // setting calendar to set time
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("hh:mm a", Locale.getDefault());
            Date date = sdf.parse(timeText.getText().toString());
            if (date == null) throw new Exception();
            calendar.setTime(date);
        }catch (Exception e){
            // do nothing
        }

        TimePickerDialog tpd = new TimePickerDialog(requireContext(),
                (TimePickerDialog.OnTimeSetListener) (view, hourOfDay, minute) -> {

                    Calendar cal = Calendar.getInstance();
                    cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
                    cal.set(Calendar.MINUTE, minute);

                    SimpleDateFormat sdf = new SimpleDateFormat("hh:mm a", Locale.getDefault());
                    SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());

                    String selected_time = sdf.format(cal.getTime());
                    timeText.setText(selected_time);
                    timeText.setHint(sdf2.format(cal.getTime()));

                }, calendar.getTime().getHours(), calendar.getTime().getMinutes(), false);

        tpd.show();

    }

    // loading freq. into its resp. spinner
    private void loadFreqNMedType() {
        progressDialog.setTitle("Please wait...");
        progressDialog.setMessage("while we load details for you.");
        progressDialog.setCancelable(false);
        progressDialog.show();

        String token = "Bearer " + AppUtil.getPatientToken(requireContext());
        viewModel.fetchFreqNMedTypes(token, this);
    }

    // frequencies and medication types loading call back
    @Override
    public void onFreqNMedTypeLoaded(FreqNMedTypeResult result) {
        frequencyList.addAll(result.frequencies);
        medicationTypeList.addAll(result.medicationTypes);
        dosageTypeList.addAll(result.dosageUnits);

        ArrayList<String> frequencies = new ArrayList<>();
        for (Frequency frequency : frequencyList) {
            frequencies.add(frequency.title);
        }
        binding.frequencySpinner.setItems(frequencies);

        // default selection to one
        if (frequencies.size() > 1) {
            binding.frequencySpinner.selectItemByIndex(0);
        }

        ArrayList<String> medicationTypes = new ArrayList<>();
        for (MedicationType type : medicationTypeList) {
            medicationTypes.add(type.title);
        }
        binding.medicationsSpinner.setItems(medicationTypes);

        ArrayList<String> dosageTypes = new ArrayList<>();
        for (DosageType dosageType: dosageTypeList){
            dosageTypes.add(dosageType.title);
        }
        binding.dosageSpinner.setItems(dosageTypes);
        try {
            binding.dosageSpinner.selectItemByIndex(0);
        }catch (Exception e){
            // do nothing
        }

        // checking if intent to EDIT or ADD reminder
        Bundle bundle = getArguments();
        if (bundle != null) {
            setLayoutDetails(reminder = (ReminderResult) bundle.getSerializable(REMINDER_KEY));
        }else{
            // selecting default week day as current
            Calendar calendar = Calendar.getInstance();
            int day_of_week = calendar.get(Calendar.DAY_OF_WEEK) - 1;

            setSelectionState(day_of_week, week_state[day_of_week] = true);
        }

        progressDialog.dismiss();
    }

    @Override
    public void onFreqNMedTypeLoadFailed(Throwable t, String message) {
        progressDialog.dismiss();
        AppUtil.showAlert(requireContext(),
                getString(R.string.something_went_wrong),
                message,
                getString(R.string.ok),
                ((dialog, which) -> {
                    dialog.dismiss();
                }), null, null);
    }

    // add reminder call back
    @Override
    public void onReminderAdded(ReminderResult reminderDetails) {
        progressDialog.dismiss();

        if (reminder == null) {
            Toast.makeText(requireContext(), "Reminder added successfully.", Toast.LENGTH_SHORT).show();

            Activity activity = getActivity();
            if (activity != null){
                activity.onBackPressed();
            }

        } else {

            AppUtil.showAnimateDBS(requireContext(),
                    getString(R.string.changes_successful), R.raw.done_anim_primary,
                    3600, v3 -> {
                        // here v3 is null
                        Activity activity = getActivity();
                        if (activity != null){
                            activity.onBackPressed();
                        }
                    });
        }
    }

    @Override
    public void onReminderAddFailed(Throwable t, String message) {
        progressDialog.dismiss();
        AppUtil.showAlert(requireContext(),
                getString(R.string.something_went_wrong),
                message,
                getString(R.string.ok),
                ((dialog, which) -> {
                    dialog.dismiss();
                }), null, null);
    }
}
