Previously, clicking on the top right countdown on my app would bring up a menu which would allow the user to select a bedtime and a wake-up time. What happened to it?

Here is my existing code:

package com.markrai.waqt.activity;

import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Build;
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.service.TimerService;
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;

    private BroadcastReceiver timerUpdateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (TimerService.ACTION_UPDATE_TIMER.equals(intent.getAction())) {
                String taskId = intent.getStringExtra(TimerService.EXTRA_TASK_ID);
                long timeRemaining = intent.getLongExtra(TimerService.EXTRA_TIME_REMAINING, 0);

                // Update the UI for the corresponding task
                taskAdapter.updateTaskTimeRemaining(taskId, timeRemaining);
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        boolean darkModeEnabled = prefs.getBoolean("dark_mode_enabled", false);

        if (darkModeEnabled) {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
        } else {
            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 = 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();
        IntentFilter filter = new IntentFilter(TimerService.ACTION_UPDATE_TIMER);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { // API level 33
            registerReceiver(timerUpdateReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
        } else {
            registerReceiver(timerUpdateReceiver, filter);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        // Unregister the receiver
        unregisterReceiver(timerUpdateReceiver);
    }

    @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.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
            int index = position - taskList.size() - 1;
            if (index >= 0 && index < deferredTaskList.size()) {
                return deferredTaskList.get(index);
            } else {
                return null;
            }
        }
        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()) {
            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 taskViewHolder = (TaskViewHolder) holder;
            Task task;
            boolean isDeferred;

            if (position < taskList.size()) {
                task = taskList.get(position);
                isDeferred = false;
            } else if (position == taskList.size()) {
                // Separator; no binding needed
                return;
            } else {
                int index = position - taskList.size() - 1;
                task = deferredTaskList.get(index);
                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());
            }

            // Update CustomTextWatcher with the current Task and EditText
            taskViewHolder.customTextWatcher.setTask(task);
            taskViewHolder.customTextWatcher.setEditTextTask(taskViewHolder.editTextTask);

            // Attach the TextWatcher and set it as a tag
            taskViewHolder.editTextTask.addTextChangedListener(taskViewHolder.customTextWatcher);
            taskViewHolder.editTextTask.setTag(taskViewHolder.customTextWatcher);
        } else if (holder instanceof SeparatorViewHolder) {
            // Handle the separator view if needed
        }
    }

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

            // Cancel the timer if it's running
            if (task.isCountdownActive()) {
                RecyclerView.ViewHolder viewHolder = ((MainActivity) context).findViewByPosition(position);
                if (viewHolder instanceof TaskViewHolder) {
                    ((TaskViewHolder) viewHolder).cancelCountdownTimer();
                }
                task.setCountdownActive(false);
                task.setPaused(false);
                task.setRemainingTime(0);
                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);

            // Insert separator when deferredTaskList becomes non-empty
            if (deferredTaskList.size() == 1) {
                notifyItemInserted(taskList.size());
            }

            // Insert the deferred task
            int insertPosition = taskList.size() + 1 + (deferredTaskList.size() - 1);
            notifyItemInserted(insertPosition);

            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 (!deferredTaskList.isEmpty()) {
            count += 1; // Always add separator if there are deferred tasks
        }
        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 int 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
            int newPosition = taskList.size() - 1;
            notifyItemInserted(newPosition);

            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();

            return newPosition; // Return the position where the task was added
        }
        return -1; // Return -1 if undefer was not possible
    }

    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);
        }
    }


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

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

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


    class CustomTextWatcher implements TextWatcher {

        private Task task;
        private EditText editTextTask;
        private final TaskAdapter adapter;

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

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

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

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

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            if (task != null && editTextTask.hasFocus()) {
                task.setTaskDescription(s.toString());
                adapter.saveTasks();
            }
        }

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

    public int updateTaskTimeRemaining(String taskId, long timeRemaining) {
        // Search active tasks
        for (int i = 0; i < taskList.size(); i++) {
            Task task = taskList.get(i);
            if (task.getId().equals(taskId)) {
                task.setRemainingTime(timeRemaining);

                if (timeRemaining == 0) {
                    // Timer finished
                    task.setCountdownActive(false);

                    // Update total time burden
                    int originalTimeBurden = TaskUtils.parseTime(task.getOriginalTimeBurden());
                    totalTimeBurden -= originalTimeBurden;
                    totalTimeBurdenListener.onTotalTimeBurdenUpdated(TaskUtils.formatTime(totalTimeBurden), remainingTime);

                    task.setTimeBurden("0m");
                    task.setOriginalTimeBurden(null);
                    currentActiveTask = null;
                }

                saveTasks();
                return i; // Return position
            }
        }
        return -1; // Task not found
    }

}


package com.markrai.waqt.adapter;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Vibrator;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;

import com.markrai.waqt.R;

public class TaskItemTouchHelperCallback extends ItemTouchHelper.Callback {

    private final TaskAdapter mAdapter;
    private final Paint mPaint;
    private final float cornerRadius = 25f; // Increase to make cornering more dramatic.
    private final Context context;
    private boolean isDeferred; // Store the deferred state
    private final int colorPrimaryLight;

