Please help me figure out a bug in my Android app code. It is a todo list app in which items can be deferred, and undeferred. However, when I defer active items, the last item which is deferred from the active list, to the deferred list does not show up. 

package com.markrai.waqt.adapter;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.RecyclerView;

import com.markrai.waqt.R;
import com.markrai.waqt.activity.MainActivity;
import com.markrai.waqt.model.Task;
import com.markrai.waqt.storage.JsonStorage;
import com.markrai.waqt.util.TaskUtils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

public class TaskAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private static MainActivity.OnTimerStateChangeListener timerStateChangeListener;
    private static final int VIEW_TYPE_TASK = 0;
    private static final int VIEW_TYPE_SEPARATOR = 1;
    private static final int VIEW_TYPE_DEFERRED_TASK = 2;
    Task currentActiveTask = null;
    private final List<Task> taskList;
    final List<Task> deferredTaskList;
    private final OnStartDragListener dragStartListener;
    int totalTimeBurden;
    final TotalTimeBurdenListener totalTimeBurdenListener;
    final String[] timeOptions;
    private static final long SEPARATOR_ID = Long.MAX_VALUE;


    long remainingTime;
    final Context context;

    public TaskAdapter(Context context, List<Task> taskList, List<Task> deferredTaskList, OnStartDragListener dragStartListener, TotalTimeBurdenListener totalTimeBurdenListener) {
        this.context = context;
        this.taskList = taskList;
        this.deferredTaskList = deferredTaskList;
        this.dragStartListener = dragStartListener;
        this.totalTimeBurdenListener = totalTimeBurdenListener;
        this.totalTimeBurden = TaskUtils.calculateTotalTimeBurden(taskList);
        this.timeOptions = context.getResources().getStringArray(R.array.time_options);
        setHasStableIds(true);
    }

    public void setRemainingTime(long remainingTime) {
        this.remainingTime = remainingTime;
        totalTimeBurdenListener.onTotalTimeBurdenUpdated(TaskUtils.formatTime(totalTimeBurden), remainingTime);
    }

    @Override
    public long getItemId(int position) {
        Task task = getTaskAtPosition(position);
        if (task != null) {
            return task.getId().hashCode();
        } else if (getItemViewType(position) == VIEW_TYPE_SEPARATOR) {
            return SEPARATOR_ID;
        }
        return RecyclerView.NO_ID;
    }

    private Task getTaskAtPosition(int position) {
        if (position < taskList.size()) {
            return taskList.get(position);
        } else if (position > taskList.size()) { // Position after separator
            return deferredTaskList.get(position - taskList.size() - 1);
        }
        return null; // Separator or invalid position
    }


    @Override
    public int getItemViewType(int position) {
        if (position < taskList.size()) {
            return VIEW_TYPE_TASK;
        } else if (position == taskList.size() && !deferredTaskList.isEmpty()) {
            return VIEW_TYPE_SEPARATOR;
        } else {
            return VIEW_TYPE_DEFERRED_TASK;
        }
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if (viewType == VIEW_TYPE_TASK) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.task_item, parent, false);
            TaskViewHolder viewHolder = new TaskViewHolder(view, new CustomTextWatcher(this), this);
            viewHolder.setTimerStateChangeListener(timerStateChangeListener);
            return viewHolder;
        } else if (viewType == VIEW_TYPE_SEPARATOR) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.separator_item, parent, false);
            return new SeparatorViewHolder(view);
        } else {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.task_item, parent, false);
            TaskViewHolder viewHolder = new TaskViewHolder(view, new CustomTextWatcher(this), this);
            viewHolder.setTimerStateChangeListener(timerStateChangeListener);
            return viewHolder;
        }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {

        if (holder instanceof TaskViewHolder taskViewHolder) {
            Task task;
            boolean isDeferred;

            if (position < taskList.size()) {
                task = taskList.get(position);
                isDeferred = false;
            } else {
                task = deferredTaskList.get(position - taskList.size() - 1);
                isDeferred = true;
            }

            taskViewHolder.setTask(task);
            TaskViewBinder.bindTaskViewHolder(
                    taskViewHolder,
                    task,
                    position,
                    isDeferred,
                    this,
                    timeOptions,
                    currentActiveTask,
                    context,
                    totalTimeBurden,
                    remainingTime,
                    dragStartListener,
                    totalTimeBurdenListener
            );

            // Remove any existing TextWatcher before adding a new one
            if (taskViewHolder.editTextTask.getTag() instanceof TextWatcher) {
                taskViewHolder.editTextTask.removeTextChangedListener((TextWatcher) taskViewHolder.editTextTask.getTag());
            }

            // Attach the new TextWatcher and set it as a tag
            taskViewHolder.editTextTask.addTextChangedListener((TextWatcher) taskViewHolder.customTextWatcher);
            taskViewHolder.editTextTask.setTag(taskViewHolder.customTextWatcher);
        }
    }


    public void deferTask(int position) {
        if (position < taskList.size()) {
            Task task = taskList.remove(position);

            // Cancel the timer if it's running
            if (task.isCountdownActive()) {
                // Get the ViewHolder and cancel the timer
                RecyclerView.ViewHolder viewHolder = ((MainActivity) context).findViewByPosition(position);
                if (viewHolder instanceof TaskViewHolder) {
                    ((TaskViewHolder) viewHolder).cancelCountdownTimer();
                }
                // Reset task timer fields
                task.setCountdownActive(false);
                task.setPaused(false);
                task.setRemainingTime(0);

                // Clear the active task reference
                clearActiveTask();
            }

            // Set the deferred date to tomorrow
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DAY_OF_YEAR, 1);
            task.setDeferredDate(calendar.getTime());

            deferredTaskList.add(task);

            notifyItemRemoved(position);

            if (deferredTaskList.size() == 1) {
                // Insert the separator
                notifyItemInserted(taskList.size());
            }

            // Insert the task in the deferred section
            notifyItemInserted(taskList.size() + (deferredTaskList.isEmpty() ? 0 : 1) + (deferredTaskList.size() - 1));

            if (!task.isCompleted()) {
                totalTimeBurden -= TaskUtils.parseTime(task.getTimeBurden());
                totalTimeBurdenListener.onTotalTimeBurdenUpdated(
                        TaskUtils.formatTime(totalTimeBurden),
                        remainingTime
                );
            }
            saveTasks();
            Toast.makeText(context, "Task deferred to tomorrow", Toast.LENGTH_SHORT).show();
        }
    }



    public int getCurrentTaskCount() {
        return taskList.size();
    }

    private Task getTaskAt(int position) {
        if (position < taskList.size()) {
            return taskList.get(position);
        } else {
            return deferredTaskList.get(position - taskList.size());
        }
    }

    public void clearActiveTask() {
        currentActiveTask = null;
    }

    void undeferAndCompleteTask(int position) {
        // Get the task and remove it from the deferred list
        Task task = deferredTaskList.remove(position - taskList.size() - 1);
        task.setDeferredDate(null);
        task.setCompleted(true);

        // Add the task to the active list
        taskList.add(task);
        notifyItemRemoved(position);
        notifyItemInserted(taskList.size() - 1); // Insert at the end of the current tasks list

        // No need to update the total time burden since the task was deferred and not contributing to it
        totalTimeBurdenListener.onTotalTimeBurdenUpdated(TaskUtils.formatTime(totalTimeBurden), remainingTime);

        saveTasks();
        Toast.makeText(context, "Task moved to today and marked as completed", Toast.LENGTH_SHORT).show();
    }

    @Override
    public int getItemCount() {
        int count = taskList.size() + deferredTaskList.size();
        if (!taskList.isEmpty() && !deferredTaskList.isEmpty()) {
            count += 1;
        }
        return count;
    }


    public void addTask(int position, String taskDescription, String timeBurden) {
        if (timeBurden == null || timeBurden.isEmpty()) {
            timeBurden = "5m";
        }
        Task newTask = new Task(UUID.randomUUID().toString(), taskDescription, timeBurden, false, position);

        if (position <= taskList.size()) {
            taskList.add(position, newTask);
            notifyItemInserted(position);
        } else {
            int deferredPosition = position - taskList.size() - 1;
            if (deferredPosition <= deferredTaskList.size()) {
                deferredTaskList.add(deferredPosition, newTask);
                notifyItemInserted(position);
            } else {
                // Handle invalid position gracefully
                taskList.add(newTask);
                notifyItemInserted(taskList.size() - 1);
            }
        }

        if (!timeBurden.equals("0m")) {
            totalTimeBurden += TaskUtils.parseTime(timeBurden);
        }

        totalTimeBurdenListener.onTotalTimeBurdenUpdated(TaskUtils.formatTime(totalTimeBurden), remainingTime);
        saveTasks();

        new Handler().post(() -> {
            RecyclerView.ViewHolder viewHolder = ((MainActivity) context).findViewByPosition(position);
            if (viewHolder instanceof TaskViewHolder) {
                TaskViewHolder taskViewHolder = (TaskViewHolder) viewHolder;
                taskViewHolder.editTextTask.requestFocus();
                InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.showSoftInput(taskViewHolder.editTextTask, InputMethodManager.SHOW_IMPLICIT);
            }
        });
        Intent intent = new Intent("com.markrai.waqt.TASK_DATA_CHANGED");
        context.sendBroadcast(intent);
    }

    public void addDeferredTask(int position, String taskDescription, String timeBurden) {
        if (timeBurden == null || timeBurden.isEmpty()) {
            timeBurden = "5m";
        }
        Task newTask = new Task(UUID.randomUUID().toString(), taskDescription, timeBurden, false, position);
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, 1);
        newTask.setDeferredDate(calendar.getTime());

        deferredTaskList.add(newTask);
        notifyItemInserted(taskList.size() + 1 + deferredTaskList.size());
        saveTasks();
    }

    public void undeferTask(int position) {
        if (position >= taskList.size() + 1) {
            int deferredPosition = position - taskList.size() - 1;
            Task task = deferredTaskList.remove(deferredPosition);
            task.setDeferredDate(null);

            // Remove the task from deferred tasks in RecyclerView
            notifyItemRemoved(position);

            if (deferredTaskList.isEmpty()) {
                // Remove the separator
                notifyItemRemoved(taskList.size()); // Separator is at position taskList.size()
            }

            // Add task to taskList
            taskList.add(task);

            // Notify that a new item is inserted at the end of taskList
            notifyItemInserted(taskList.size() - 1);

            if (!task.isCompleted()) {
                totalTimeBurden += TaskUtils.parseTime(task.getTimeBurden());
                totalTimeBurdenListener.onTotalTimeBurdenUpdated(
                        TaskUtils.formatTime(totalTimeBurden),
                        remainingTime
                );
            }
            saveTasks();
            Toast.makeText(context, "Task moved to today", Toast.LENGTH_SHORT).show();
        }
    }


    public void removeTask(int position) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
        boolean confirmDelete = prefs.getBoolean("confirm_delete_task", false);

        if (confirmDelete) {
            new AlertDialog.Builder(context, R.style.CustomAlertDialogTheme)
                    .setTitle("Delete Task")
                    .setMessage("Are you sure?")
                    .setPositiveButton(android.R.string.yes, (dialog, which) -> performRemoveTask(position))
                    .setNegativeButton(android.R.string.no, (dialog, which) -> {
                        // Restore the task
                        notifyItemChanged(position);
                    })
                    .setCancelable(false)
                    .show();
        } else {
            performRemoveTask(position);
        }
        Intent intent = new Intent("com.markrai.waqt.TASK_DATA_CHANGED");
        context.sendBroadcast(intent);
    }

    private void performRemoveTask(int position) {
        Task task;
        TaskViewHolder taskViewHolder = (TaskViewHolder) ((MainActivity) context).findViewByPosition(position);

        if (taskViewHolder != null) {
            taskViewHolder.cancelCountdownTimer();
        }

        // If the task being removed is the current active task, clear the active task
        if (currentActiveTask != null && taskList.get(position).equals(currentActiveTask)) {
            clearActiveTask(); // Clear the current active task
        }

        boolean isDeferred = position >= taskList.size() + 1;

        if (isDeferred) {
            int deferredPosition = position - taskList.size() - 1;
            task = deferredTaskList.remove(deferredPosition);
            notifyItemRemoved(position);
            notifyItemRangeChanged(taskList.size() + 1, deferredTaskList.size());
        } else {
            task = taskList.remove(position);
            if (!task.isCompleted()) {
                totalTimeBurden -= TaskUtils.parseTime(task.getTimeBurden());
            }
            notifyItemRemoved(position);
            notifyItemRangeChanged(position, taskList.size());
        }

        totalTimeBurdenListener.onTotalTimeBurdenUpdated(TaskUtils.formatTime(totalTimeBurden), remainingTime);
        saveTasks();
    }

    public void moveItem(int fromPosition, int toPosition) {
        if (fromPosition < taskList.size()) {
            if (toPosition < taskList.size()) {
                Collections.swap(taskList, fromPosition, toPosition);
            } else if (toPosition > taskList.size()) {
                Task task = taskList.remove(fromPosition);
                deferredTaskList.add(toPosition - taskList.size() - 1, task);
            }
        } else {
            if (toPosition > taskList.size()) {
                Collections.swap(deferredTaskList, fromPosition - taskList.size() - 1, toPosition - taskList.size() - 1);
            } else if (toPosition < taskList.size()) {
                Task task = deferredTaskList.remove(fromPosition - taskList.size() - 1);
                taskList.add(toPosition, task);
            }
        }
        notifyItemMoved(fromPosition, toPosition);
        saveTasks();
    }

    void moveItemToBottom(int position) {
        Task task;
        if (position < taskList.size()) {
            task = taskList.remove(position);
            taskList.add(task);
            notifyItemMoved(position, taskList.size() - 1);
        } else {
            task = deferredTaskList.remove(position - taskList.size() - 1);
            deferredTaskList.add(task);
            notifyItemMoved(position, getItemCount() - 1);
        }
        notifyItemRangeChanged(position, getItemCount());
    }

    void moveItemToTop(int position) {
        Task task;
        if (position < taskList.size()) {
            task = taskList.remove(position);
            taskList.add(0, task);
            notifyItemMoved(position, 0);
        } else {
            task = deferredTaskList.remove(position - taskList.size() - 1);
            taskList.add(0, task);
            notifyItemMoved(position, 0);
        }
        notifyItemRangeChanged(0, getItemCount());
    }

    public List<Task> getTaskList() {
        List<Task> combinedTasks = new ArrayList<>(taskList);
        combinedTasks.addAll(deferredTaskList);
        return combinedTasks;
    }

    static class SeparatorViewHolder extends RecyclerView.ViewHolder {
        SeparatorViewHolder(@NonNull View itemView) {
            super(itemView);
        }
    }

    class CustomTextWatcher implements TextWatcher {

        private int position;
        private EditText editTextTask;
        private final TaskAdapter adapter;

        public CustomTextWatcher(TaskAdapter adapter) {
            this.adapter = adapter;
        }

        public void setEditTexts(EditText editTextTask) {
            this.editTextTask = editTextTask;
        }

        public void updatePosition(int position) {
            this.position = position;
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            // No action needed before text changed
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            if (position >= 0 && position < adapter.getItemCount()) {
                Task task;
                if (position < adapter.taskList.size()) {
                    task = adapter.taskList.get(position);
                } else {
                    task = adapter.deferredTaskList.get(position - adapter.taskList.size() - 1);
                }
                if (task != null) {
                    if (editTextTask.hasFocus()) {
                        task.setTaskDescription(s.toString());
                        adapter.saveTasks();
                    }
                }
            }
        }

        @Override
        public void afterTextChanged(Editable s) {
            // No action needed after text changed
        }
    }

    public interface OnStartDragListener {
        void onStartDrag(RecyclerView.ViewHolder viewHolder);
    }

    public interface TotalTimeBurdenListener {
        void onTotalTimeBurdenUpdated(String formattedTotalTimeBurden, long remainingTime);
    }

    void saveTasks() {
        JsonStorage.saveTasks(context, getTaskList());
    }
}

