package com.app.simplitend.patientprofile.medreminder.mvvm;

import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.recyclerview.widget.RecyclerView;

import com.app.simplitend.R;
import com.app.simplitend.apputils.AppUtil;
import com.app.simplitend.databinding.ReminderViewholderBinding;
import com.app.simplitend.patientprofile.medreminder.mvvm.models.ReminderResult;

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

public class ReminderAdapter extends RecyclerView.Adapter<ReminderAdapter.ReminderViewHolder> {

    private ReminderCheckClickListener checkClickListener;
    private ReminderClickListener reminderClickListener;

    private volatile Date selected_date;

    private List<ReminderResult> reminderResultList;

    public ReminderAdapter(ArrayList<ReminderResult> reminderResultList){
        this.reminderResultList = reminderResultList;
    }

    public void setCheckClickListener(ReminderCheckClickListener checkClickListener) {
        this.checkClickListener = checkClickListener;
    }

    public void setReminderClickListener(ReminderClickListener reminderClickListener) {
        this.reminderClickListener = reminderClickListener;
    }

    public void submitLIst(List<ReminderResult> reminderResultList){
        this.reminderResultList = null;
        this.reminderResultList = reminderResultList;
        notifyDataSetChanged();
    }

    public List<ReminderResult> getReminderResultList() {
        return reminderResultList;
    }

    public void setSelected_date(Date selected_date) {
        this.selected_date = selected_date;
    }

    public Date getSelected_date() {
        return selected_date;
    }

