package com.example.todojava;

import android.app.Application;

import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MediatorLiveData;
import androidx.lifecycle.MutableLiveData;

import com.example.todojava.data.Todo;
import com.example.todojava.data.TodoDao;
import com.example.todojava.data.TodoDatabase;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TodoViewModel extends AndroidViewModel {

    public enum Filter {
        ALL, ACTIVE, DONE
    }

    private final TodoDao todoDao;
    private final ExecutorService executor;

    private final LiveData<List<Todo>> allTodos;
    private final LiveData<List<Todo>> activeTodos;
    private final LiveData<List<Todo>> completedTodos;

    private final LiveData<Integer> allCount;
    private final LiveData<Integer> activeCount;
    private final LiveData<Integer> completedCount;

    private final MutableLiveData<Filter> currentFilter = new MutableLiveData<>(Filter.ALL);
    private final MediatorLiveData<List<Todo>> filteredTodos = new MediatorLiveData<>();

    public TodoViewModel(@NonNull Application application) {
        super(application);
        TodoDatabase db = TodoDatabase.getInstance(application);
        todoDao = db.todoDao();
        executor = Executors.newSingleThreadExecutor();

        allTodos = todoDao.getAllTodos();
        activeTodos = todoDao.getActiveTodos();
        completedTodos = todoDao.getCompletedTodos();

        allCount = todoDao.getAllCount();
        activeCount = todoDao.getActiveCount();
        completedCount = todoDao.getCompletedCount();

        filteredTodos.addSource(allTodos, todos -> {
            if (currentFilter.getValue() == Filter.ALL) {
                filteredTodos.setValue(todos);
            }
        });
        filteredTodos.addSource(activeTodos, todos -> {
            if (currentFilter.getValue() == Filter.ACTIVE) {
                filteredTodos.setValue(todos);
            }
        });
        filteredTodos.addSource(completedTodos, todos -> {
            if (currentFilter.getValue() == Filter.DONE) {
                filteredTodos.setValue(todos);
            }
        });
        filteredTodos.addSource(currentFilter, filter -> {
            switch (filter) {
                case ALL:
                    filteredTodos.setValue(allTodos.getValue());
                    break;
                case ACTIVE:
                    filteredTodos.setValue(activeTodos.getValue());
                    break;
                case DONE:
                    filteredTodos.setValue(completedTodos.getValue());
                    break;
            }
        });
    }

    public LiveData<List<Todo>> getFilteredTodos() {
        return filteredTodos;
    }

    public LiveData<Integer> getAllCount() {
        return allCount;
    }

    public LiveData<Integer> getActiveCount() {
        return activeCount;
    }

    public LiveData<Integer> getCompletedCount() {
        return completedCount;
    }

    public MutableLiveData<Filter> getCurrentFilter() {
        return currentFilter;
    }

    public void setFilter(Filter filter) {
        currentFilter.setValue(filter);
    }

    public void insert(Todo todo) {
        executor.execute(() -> todoDao.insert(todo));
    }

    public void update(Todo todo) {
        executor.execute(() -> todoDao.update(todo));
    }

    public void delete(Todo todo) {
        executor.execute(() -> todoDao.delete(todo));
    }

    public void toggleCompleted(Todo todo) {
        todo.setCompleted(!todo.isCompleted());
        executor.execute(() -> todoDao.update(todo));
    }
}