package com.markrai.waqt.activity;

import android.app.AlertDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.markrai.waqt.R;
import com.markrai.waqt.adapter.TaskAdapter;
import com.markrai.waqt.adapter.TaskItemTouchHelperCallback;
import com.markrai.waqt.model.Task;
import com.markrai.waqt.storage.JsonStorage;
import com.markrai.waqt.util.TaskUtils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

public class MainActivity extends AppCompatActivity implements TaskAdapter.OnStartDragListener, TaskAdapter.TotalTimeBurdenListener {

    private static final String PREFS_NAME = "UserSettings";
    private static final String WAKEUP_TIME_HOUR = "WakeupTimeHour";
    private static final String WAKEUP_TIME_MINUTE = "WakeupTimeMinute";
    private static final String BEDTIME_HOUR = "BedtimeHour";
    private static final String BEDTIME_MINUTE = "BedtimeMinute";
    public static final int REQUEST_DRAW = 1;
    private TaskAdapter taskAdapter;
    private ItemTouchHelper itemTouchHelper;
    private TextView textViewTotalTimeBurden;
    private TextView textViewCountdownTimer;
    private long remainingTime;
    private List<Task> tasks;
    private List<Task> deferredTasks;
    private CountDownTimer countdownTimer;
    private Button buttonAddTask;
    private boolean isTaskTimerActive = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        List<Task> allTasks = JsonStorage.loadTasks(this);
        tasks = allTasks.stream()
                .filter(task -> task.getDeferredDate() == null || !task.getDeferredDate().after(new Date()))
                .collect(Collectors.toList());