    @NonNull
    @Override
    public ReminderViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        ReminderViewholderBinding binding = ReminderViewholderBinding.inflate(LayoutInflater.from(parent.getContext()));
        return new ReminderViewHolder(binding);
    }

    @Override
    public void onBindViewHolder(@NonNull ReminderViewHolder holder, int position) {
        holder.setReminder(reminderResultList.get(position), position);

        holder.binding.done.setOnClickListener(v -> {
            if (checkClickListener != null) checkClickListener.onCheck(reminderResultList.get(position), position);
        });

        holder.binding.card.setOnClickListener(v -> {
            if (reminderClickListener != null)
            {
                reminderClickListener.onReminderClicked(reminderResultList.get(position), position);
            }
        });

    }

    @Override
    public int getItemCount() {
        return reminderResultList.size();
    }

    public static class ReminderViewHolder extends RecyclerView.ViewHolder{

        public ReminderViewholderBinding binding;

        public ReminderViewHolder(ReminderViewholderBinding binding){
            super(binding.getRoot());
            this.binding = binding;
        }

        public void setReminder(ReminderResult reminder, int position){
            binding.medName.setText(reminder.medicine_name);

            String instruction;
            if (reminder.medication_instruction == null || reminder.medication_instruction.trim().isEmpty()){
                instruction = "None";
            }else{
                instruction = reminder.medication_instruction;
            }

            binding.instruction.setText(instruction);

            String medicine_time = AppUtil.formatDate("HH:mm:ss", "hh:mm a", reminder.medicine_time);

            if (medicine_time != null){
                binding.time.setText(medicine_time);
            }

            String quantity = "";

            if (reminder.medication_type != null && reminder.medication_type.size() > 0) {
                try {
                    quantity = reminder.medication_type.get(0).title.toLowerCase();
                } catch (NullPointerException e) {
                    // do nothing
                    quantity = "unit";
                }
                quantity = reminder.medication_quantity + " " + quantity;
                switch (reminder.medication_type.get(0).title){
                    case "Capsule":
                        binding.medImg.setImageResource(R.drawable.ic_capsules);
                        break;
                    case "Tablet":
                        binding.medImg.setImageResource(R.drawable.ic_pills);
                        break;
                    case "Drop":
                        binding.medImg.setImageResource(R.drawable.ic_drops);
                        break;
                    case "Spoon":
                        binding.medImg.setImageResource(R.drawable.ic_med_spoon);
                        break;
                    case "Cup":
                        binding.medImg.setImageResource(R.drawable.ic_med_cup);
                        break;
                    case "Syringe":
                        binding.medImg.setImageResource(R.drawable.ic_syringe);
                        break;
                    default:
                        binding.medImg.setImageResource(R.drawable.ic_other_med);
                        break;
                }
            }else{
                binding.medImg.setImageResource(R.drawable.ic_capsules);
            }

            binding.quantity.setText(quantity);

            if (reminder.reminder_marked != null){
                /*
                    This routine is done for some day.
                    New, checking if this routine done is done today or day before it
                 */

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

                try {
                    Date routine_date = sdf.parse(reminder.reminder_marked);
                    if (routine_date == null)
                        throw new Exception("Cannot parse routine marked date from Backend");

                    ReminderAdapter routineAdapter = (ReminderAdapter) getBindingAdapter();

                    if (routineAdapter == null) throw new Exception();

                    Date selected_date = routineAdapter.getSelected_date();
                    Calendar selected_calendar = Calendar.getInstance();
                    selected_calendar.setTime(selected_date);

                    Calendar routine_calendar = Calendar.getInstance();
                    routine_calendar.setTime(routine_date);

                    if (routine_calendar.get(Calendar.DAY_OF_MONTH) == selected_calendar.get(Calendar.DAY_OF_MONTH)){
                        // it is the same day on which routine is checked
                        // as routine done date is equal to selected_tab date
                        binding.card.setCardBackgroundColor(AppCompatResources.getColorStateList(itemView.getContext(), R.color.color_primary));
                        binding.innerCard.setBackgroundTintList(AppCompatResources.getColorStateList(itemView.getContext(), R.color.color_accent));
                        binding.done.setImageResource(R.drawable.ic_done_accent_2);
                    }else{
                        // item selected. un-selecting now
                        binding.card.setCardBackgroundColor(AppCompatResources.getColorStateList(itemView.getContext(), R.color.color_accent));
                        binding.innerCard.setBackgroundTintList(AppCompatResources.getColorStateList(itemView.getContext(), R.color.white));
                        binding.done.setImageResource(R.drawable.ic_done_accent);
                    }

                } catch (Exception e) {
                    Toast.makeText(itemView.getContext(), "Couldn't mark it done.", Toast.LENGTH_SHORT).show();
                    // item selected. un-selecting now
                    binding.card.setCardBackgroundColor(AppCompatResources.getColorStateList(itemView.getContext(), R.color.color_accent));
                    binding.innerCard.setBackgroundTintList(AppCompatResources.getColorStateList(itemView.getContext(), R.color.white));
                    binding.done.setImageResource(R.drawable.ic_done_accent);
                }
            }else{
                // item selected. un-selecting now
                binding.card.setCardBackgroundColor(AppCompatResources.getColorStateList(itemView.getContext(), R.color.color_accent));
                binding.innerCard.setBackgroundTintList(AppCompatResources.getColorStateList(itemView.getContext(), R.color.white));
                binding.done.setImageResource(R.drawable.ic_done_accent);
            }

        }

        @NonNull
        private String selectNextReminder(String time1, String time2, String time3) {

            ReminderAdapter routineAdapter = (ReminderAdapter) getBindingAdapter();

            if (routineAdapter == null) return time1;

            // getting selected calendar
            Date selected_date = routineAdapter.getSelected_date();
            Calendar selected_calendar = Calendar.getInstance();
            selected_calendar.setTime(selected_date);

            Calendar cur_cal = Calendar.getInstance();

            String upcoming_reminder;
            if (cur_cal.get(Calendar.DAY_OF_MONTH) == selected_calendar.get(Calendar.DAY_OF_MONTH)) {
                // Current date is selected by user
                // thus, selecting the upcoming reminder time
                upcoming_reminder= selectNextReminder(time1, selectNextReminder(time2, time3));
            }else{
                // some other day is selected
                // thus, showing the first reminder for a day
                upcoming_reminder = smallestTime(time1, smallestTime(time2, time3));
            }

            return upcoming_reminder == null?"None":upcoming_reminder;
        }

        private String selectNextReminder(String time1, String time2) {
            if (time1 == null && time2 == null) return null;
            if (time1 == null) return time2;
            if (time2 == null) return time1;

            // comparing this 2 times with current time
            // first converting time string to calendar
            SimpleDateFormat input_sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());

            try {
                Date date1 = input_sdf.parse(time1);
                Date date2 = input_sdf.parse(time2);

                if (date2 == null || date1 == null) throw new Exception();

                Calendar cur_cal = Calendar.getInstance();
                Date cur_date = new Date(date1.getYear(), date1.getMonth(), date1.getDate(), cur_cal.get(Calendar.HOUR_OF_DAY), cur_cal.get(Calendar.MINUTE), cur_cal.get(Calendar.SECOND));

                // All three above dates are of same date 01 Jan 1970
                // but, of different times i.e. hh:mm:ss

                long t1 = date1.getTime();
                long t2 = date2.getTime();
                long c_t = cur_date.getTime();

                if (t1 < c_t && t2 > c_t){
                    // t1 time is passed and t2 time is yet to come for the same day
                    // thus, returning t2
                    return time2;
                }else if (t1 > c_t && t2 < c_t){
                    // t1 is yet to come for this day, and t2 has already been passed
                    // thus, returning t1
                    return time1;
                }else if (t1 > c_t && t2 > c_t){
                    // Both the times are greater than current time, yet to come
                    // In this case, we show the smallest time

                    if (t1 < t2) return time1;
                    else return time2;
                }else{
                    // Last case would be both the times has passed the current time
                    // thus, showing the last reminder for this day

                    if (t1 < t2) return time2;
                    else return time1;
                }

            }catch (Exception e){
                // if something goes wrong, returning the time1
                return time1;
            }
        }


        private String smallestTime(String time1, String time2) {
            if (time1 == null && time2 == null) return null;
            if (time1 == null) return time2;
            if (time2 == null) return time1;

            // comparing this 2 times with current time
            // first converting time string to calendar
            SimpleDateFormat input_sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());

            try {
                Date date1 = input_sdf.parse(time1);
                Date date2 = input_sdf.parse(time2);

                if (date2 == null || date1 == null) throw new Exception();

                // All times above dates are of same date 01 Jan 1970
                // but, of different times i.e. hh:mm:ss

                long t1 = date1.getTime();
                long t2 = date2.getTime();

                if (t2 < t1) return time2;
                else return time1;

            }catch (Exception e){
                // if something goes wrong, returning the time1
                return time1;
            }
        }
    }

    public interface ReminderCheckClickListener{
        void onCheck(ReminderResult reminderResult, int position);
    }

    public interface ReminderClickListener{
        void onReminderClicked(ReminderResult reminderResult, int position);
    }

}