    public TaskItemTouchHelperCallback(TaskAdapter adapter, Context context) {
        mAdapter = adapter;
        this.context = context;
        mPaint = new Paint();
        colorPrimaryLight = ContextCompat.getColor(context, R.color.colorPrimaryLight);
    }

    @Override
    public boolean isLongPressDragEnabled() {
        return false; // Disable long press to start drag
    }

    @Override
    public boolean isItemViewSwipeEnabled() {
        return true; // Enable swipe
    }

    @Override
    public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
        int position = viewHolder.getAdapterPosition();
        Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
        if (vibrator != null) {
            vibrator.vibrate(50); // Vibrate for 50 milliseconds
        }

        if (direction == ItemTouchHelper.RIGHT && position < mAdapter.getCurrentTaskCount()) {
            mAdapter.deferTask(position);
        } else if (direction == ItemTouchHelper.LEFT && position < mAdapter.getCurrentTaskCount()) {
            mAdapter.removeTask(position);
        } else if (direction == ItemTouchHelper.LEFT && position >= mAdapter.getCurrentTaskCount() + 1) {
            mAdapter.undeferTask(position);
        }
    }

    @Override
    public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
        int swipeFlags;
        int position = viewHolder.getAdapterPosition();
        isDeferred = position >= mAdapter.getCurrentTaskCount(); // Update the deferred state at the start of the swipe
        if (position < mAdapter.getCurrentTaskCount()) {
            swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; // Allow both left and right swipe for active tasks
        } else {
            swipeFlags = ItemTouchHelper.LEFT; // Only allow left swipe for deferred tasks
        }

        final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; // Enable drag in both directions
        return makeMovementFlags(dragFlags, swipeFlags);
    }

    @Override
    public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
        mAdapter.moveItem(viewHolder.getAdapterPosition(), target.getAdapterPosition());
        return true;
    }

    @Override
    public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder,
                            float dX, float dY, int actionState, boolean isCurrentlyActive) {

        if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
            View itemView = viewHolder.itemView;
            float itemWidth = (float) itemView.getRight() - (float) itemView.getLeft();
            float threshold = itemWidth / 3; // One-third of the item width

            if (dX < 0) { // Swiping left
                // Check if task is deferred and set the appropriate background color
                if (isDeferred) {
                    mPaint.setColor(colorPrimaryLight);
                } else {
                    mPaint.setColor(Color.BLACK);
                }

                // Set the maximum swipe distance to the threshold
                float cappedDx = Math.max(dX, -threshold);
                // Set the opacity proportional to the swipe distance up to the threshold
                int alpha = (int) Math.min(255, (Math.abs(dX) / threshold) * 255); // Maximum opacity at 100%
                mPaint.setAlpha(alpha); // Ensure alpha does not exceed 255 (100% opacity)
                RectF background = new RectF(itemView.getRight() + cappedDx, itemView.getTop(), itemView.getRight(), itemView.getBottom());
                c.drawRoundRect(background, cornerRadius, cornerRadius, mPaint);

                mPaint.setColor(Color.WHITE);
                mPaint.setAlpha(alpha);
                mPaint.setTextSize(48);
                mPaint.setTextAlign(Paint.Align.CENTER);
                float textX = background.centerX();
                float textY = background.centerY() - ((mPaint.descent() + mPaint.ascent()) / 2);
                if (isDeferred) {
                    c.drawText("Today", textX, textY, mPaint);
                } else {
                    c.drawText("Delete", textX, textY, mPaint);
                }
            } else if (dX > 0) { // Swiping right
                mPaint.setColor(Color.WHITE); // Defer Color Bar
                float cappedDx = Math.min(dX, threshold);
                int alpha = (int) Math.min(255, (Math.abs(dX) / threshold) * 255); // Maximum opacity at 100%
                mPaint.setAlpha(alpha); // Ensure alpha does not exceed 255 (100% opacity)
                RectF background = new RectF(itemView.getLeft(), itemView.getTop(), itemView.getLeft() + cappedDx, itemView.getBottom());
                c.drawRoundRect(background, cornerRadius, cornerRadius, mPaint);

                mPaint.setColor(Color.BLACK);
                mPaint.setAlpha(alpha);
                mPaint.setTextSize(48);
                mPaint.setTextAlign(Paint.Align.CENTER);
                float textX = background.centerX();
                float textY = background.centerY() - ((mPaint.descent() + mPaint.ascent()) / 2);
                c.drawText("Defer", textX, textY, mPaint);
            }

            super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);

        } else if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
            // Apply elevation and opacity effects during drag
            if (isCurrentlyActive) {
                viewHolder.itemView.setElevation(10f); // Increase elevation to give a sense of lifting
                viewHolder.itemView.setAlpha(0.8f); // Reduce opacity slightly to indicate movement
            } else {
                viewHolder.itemView.setElevation(0f); // Reset elevation when the drag is not active
                viewHolder.itemView.setAlpha(1f); // Reset opacity to fully opaque when not moving
            }

            super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
        } else {
            // Reset elevation and opacity for other actions
            viewHolder.itemView.setElevation(0f);
            viewHolder.itemView.setAlpha(1f);
            super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
        }
    }

}