        deferredTasks = allTasks.stream()
                .filter(task -> task.getDeferredDate() != null && task.getDeferredDate().after(new Date()))
                .collect(Collectors.toList());

        if (tasks == null || tasks.isEmpty()) {
            tasks = new ArrayList<>();
        }

        taskAdapter = new TaskAdapter(this, tasks, deferredTasks, this, this);

        if (getSupportActionBar() != null) {
            getSupportActionBar().hide();
        }

        textViewTotalTimeBurden = findViewById(R.id.textViewTotalTimeBurden);
        textViewCountdownTimer = findViewById(R.id.textViewCountdownTimer);
        RecyclerView recyclerViewTasks = findViewById(R.id.recyclerViewTasks);
        buttonAddTask = findViewById(R.id.buttonAddTask);

        recyclerViewTasks.setLayoutManager(new LinearLayoutManager(this));
        recyclerViewTasks.setAdapter(taskAdapter);

        ItemTouchHelper.Callback callback = new TaskItemTouchHelperCallback(taskAdapter, this);
        itemTouchHelper = new ItemTouchHelper(callback);
        itemTouchHelper.attachToRecyclerView(recyclerViewTasks);

        initializeCountdownTimer();

        textViewCountdownTimer.setOnLongClickListener(v -> {
            if (isTaskTimerActive) {
                // Optionally show a message to the user
                Toast.makeText(MainActivity.this, "Cannot set time while a task timer is active.", Toast.LENGTH_SHORT).show();
                return true; // Prevent the long-press action
            } else {
                showTimePickerDialog(); // Allow the long-press action
                return true;
            }
        });

