/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.camel.component.box.api;

import java.util.Date;
import java.util.List;

import com.box.sdk.BoxAPIConnection;
import com.box.sdk.BoxAPIException;
import com.box.sdk.BoxFile;
import com.box.sdk.BoxTask;
import com.box.sdk.BoxTaskAssignment;
import com.box.sdk.BoxUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Box Tasks Manager
 * 
 * <p>
 * Provides operations to manage Box tasks.
 * 
 * 
 *
 */
public class BoxTasksManager {

    private static final Logger LOG = LoggerFactory.getLogger(BoxTasksManager.class);

    /**
     * Box connection to authenticated user account.
     */
    private BoxAPIConnection boxConnection;

    /**
     * Create tasks manager to manage the tasks of Box connection's
     * authenticated user.
     * 
     * @param boxConnection
     *            - Box connection to authenticated user account.
     */
    public BoxTasksManager(BoxAPIConnection boxConnection) {
        this.boxConnection = boxConnection;
    }

    /**
     * Get a list of any tasks on file.
     * 
     * @param fileId
     *            - the id of file.
     * @return The list of tasks on file.
     */
    public List<BoxTask.Info> getFileTasks(String fileId) {
        try {
            LOG.debug("Getting tasks of file(id={})", fileId);
            if (fileId == null) {
                throw new IllegalArgumentException("Parameter 'fileId' can not be null");
            }

            BoxFile file = new BoxFile(boxConnection, fileId);

            return file.getTasks();

        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }

    /**
     * Add task to file.
     * 
     * @param fileId
     *            - the id of file to add task to.
     * @param action
     *            - the action the task assignee will be prompted to do.
     * @param dueAt
     *            - - the day at which this task is due.
     * @param message
     *            - an optional message to include with the task.
     * @return The new task.
     */
    public BoxTask addFileTask(String fileId, BoxTask.Action action, Date dueAt, String message) {
        try {
            LOG.debug("Adding task to file(id=" + fileId + ") to '" + message + "'");
            if (fileId == null) {
                throw new IllegalArgumentException("Parameter 'fileId' can not be null");
            }
            if (action == null) {
                throw new IllegalArgumentException("Parameter 'action' can not be null");
            }
            if (dueAt == null) {
                throw new IllegalArgumentException("Parameter 'dueAt' can not be null");
            }

            BoxFile fileToAddTaskOn = new BoxFile(boxConnection, fileId);
            return fileToAddTaskOn.addTask(action, message, dueAt).getResource();
        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }

    /**
     * Delete task.
     * 
     * @param taskId
     *            - the id of task to delete.
     */
    public void deleteTask(String taskId) {
        try {
            LOG.debug("Deleting task(id={})", taskId);
            if (taskId == null) {
                throw new IllegalArgumentException("Parameter 'taskId' can not be null");
            }
            BoxTask task = new BoxTask(boxConnection, taskId);
            task.delete();
        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }

    /**
     * Get task information.
     * 
     * @param taskId
     *            - the id of task.
     * @return The task information.
     */
    public BoxTask.Info getTaskInfo(String taskId) {
        try {
            LOG.debug("Getting info for task(id={})", taskId);
            if (taskId == null) {
                throw new IllegalArgumentException("Parameter 'taskId' can not be null");
            }

            BoxTask task = new BoxTask(boxConnection, taskId);

            return task.getInfo();
        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }

    /**
     * Update task information.
     * 
     * @param taskId
     *            - the id of task.
     * @param info
     *            - the updated information
     * @return The updated task.
     */
    public BoxTask updateTaskInfo(String taskId, BoxTask.Info info) {
        try {
            LOG.debug("Updating info for task(id={})", taskId);
            if (taskId == null) {
                throw new IllegalArgumentException("Parameter 'taskId' can not be null");
            }
            if (info == null) {
                throw new IllegalArgumentException("Parameter 'info' can not be null");
            }

            BoxTask task = new BoxTask(boxConnection, taskId);
            task.updateInfo(info);

            return task;
        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }

    /**
     * Get a list of any assignments for task.
     * 
     * @param taskId
     *            - the id of task.
     * @return The list of assignments for task.
     */
    public List<BoxTaskAssignment.Info> getTaskAssignments(String taskId) {
        try {
            LOG.debug("Getting assignments for task(id={})", taskId);
            if (taskId == null) {
                throw new IllegalArgumentException("Parameter 'taskId' can not be null");
            }

            BoxTask file = new BoxTask(boxConnection, taskId);

            return file.getAssignments();

        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }

    /**
     * Add assignment for task.
     * 
     * @param taskId
     *            - the id of task to add assignment for.
     * @param assignTo
     *            - the user to assign to task.
     * @return The assigned task.
     */
    @SuppressWarnings("unused") // compiler for some reason thinks 'if (assignTo
                                // == null)' clause is dead code.
    public BoxTask addAssignmentToTask(String taskId, BoxUser assignTo) {
        try {
            LOG.debug("Assigning task(id=" + taskId + ") to user(id=" + assignTo.getID() + ")");
            if (taskId == null) {
                throw new IllegalArgumentException("Parameter 'commentId' can not be null");
            }
            if (assignTo == null) {
                throw new IllegalArgumentException("Parameter 'assignTo' can not be null");
            }

            BoxTask task = new BoxTask(boxConnection, taskId);
            task.addAssignment(assignTo);

            return task;
        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }

    /**
     * Get task assignment information.
     * 
     * @param taskAssignmentId
     *            - the id of task assignment.
     * @return The task assignment information.
     */
    public BoxTaskAssignment.Info getTaskAssignmentInfo(String taskAssignmentId) {
        try {
            LOG.debug("Getting info for task(id={})", taskAssignmentId);
            if (taskAssignmentId == null) {
                throw new IllegalArgumentException("Parameter 'taskAssignmentId' can not be null");
            }

            BoxTaskAssignment taskAssignment = new BoxTaskAssignment(boxConnection, taskAssignmentId);

            return taskAssignment.getInfo();
        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }

    // TODO Add this method when BoxTaskAssignment API fixed:
    // BoxTaskAssignment.update method currently
    // takes BoxTask.Info instead of BoxTaskAssignment.Info
    // /**
    // * Update task assignment information.
    // *
    // * @param taskAssignmentId
    // * - the id of task assignment.
    // * @param info
    // * - the updated information
    // * @return The updated task assignment.
    // */
    // public BoxTaskAssignment updateTaskAssignmentInfo(String
    // taskAssignmentId, BoxTaskAssignment.Info info) {
    // try {
    // LOG.debug("Updating info for task(id={})", taskAssignmentId);
    // if (taskAssignmentId == null) {
    // throw new IllegalArgumentException("Parameter 'taskAssignmentId' can not
    // be null");
    // }
    // if (info == null) {
    // throw new IllegalArgumentException("Parameter 'info' can not be null");
    // }
    //
    // BoxTaskAssignment taskAssignment = new BoxTaskAssignment(boxConnection,
    // taskAssignmentId);
    // taskAssignment.updateInfo(info);
    //
    // return taskAssignment;
    // } catch (BoxAPIException e) {
    // throw new RuntimeException(
    // String.format("Box API returned the error code %d\n\n%s",
    // e.getResponseCode(), e.getResponse()), e);
    // }
    // }

    /**
     * Delete task assignment.
     * 
     * @param taskAssignmentId
     *            - the id of task assignment to delete.
     */
    public void deleteTaskAssignment(String taskAssignmentId) {
        try {
            LOG.debug("Deleting task(id={})", taskAssignmentId);
            if (taskAssignmentId == null) {
                throw new IllegalArgumentException("Parameter 'taskAssignmentId' can not be null");
            }
            BoxTaskAssignment taskAssignment = new BoxTaskAssignment(boxConnection, taskAssignmentId);
            taskAssignment.delete();
        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }
}
