/**
 * This file is part of the Meeds project (https://meeds.io/).
 * Copyright (C) 2022 Meeds Association
 * contact@meeds.io
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package org.exoplatform.task.storage;

import org.exoplatform.commons.utils.ListAccess;
import org.exoplatform.task.dao.OrderBy;
import org.exoplatform.task.dao.TaskQuery;
import org.exoplatform.task.domain.ChangeLog;
import org.exoplatform.task.domain.Status;
import org.exoplatform.task.domain.Task;
import org.exoplatform.task.dto.ChangeLogEntry;
import org.exoplatform.task.dto.LabelDto;
import org.exoplatform.task.dto.TaskDto;
import org.exoplatform.task.exception.EntityNotFoundException;

import java.util.List;
import java.util.Set;

public interface TaskStorage {

    /**
     * Find task by its id
     *
     * @param id the given id.
     * @return {@link TaskDto}
     */
    TaskDto getTaskById(long id);

    /**
     * Create a new task.
     *
     * @param task the given task
     * @return {@link TaskDto}
     */
    TaskDto createTask(TaskDto task);

    /**
     * Update the provided task.
     *
     * @param task the given task.
     * @return {@link TaskDto}
     */
    TaskDto update(TaskDto task);

    /**
     * Delete the provided task.
     *
     * @param task the provided task.
     */
    void delete(TaskDto task);

    List<TaskDto> findTasksByLabel(LabelDto label,
                                   List<Long> projectIds,
                                   String username,
                                   OrderBy orderBy,
                                   int offset,
                                   int limit) throws Exception;

    int countTasksByLabel(LabelDto label, List<Long> projectIds, String username, OrderBy orderBy) throws Exception;

    List<TaskDto> findByUser(String user);

    List<TaskDto> findTasks(TaskQuery query, int offset, int limit) throws Exception;

    int countTasks(TaskQuery query) throws Exception;

    <T> List<T> selectTaskField(TaskQuery query, String fieldName);

    TaskDto findTaskByActivityId(String activityId);

    void updateStatus(Status stOld, Status stNew);

    void updateTaskOrder(long currentTaskId, Status newStatus, long[] orders);

    Set<String> getCoworker(long taskid);

    TaskDto getTaskWithCoworkers(long id);

    List<TaskDto> getUncompletedTasks(String user, int limit);

    List<TaskDto> getAssignedTasks(String user, int limit);

    Long countAssignedTasks(String user);

    List<TaskDto> getWatchedTasks(String user, int limit);

    Long countUncompletedTasks(String user);

    Long countWatchedTasks(String user);

    List<TaskDto> getCollaboratedTasks(String user, int limit);

    Long countCollaboratedTasks(String user);

    List<TaskDto> getIncomingTasks(String user, int offset, int limit) throws Exception;

    int countIncomingTasks(String user) throws Exception;

    List<TaskDto> getOverdueTasks(String user, int limit);

    Long countOverdueTasks(String user);

    void addWatcherToTask(String username, TaskDto task) throws Exception;

    void deleteWatcherOfTask(String username, TaskDto task) throws Exception;

    Set<String> getWatchersOfTask(TaskDto task);

    /**
     * Find tasks assigned to a user using a term to find in title or description of
     * the task
     *
     * @param user  username
     * @param memberships memberships
     * @param query term to search in title or description
     * @param limit term to limit results.
     * @return {@link List} of {@link TaskDto}
     */
    List<TaskDto> findTasks(String user, List<String> memberships, String query, int limit);

    /**
     * Count tasks assigned to a user using a search term to find in title or
     * description of the task
     *
     * @param user  username
     * @param query term to search in title or description
     * @return tasks count
     */
    long countTasks(String user, String query, List<String> memberships);

    /**
     * Create a log associated with a task with given <code>changeLogEntry</code>.
     *
     * @param changeLogEntry changeLogEntry
     * @return Create a log associated
     * @throws EntityNotFoundException when user is not authorized to add taskLog.
     */
    ChangeLogEntry addTaskLog(ChangeLogEntry changeLogEntry) throws EntityNotFoundException;

    List<ChangeLogEntry> getTaskLogs(long taskId, int offset, int limit) throws Exception;

    List<Object[]> countTaskStatusByProject(long projectId);

    /**
     * Retrieves a paginated list of all task IDs.
     *
     * @param offset the starting position of the first result
     * @param limit  the maximum number of results to retrieve
     * @return a list of task IDs
     */
    List<Long> getAllIds(int offset, int limit);
}