        // Set up click listener for the logo
        ImageView imageViewLogo = findViewById(R.id.imageViewLogo);
        imageViewLogo.setOnClickListener(v -> {
            Intent intent = new Intent(MainActivity.this, SettingsActivity.class);
            startActivity(intent);
        });

        buttonAddTask.setOnClickListener(v -> {
            taskAdapter.addTask(0, "", "0m");
            recyclerViewTasks.smoothScrollToPosition(0); // Scroll to the newly added task
        });

        updateTotalTimeBurden();
        updateAddTaskButtonVisibility();
    }


    public interface OnTimerStateChangeListener {
        void onTimerStarted();
    }


    @Override
    protected void onResume() {
        super.onResume();
        updateAddTaskButtonVisibility();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    private void updateAddTaskButtonVisibility() {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        boolean hideAddTaskButton = prefs.getBoolean("hide_add_task_button", false);
        buttonAddTask.setVisibility(hideAddTaskButton ? View.GONE : View.VISIBLE);
    }

    private void showTimePickerDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.CustomAlertDialogTheme);
        LayoutInflater inflater = this.getLayoutInflater();
        View dialogView = inflater.inflate(R.layout.dialog_time_picker, null);

        // Set the background color and rounded corners to the dialog view itself
        dialogView.setBackgroundResource(R.drawable.rounded_dialog_background);

        builder.setView(dialogView)
                .setPositiveButton("Set", (dialog, id) -> {
                    TimePicker timePickerWakeUp = dialogView.findViewById(R.id.timePickerWakeUp);
                    TimePicker timePickerBedTime = dialogView.findViewById(R.id.timePickerBedTime);

                    // Get and save the wake-up and bedtime
                    int wakeupHour = timePickerWakeUp.getHour();
                    int wakeupMinute = timePickerWakeUp.getMinute();
                    int bedtimeHour = timePickerBedTime.getHour();
                    int bedtimeMinute = timePickerBedTime.getMinute();

                    saveWakeupAndBedtime(wakeupHour, wakeupMinute, bedtimeHour, bedtimeMinute);
                    initializeCountdownTimer(); // Reinitialize the countdown timer with new times
                })
                .setNegativeButton("Cancel", (dialog, id) -> dialog.cancel());

        AlertDialog dialog = builder.create();
        dialog.show();

        // Set TimePicker to 12-hour view programmatically
        TimePicker timePickerWakeUp = dialogView.findViewById(R.id.timePickerWakeUp);
        TimePicker timePickerBedTime = dialogView.findViewById(R.id.timePickerBedTime);
        timePickerWakeUp.setIs24HourView(false);
        timePickerBedTime.setIs24HourView(false);

        // Load saved wake-up and bedtimes
        SharedPreferences preferences = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
        int wakeupHour = preferences.getInt(WAKEUP_TIME_HOUR, 7);
        int wakeupMinute = preferences.getInt(WAKEUP_TIME_MINUTE, 30);
        int bedtimeHour = preferences.getInt(BEDTIME_HOUR, 21);
        int bedtimeMinute = preferences.getInt(BEDTIME_MINUTE, 0);

        // Set the current times to the time pickers
        timePickerWakeUp.setHour(wakeupHour);
        timePickerWakeUp.setMinute(wakeupMinute);
        timePickerBedTime.setHour(bedtimeHour);
        timePickerBedTime.setMinute(bedtimeMinute);
    }

    private void saveWakeupAndBedtime(int wakeupHour, int wakeupMinute, int bedtimeHour, int bedtimeMinute) {
        SharedPreferences preferences = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
        SharedPreferences.Editor editor = preferences.edit();
        editor.putInt(WAKEUP_TIME_HOUR, wakeupHour);
        editor.putInt(WAKEUP_TIME_MINUTE, wakeupMinute);
        editor.putInt(BEDTIME_HOUR, bedtimeHour);
        editor.putInt(BEDTIME_MINUTE, bedtimeMinute);
        editor.apply();
    }

    @Override
    protected void onStop() {
        super.onStop();
        JsonStorage.saveTasks(this, taskAdapter.getTaskList());
    }

    @Override
    public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
        itemTouchHelper.startDrag(viewHolder);
    }

    @Override
    public void onTotalTimeBurdenUpdated(String formattedTotalTimeBurden, long remainingTime) {
        textViewTotalTimeBurden.setText(formattedTotalTimeBurden);
        if (TaskUtils.parseFormattedTime(formattedTotalTimeBurden) > remainingTime) {
            textViewTotalTimeBurden.setTextColor(getResources().getColor(android.R.color.holo_red_dark));
        } else {
            textViewTotalTimeBurden.setTextColor(getResources().getColor(android.R.color.black));
        }
    }


    private void initializeCountdownTimer() {
        // Load the wake-up and bedtimes
        SharedPreferences preferences = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
        int wakeupHour = preferences.getInt(WAKEUP_TIME_HOUR, 7);
        int wakeupMinute = preferences.getInt(WAKEUP_TIME_MINUTE, 30);
        int bedtimeHour = preferences.getInt(BEDTIME_HOUR, 21);
        int bedtimeMinute = preferences.getInt(BEDTIME_MINUTE, 0);

        // Get the current time
        Calendar currentTime = Calendar.getInstance();
        long currentMillis = currentTime.getTimeInMillis();

        // Calculate wake-up and bedtime in milliseconds
        Calendar wakeupTime = Calendar.getInstance();
        wakeupTime.set(Calendar.HOUR_OF_DAY, wakeupHour);
        wakeupTime.set(Calendar.MINUTE, wakeupMinute);
        wakeupTime.set(Calendar.SECOND, 0);
        wakeupTime.set(Calendar.MILLISECOND, 0);
        long wakeupMillis = wakeupTime.getTimeInMillis();

        Calendar bedTime = Calendar.getInstance();
        bedTime.set(Calendar.HOUR_OF_DAY, bedtimeHour);
        bedTime.set(Calendar.MINUTE, bedtimeMinute);
        bedTime.set(Calendar.SECOND, 0);
        bedTime.set(Calendar.MILLISECOND, 0);
        long bedMillis = bedTime.getTimeInMillis();

        // Adjust for times after midnight (when bedMillis < wakeupMillis)
        if (bedMillis < wakeupMillis) {
            bedTime.add(Calendar.DAY_OF_MONTH, 1);
            bedMillis = bedTime.getTimeInMillis();
        }

        // Check if current time is between bedtime and wake-up time
        if (currentMillis >= bedMillis || currentMillis < wakeupMillis) {
            textViewCountdownTimer.setText("00:00");
            if (countdownTimer != null) {
                countdownTimer.cancel();
            }

            // Schedule a new countdown timer to start at wake-up time
            long millisUntilWakeup = wakeupMillis - currentMillis;
            if (millisUntilWakeup < 0) {
                // Adjust for next day's wake-up time
                wakeupTime.add(Calendar.DAY_OF_MONTH, 1);
                wakeupMillis = wakeupTime.getTimeInMillis();
                millisUntilWakeup = wakeupMillis - currentMillis;
            }

            new CountDownTimer(millisUntilWakeup, 1000) {
                public void onTick(long millisUntilFinished) {
                    // No need to update UI, just waiting for wake-up time
                }

                public void onFinish() {
                    initializeCountdownTimer(); // Reinitialize the countdown timer at wake-up time
                }
            }.start();
        } else {
            // Calculate the remaining time until bedtime
            remainingTime = bedMillis - currentMillis;
            taskAdapter.setRemainingTime(remainingTime);

            if (countdownTimer != null) {
                countdownTimer.cancel(); // Cancel any existing countdown timer
            }

            // Create and start the countdown timer
            countdownTimer = new CountDownTimer(remainingTime, 1000) {
                public void onTick(long millisUntilFinished) {
                    // Update the countdown timer text view every second
                    textViewCountdownTimer.setText(TaskUtils.formatMillis(millisUntilFinished));
                    taskAdapter.setRemainingTime(millisUntilFinished);
                }

                public void onFinish() {
                    // Countdown timer finished
                    textViewCountdownTimer.setText("00:00");

                    // Schedule a new countdown timer to start at wake-up time
                    Calendar wakeupTime = Calendar.getInstance();
                    wakeupTime.set(Calendar.HOUR_OF_DAY, wakeupHour);
                    wakeupTime.set(Calendar.MINUTE, wakeupMinute);
                    wakeupTime.set(Calendar.SECOND, 0);
                    wakeupTime.set(Calendar.MILLISECOND, 0);
                    wakeupTime.add(Calendar.DAY_OF_MONTH, 1);

                    long millisUntilWakeup = wakeupTime.getTimeInMillis() - currentMillis;

                    new CountDownTimer(millisUntilWakeup, 1000) {
                        public void onTick(long millisUntilFinished) {
                            // No need to update UI, just waiting for wake-up time
                        }

                        public void onFinish() {
                            initializeCountdownTimer(); // Reinitialize the countdown timer at wake-up time
                        }
                    }.start();
                }
            }.start();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_DRAW && resultCode == RESULT_OK && data != null) {
            String imagePath = data.getStringExtra("imagePath");
            String taskId = data.getStringExtra("taskId");

            if (taskId != null && imagePath != null) {
                // Update the task in both active and deferred lists
                for (int i = 0; i < tasks.size(); i++) {
                    if (tasks.get(i).getId().equals(taskId)) {
                        taskAdapter.notifyItemChanged(i);
                        break;
                    }
                }

                for (int i = 0; i < deferredTasks.size(); i++) {
                    if (deferredTasks.get(i).getId().equals(taskId)) {
                        taskAdapter.notifyItemChanged(i + tasks.size() + 1); // Adjust for deferred tasks position
                        break;
                    }
                }
            }
        }
    }


    public RecyclerView.ViewHolder findViewByPosition(int position) {
        RecyclerView recyclerViewTasks = findViewById(R.id.recyclerViewTasks);
        return recyclerViewTasks.findViewHolderForAdapterPosition(position);
    }

    private void updateTotalTimeBurden() {
        int totalTimeBurden = TaskUtils.calculateTotalTimeBurden(tasks);
        textViewTotalTimeBurden.setText(TaskUtils.formatTime(totalTimeBurden));
    }
}

package com.markrai.waqt.adapter;

import android.content.Context;
import android.text.InputFilter;
import android.text.InputType;
import android.text.Spanned;

import androidx.recyclerview.widget.RecyclerView;

import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Toast;

import androidx.core.widget.CompoundButtonCompat;

import com.markrai.waqt.R;
import com.markrai.waqt.activity.MainActivity;
import com.markrai.waqt.model.Task;
import com.markrai.waqt.storage.JsonStorage;
import com.markrai.waqt.util.TaskUtils;

public class TaskViewBinder {

    static void bindTaskViewHolder(
            TaskViewHolder holder,
            Task task,
            int position,
            boolean isDeferred,
            TaskAdapter adapter,
            String[] timeOptions,
            Task currentActiveTask,
            Context context,
            int totalTimeBurden,
            long remainingTime,
            TaskAdapter.OnStartDragListener dragStartListener,
            TaskAdapter.TotalTimeBurdenListener totalTimeBurdenListener
    ) {

        // Bind task to the holder and set position
        task.setPosition(position);
        holder.setTask(task); // Bind the task to the ViewHolder
        holder.customTextWatcher.updatePosition(holder.getAdapterPosition());
        holder.editTextTask.setText(task.getTaskDescription());
        holder.editTextTask.setSingleLine(true);
        holder.editTextTask.setImeOptions(EditorInfo.IME_ACTION_DONE);
        holder.editTextTask.setInputType(InputType.TYPE_CLASS_TEXT);


        holder.editTextTask.setFilters(new InputFilter[]{new InputFilter() {
            @Override
            public CharSequence filter(CharSequence source, int start, int end,
                                       Spanned dest, int dstart, int dend) {
                for (int i = start; i < end; i++) {
                    if (source.charAt(i) == '\n') {
                        // Prevent manual line breaks (Enter key)
                        return "";
                    }
                }
                return null;
            }
        }});


        // Set up the Spinner
        ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(holder.itemView.getContext(), android.R.layout.simple_spinner_item, timeOptions);
        spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        holder.spinnerTimeBurden.setAdapter(spinnerAdapter);

        // Set the current time burden
        int spinnerPosition = spinnerAdapter.getPosition(task.getTimeBurden());
        if (spinnerPosition == -1) {
            spinnerPosition = 0;
            task.setTimeBurden(timeOptions[spinnerPosition]);
        }
        holder.spinnerTimeBurden.setSelection(spinnerPosition);

        // Restore the countdown timer state
        if (task.isCountdownActive()) {
            holder.playIcon.setVisibility(View.VISIBLE);
            if (task.isPaused()) {
                holder.playIcon.setImageResource(R.drawable.ic_pause_black_24dp);
                holder.startBlinking();
            } else {
                holder.playIcon.setImageResource(R.drawable.ic_play_arrow_black_24dp);
                holder.stopBlinking();
            }

            // Disable spinner and show the countdown time
            holder.spinnerTimeBurden.setEnabled(false);
            holder.spinnerTimeBurden.setAlpha(0.5f);
            holder.spinnerTimeBurden.setVisibility(View.INVISIBLE);
            holder.textViewTimer.setVisibility(View.VISIBLE);
            holder.textViewTimer.setText(TaskUtils.formatCountdownTime(task.getRemainingTime()));

            // Restart the countdown timer, binding it to the task ID
            holder.startCountdownTimer(
                    task.getRemainingTime(),
                    () -> {
                        holder.spinnerTimeBurden.setEnabled(true);
                        holder.spinnerTimeBurden.setAlpha(1.0f);
                        holder.textViewTimer.setVisibility(View.GONE);
                        holder.spinnerTimeBurden.setVisibility(View.VISIBLE);
                        holder.stopBlinking();
                        holder.playIcon.setVisibility(View.GONE);
                        Toast.makeText(context, "Time's up!", Toast.LENGTH_SHORT).show();
                        adapter.clearActiveTask();
                    },
                    spinnerAdapter
            );

        } else {
            // If no countdown is active, reset views to their default state
            holder.playIcon.setVisibility(View.GONE);
            holder.textViewTimer.setVisibility(View.GONE);
            holder.spinnerTimeBurden.setEnabled(true);
            holder.spinnerTimeBurden.setAlpha(1.0f);
            holder.stopBlinking();
            holder.spinnerTimeBurden.setVisibility(View.VISIBLE);

            String timeToDisplay = task.getOriginalTimeBurden() != null ? task.getOriginalTimeBurden() : task.getTimeBurden();
            holder.spinnerTimeBurden.setSelection(spinnerAdapter.getPosition(timeToDisplay));
        }

        // Long press on spinner to start or stop the countdown timer
        holder.spinnerTimeBurden.setOnLongClickListener(v -> {

            if (isDeferred) {
                adapter.undeferTask(position);
                int newPosition = adapter.getTaskList().size() - 1;
                new Handler(Looper.getMainLooper()).post(() -> {
                    RecyclerView.ViewHolder viewHolder = ((MainActivity) context).findViewByPosition(newPosition);
                    if (viewHolder instanceof TaskViewHolder) {
                        TaskViewHolder newHolder = (TaskViewHolder) viewHolder;
                        newHolder.spinnerTimeBurden.performLongClick();
                    }
                });
                return true;
            }

            if (adapter.currentActiveTask != null && !adapter.currentActiveTask.getId().equals(task.getId())) {
                Toast.makeText(context, "Let's focus on one thing at a time 😉", Toast.LENGTH_SHORT).show();
                return true; // Prevent starting a new timer
            }

            if (task.isCountdownActive()) {
                // User wants to stop the timer
                holder.cancelCountdownTimer();
                task.setCountdownActive(false);
                task.setPaused(false);
                task.setRemainingTime(0);
                adapter.saveTasks();

                holder.spinnerTimeBurden.setEnabled(true);
                holder.spinnerTimeBurden.setAlpha(1.0f);
                holder.textViewTimer.setVisibility(View.GONE);
                holder.stopBlinking();
                holder.playIcon.setVisibility(View.GONE);
                holder.spinnerTimeBurden.setVisibility(View.VISIBLE);


                Toast.makeText(context, "Timer stopped.", Toast.LENGTH_SHORT).show();

                adapter.clearActiveTask();
            } else {
                String selectedTime = task.getTimeBurden();
                int timeInMinutes = TaskUtils.parseTime(selectedTime);

                if (timeInMinutes > 0) {
                    long millisInFuture = timeInMinutes * 60 * 1000;

                    Log.d("TaskAdapter", "Starting countdown timer for " + selectedTime + " (" + millisInFuture + "ms) for task with ID " + task.getId());

                    adapter.currentActiveTask = task;

                    holder.spinnerTimeBurden.setEnabled(false);

                    holder.startCountdownTimer(millisInFuture, () -> {
                        holder.spinnerTimeBurden.setEnabled(true);
                        holder.spinnerTimeBurden.setAlpha(1.0f);
                        holder.textViewTimer.setVisibility(View.GONE);
                        holder.stopBlinking();
                        holder.playIcon.setVisibility(View.GONE);
                        Toast.makeText(context, "Time's up!", Toast.LENGTH_SHORT).show();

                        adapter.clearActiveTask();
                    }, spinnerAdapter);

                } else {
                    Toast.makeText(context, "Cannot start timer for 0m", Toast.LENGTH_SHORT).show();
                }
            }
            return true;
        });


        holder.spinnerTimeBurden.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int spinnerPosition, long id) {
                String selectedTime = timeOptions[spinnerPosition];
                int oldTimeBurden = TaskUtils.parseTime(task.getTimeBurden());
                int newTimeBurden = TaskUtils.parseTime(selectedTime);

                if (!task.isCompleted() && !isDeferred) {
                    adapter.totalTimeBurden -= oldTimeBurden;
                    adapter.totalTimeBurden += newTimeBurden;
                }

                task.setTimeBurden(selectedTime);
                if (!isDeferred) {
                    totalTimeBurdenListener.onTotalTimeBurdenUpdated(TaskUtils.formatTime(adapter.totalTimeBurden), remainingTime);
                }
                adapter.saveTasks();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parentView) {
                // No action needed
            }
        });

        holder.checkBoxTask.setChecked(task.isCompleted());
        if (isDeferred) {
            CompoundButtonCompat.setButtonTintList(holder.checkBoxTask, ColorStateList.valueOf(context.getResources().getColor(R.color.white)));
        } else {
            CompoundButtonCompat.setButtonTintList(holder.checkBoxTask, ColorStateList.valueOf(Color.BLACK));
        }

        // Apply gray color to individual items if the task is completed
        if (task.isCompleted()) {
            holder.editTextTask.setTextColor(Color.GRAY);
            holder.editTextTask.setBackgroundTintList(ColorStateList.valueOf(Color.GRAY));
            holder.spinnerTimeBurden.setEnabled(false);
            CompoundButtonCompat.setButtonTintList(holder.checkBoxTask, ColorStateList.valueOf(Color.GRAY));
            holder.dragHandle.setColorFilter(Color.GRAY);
        } else {
            holder.editTextTask.setTextColor(Color.BLACK);
            holder.editTextTask.setBackgroundTintList(ColorStateList.valueOf(Color.BLACK));
            holder.spinnerTimeBurden.setEnabled(true);
            CompoundButtonCompat.setButtonTintList(holder.checkBoxTask, ColorStateList.valueOf(Color.BLACK));
            holder.dragHandle.setColorFilter(Color.BLACK);
        }

        holder.editTextTask.setOnEditorActionListener((v, actionId, event) -> {
            if (actionId == EditorInfo.IME_ACTION_DONE && event == null) {
                String taskDescription = v.getText().toString().trim();
                if (!taskDescription.isEmpty()) {
                    // Ensure time burden is set
                    if (task.getTimeBurden().equals("0m")) {
                        task.setTimeBurden("5m");
                        if (!isDeferred) {
                            adapter.totalTimeBurden += TaskUtils.parseTime("5m");
                            totalTimeBurdenListener.onTotalTimeBurdenUpdated(
                                    TaskUtils.formatTime(adapter.totalTimeBurden),
                                    remainingTime
                            );
                        }
                        adapter.notifyItemChanged(position);
                    }

                    // Find the task's actual index in the taskList or deferredTaskList
                    int taskIndex;
                    if (isDeferred) {
                        taskIndex = adapter.deferredTaskList.indexOf(task);
                        adapter.addDeferredTask(taskIndex + 1, "", "0m");
                    } else {
                        taskIndex = adapter.getTaskList().indexOf(task);
                        adapter.addTask(taskIndex + 1, "", "0m");
                    }

                    // Move focus to the new task's EditText
                    new Handler().post(() -> {
                        RecyclerView.ViewHolder viewHolder = ((MainActivity) context).findViewByPosition(taskIndex + 1);
                        if (viewHolder instanceof TaskViewHolder) {
                            TaskViewHolder taskViewHolder = (TaskViewHolder) viewHolder;
                            taskViewHolder.editTextTask.requestFocus();
                            InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
                            imm.showSoftInput(taskViewHolder.editTextTask, InputMethodManager.SHOW_IMPLICIT);
                        }
                    });
                    return true; // Consume the event
                } else {
                    return true; // Consume the event even if the description is empty
                }
            }
            return false;
        });




        holder.editTextTask.setOnFocusChangeListener((v, hasFocus) -> {
            if (hasFocus) {
                holder.editTextTask.setBackgroundTintList(ColorStateList.valueOf(Color.RED));
            } else {
                holder.editTextTask.setBackgroundTintList(ColorStateList.valueOf(task.isCompleted() ? Color.GRAY : Color.BLACK));
            }
        });


        // Set the touch listener only on the drag handle
        holder.dragHandle.setOnTouchListener((v, event) -> {
            if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
                dragStartListener.onStartDrag(holder);
                return true;  // Handle the event
            }
            return false;
        });

        // Override performClick or ensure it's called
        holder.dragHandle.setOnClickListener(v -> {
            // Handle click actions
            v.performClick(); // Ensure performClick() is called for accessibility
        });

        holder.checkBoxTask.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (holder.checkBoxTask.isPressed()) {
                if (isDeferred && isChecked) {
                    // Handle the case where a deferred task is marked as completed
                    adapter.undeferAndCompleteTask(position);
                } else {
                    task.setCompleted(isChecked);
                    if (isChecked) {
                        adapter.totalTimeBurden -= TaskUtils.parseTime(task.getTimeBurden());
                        adapter.moveItemToBottom(position);
                    } else {
                        if (!isDeferred) {
                            adapter.totalTimeBurden += TaskUtils.parseTime(task.getTimeBurden());
                        }
                        if (!isDeferred) {
                            adapter.moveItemToTop(position);
                        }
                    }
                    totalTimeBurdenListener.onTotalTimeBurdenUpdated(TaskUtils.formatTime(adapter.totalTimeBurden), remainingTime);
                    adapter.notifyItemChanged(position);
                    adapter.saveTasks();
                }
            }
        });

        holder.editTextTask.addTextChangedListener(holder.customTextWatcher);

    }
}
package com.markrai.waqt.adapter;

import android.media.MediaPlayer;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.markrai.waqt.R;
import com.markrai.waqt.activity.MainActivity;
import com.markrai.waqt.model.Task;
import com.markrai.waqt.util.TaskUtils;


class TaskViewHolder extends RecyclerView.ViewHolder {
    EditText editTextTask;
    Spinner spinnerTimeBurden;
    CheckBox checkBoxTask;
    ImageView dragHandle;
    ImageView imageViewTask;
    ImageView playIcon;
    TaskAdapter.CustomTextWatcher customTextWatcher;
    LinearLayout container;
    private CountDownTimer countDownTimer;
    private long timeRemaining;
    private boolean isPaused = false;
    private Task task;  // Reference to the current task
    TextView textViewTimer;
    private TaskAdapter taskAdapter;  // Reference to the adapter
    private MainActivity.OnTimerStateChangeListener timerStateChangeListener;
    private MediaPlayer mediaPlayer; // MediaPlayer for beep sound


    public TaskViewHolder(@NonNull View itemView, TaskAdapter.CustomTextWatcher customTextWatcher, TaskAdapter taskAdapter) {
        super(itemView);
        editTextTask = itemView.findViewById(R.id.editTextTask);
        spinnerTimeBurden = itemView.findViewById(R.id.spinnerTimeBurden);
        checkBoxTask = itemView.findViewById(R.id.checkBoxTask);
        dragHandle = itemView.findViewById(R.id.dragHandle);
        imageViewTask = itemView.findViewById(R.id.imageViewTask);
        playIcon = itemView.findViewById(R.id.playIcon);
        textViewTimer = itemView.findViewById(R.id.textViewTimer);
        this.customTextWatcher = customTextWatcher;
        this.taskAdapter = taskAdapter;
        this.customTextWatcher.setEditTexts(editTextTask);

        // Add long-press listeners to stop the timer
        View.OnLongClickListener stopTimerListener = v -> {
            stopTimer();
            return true;
        };

        playIcon.setOnLongClickListener(stopTimerListener);
        textViewTimer.setOnLongClickListener(stopTimerListener);
    }

    void cancelCountdownTimer() {
        if (countDownTimer != null) {
            countDownTimer.cancel();
            countDownTimer = null;
        }
    }

    void stopTimer() {
        cancelCountdownTimer();
        // Reset UI elements
        spinnerTimeBurden.setEnabled(true);
        spinnerTimeBurden.setAlpha(1.0f);
        textViewTimer.setVisibility(View.GONE);
        stopBlinking();
        playIcon.setVisibility(View.GONE);
        spinnerTimeBurden.setVisibility(View.VISIBLE);  // Show the spinner again
        task.setCountdownActive(false);
        taskAdapter.clearActiveTask();
        Toast.makeText(taskAdapter.context, "Timer stopped", Toast.LENGTH_SHORT).show();
    }


    void setTask(Task task) {
        this.task = task;
    }

    void startCountdownTimer(long millisInFuture, Runnable onFinish, ArrayAdapter<String> spinnerAdapter) {
        cancelCountdownTimer();

        if (timerStateChangeListener != null) {
            timerStateChangeListener.onTimerStarted();
        }

        // Save the original time burden before changing it
        if (task.getOriginalTimeBurden() == null) {
            task.setOriginalTimeBurden(task.getTimeBurden());
        }

        timeRemaining = millisInFuture;
        task.setRemainingTime(timeRemaining);
        task.setCountdownActive(true);
        isPaused = false;
        task.setPaused(isPaused);
        playIcon.setImageResource(R.drawable.ic_play_arrow_black_24dp);
        playIcon.setVisibility(View.VISIBLE);

        new Handler(Looper.getMainLooper()).post(() -> {
            textViewTimer.setVisibility(View.VISIBLE);  // Ensure the timer TextView is visible
            spinnerTimeBurden.setVisibility(View.INVISIBLE);  // Hide the spinner
        });

        countDownTimer = createCountDownTimer(timeRemaining, onFinish, spinnerAdapter);
        countDownTimer.start();

        playIcon.setOnClickListener(v -> {
            if (isPaused) {
                resumeCountdownTimer(onFinish, spinnerAdapter);
                playIcon.setImageResource(R.drawable.ic_play_arrow_black_24dp);
            } else {
                pauseCountdownTimer();
            }
        });
    }

    private void pauseCountdownTimer() {
        if (countDownTimer != null) {
            countDownTimer.cancel();
        }
        isPaused = true;
        task.setPaused(isPaused);
        playIcon.setImageResource(R.drawable.ic_pause_black_24dp);
        startBlinking();  // Start blinking animation when paused
    }

    private void resumeCountdownTimer(Runnable onFinish, ArrayAdapter<String> spinnerAdapter) {
        stopBlinking();  // Stop blinking animation when resumed
        isPaused = false;
        task.setPaused(isPaused);
        playIcon.setImageResource(R.drawable.ic_pause_black_24dp);

        countDownTimer = createCountDownTimer(timeRemaining, () -> {
            int originalTimeBurden = TaskUtils.parseTime(task.getOriginalTimeBurden());
            taskAdapter.totalTimeBurden -= originalTimeBurden;
            taskAdapter.totalTimeBurdenListener.onTotalTimeBurdenUpdated(TaskUtils.formatTime(taskAdapter.totalTimeBurden), timeRemaining);

            task.setTimeBurden("0m");
            task.setOriginalTimeBurden(null);

            spinnerTimeBurden.setAdapter(spinnerAdapter);
            spinnerTimeBurden.setSelection(spinnerAdapter.getPosition("0m"));
            spinnerTimeBurden.setEnabled(true);

            onFinish.run();
        }, spinnerAdapter);

        countDownTimer.start();
    }

    void startBlinking() {
        // Load the blink animation and start it on the playIcon
        Animation blinkAnimation = AnimationUtils.loadAnimation(itemView.getContext(), R.anim.blink);
        playIcon.startAnimation(blinkAnimation);
    }

    void stopBlinking() {
        // Clear the blinking animation
        playIcon.clearAnimation();
    }

    public void setTimerStateChangeListener(MainActivity.OnTimerStateChangeListener listener) {
        this.timerStateChangeListener = listener;
    }

    private CountDownTimer createCountDownTimer(long millisInFuture, Runnable onFinish, ArrayAdapter<String> spinnerAdapter) {
        return new CountDownTimer(millisInFuture, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                timeRemaining = millisUntilFinished;
                long minutesRemaining = millisUntilFinished / 1000 / 60;
                long secondsRemaining = (millisUntilFinished / 1000) % 60;

                Log.d("TaskAdapter", "Time left: " + minutesRemaining + "m " + secondsRemaining + "s");

                new Handler(Looper.getMainLooper()).post(() -> {
                    textViewTimer.setText(minutesRemaining + "m " + secondsRemaining + "s");
                });
            }

            @Override
            public void onFinish() {
                Log.d("TaskAdapter", "Countdown timer finished for task at position " + getAdapterPosition());

                new Handler(Looper.getMainLooper()).post(() -> {
                    if (task != null) {
                        int originalTimeBurden = TaskUtils.parseTime(task.getOriginalTimeBurden());
                        taskAdapter.totalTimeBurden -= originalTimeBurden;

                        taskAdapter.totalTimeBurdenListener.onTotalTimeBurdenUpdated(
                                TaskUtils.formatTime(taskAdapter.totalTimeBurden),
                                taskAdapter.remainingTime
                        );

                        task.setTimeBurden("0m");
                        task.setOriginalTimeBurden(null);
                        task.setCountdownActive(false);

                        playIcon.setVisibility(View.GONE);
                        stopBlinking();

                        spinnerTimeBurden.setAdapter(spinnerAdapter);
                        spinnerTimeBurden.setSelection(spinnerAdapter.getPosition("0m"));
                        spinnerTimeBurden.setEnabled(true);
                        textViewTimer.setVisibility(View.GONE);
                        spinnerTimeBurden.setVisibility(View.VISIBLE);

                        playDoubleBeep();
                        onFinish.run();
                    }
                });
            }
        };
    }

    private void playDoubleBeep() {
        if (mediaPlayer == null) {
            mediaPlayer = MediaPlayer.create(itemView.getContext(), R.raw.doublebeep);
        }

        if (mediaPlayer != null) {
            mediaPlayer.setOnCompletionListener(mp -> {
                mp.release(); // Release the MediaPlayer resources
                mediaPlayer = null; // Set the mediaPlayer to null to prevent replaying
            });
            mediaPlayer.start(); // Start the beep sound
        }
    }

    @Override
    protected void finalize() throws Throwable {
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
        super.finalize();
    }
}