/*
 * 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.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;

import com.box.sdk.BoxAPIConnection;
import com.box.sdk.BoxAPIException;
import com.box.sdk.BoxFolder;
import com.box.sdk.BoxItem;
import com.box.sdk.BoxSharedLink;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Box Folders Manager
 * 
 * <p>
 * Provides operations to manage Box folders.
 * 
 * 
 *
 */
public class BoxFoldersManager {

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

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

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

    /**
     * Return the root folder of authenticated user.
     * 
     * @return The root folder of authenticated user.
     */
    public BoxFolder getRootFolder() {
        try {
            LOG.debug("Getting root folder");
            return BoxFolder.getRootFolder(boxConnection);
        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }

    /**
     * Return the Box folder referenced by <code>path</code>.
     * 
     * @param path
     *            - Sequence of Box folder names from root folder to returned
     *            folder.
     * 
     * @return The Box folder referenced by <code>path</code> or
     *         <code>null</code> if folder is not found.
     */
    public BoxFolder getFolder(String... path) {
        try {
            LOG.debug("Getting folder at path={}", Arrays.toString(path));

            BoxFolder folder = BoxFolder.getRootFolder(boxConnection);
            if (path == null || path.length == 0) {
                // Return root folder if path is null or empty.
                return folder;
            }

            searchPath: for (int folderIndex = 0; folderIndex < path.length; folderIndex++) {
                for (BoxItem.Info itemInfo : folder) {
                    if (itemInfo instanceof BoxFolder.Info && itemInfo.getName().equals(path[folderIndex])) {
                        folder = (BoxFolder) itemInfo.getResource();
                        continue searchPath;
                    }
                }
                // Failed to find named folder in path: return null
                return null;
            }
            return folder;
        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }

    /**
     * Returns a specific range of child items in folder and specifies which
     * fields of each item to retrieve.
     * 
     * @param folderId
     *            - the id of folder.
     * @param offset
     *            - the index of first child item to retrieve; if
     *            <code>null</code> all child items are retrieved.
     * @param limit
     *            - the maximum number of children to retrieve after the offset;
     *            if <code>null</code> all child items are retrieved.
     * @param fields
     *            - the item fields to retrieve for each child item; if
     *            <code>null</code> all item fields are retrieved.
     * @return The Items in folder
     */
    public Collection<BoxItem.Info> getFolderItems(String folderId, Long offset, Long limit, String... fields) {
        try {
            LOG.debug("Getting folder items in folder(id=" + folderId + ") at offset=" + offset + " and limit=" + limit
                    + " with fields=" + Arrays.toString(fields));
            if (folderId == null) {
                throw new IllegalArgumentException("Parameter 'folderId' can not be null");
            }
            BoxFolder folder = new BoxFolder(boxConnection, folderId);
            if (fields == null) {
                fields = new String[0];
            }
            if (offset != null && limit != null) {
                return folder.getChildrenRange(offset, limit, fields);
            } else {
                Collection<BoxItem.Info> folderItems = new ArrayList<>();
                Iterable<BoxItem.Info> iterable;
                if (fields.length > 0) {
                    iterable = folder.getChildren(fields);
                } else {
                    iterable = folder.getChildren();
                }
                for (BoxItem.Info itemInfo : iterable) {
                    folderItems.add(itemInfo);
                }

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

    /**
     * Create a folder in parent folder with given <code>parentFolderId</code>.
     * 
     * @param parentFolderId
     *            - the id of parent folder.
     * @param folderName
     *            the name of created folder.
     * @return The created folder.
     */
    public BoxFolder createFolder(String parentFolderId, String folderName) {
        try {
            LOG.debug("Creating folder with name '" + folderName + "' in parent_folder(id=" + parentFolderId + ")");
            if (parentFolderId == null) {
                throw new IllegalArgumentException("Parameter 'parentFolderId' can not be null");
            }
            if (folderName == null) {
                throw new IllegalArgumentException("Paramerer 'folderName' can not be null");
            }
            BoxFolder parentFolder = new BoxFolder(boxConnection, parentFolderId);
            return parentFolder.createFolder(folderName).getResource();
        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }

    /**
     * Create a folder specified by path from parent folder with given <code>parentFolderId</code>,
     * creating intermediate directories as required.
     *
     * @param parentFolderId
     *            - the id of parent folder.
     * @param path
     *            - Sequence of Box folder names from parent folder to returned
     *            folder.
     * @return The last folder in path, no fault will be thrown if it already exists.
     */
    public BoxFolder createFolder(String parentFolderId, String... path) {
        try {
            LOG.debug("Creating folder with path '" + Arrays.toString(path) + "' in parent_folder(id=" + parentFolderId + ")");
            if (parentFolderId == null) {
                throw new IllegalArgumentException("Parameter 'parentFolderId' can not be null");
            }
            if (path == null) {
                throw new IllegalArgumentException("Paramerer 'path' can not be null");
            }
            BoxFolder folder = new BoxFolder(boxConnection, parentFolderId);
            searchPath: for (int folderIndex = 0; folderIndex < path.length; folderIndex++) {
                for (BoxItem.Info itemInfo : folder) {
                    if (itemInfo instanceof BoxFolder.Info && itemInfo.getName().equals(path[folderIndex])) {
                        folder = (BoxFolder) itemInfo.getResource();
                        continue searchPath;
                    }
                }
                folder = folder.createFolder(path[folderIndex]).getResource();
            }
            return folder;
        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }

    /**
     * Copy folder to destination folder while optionally giving it a new name.
     * 
     * @param folderId
     *            - the id of folder to copy.
     * @param destinationFolderId
     *            - the id of the destination folder.
     * @param newName
     *            - the new name for copied folder; if <code>newName</code> is
     *            <code>null</code>, the copied folder has same name as the
     *            original.
     * @return The copied folder.
     */
    public BoxFolder copyFolder(String folderId, String destinationFolderId, String newName) {
        try {
            LOG.debug("Copying folder(id=" + folderId + ") to destination_folder(id=" + destinationFolderId + ")"
                    + (newName == null ? "" : " with new name '" + newName + "'"));
            if (folderId == null) {
                throw new IllegalArgumentException("Parameter 'folderId' can not be null");
            }
            if (destinationFolderId == null) {
                throw new IllegalArgumentException("Parameter 'destinationFolderId' can not be null");
            }
            BoxFolder folderToCopy = new BoxFolder(boxConnection, folderId);
            BoxFolder destinationFolder = new BoxFolder(boxConnection, destinationFolderId);
            if (newName == null) {
                return folderToCopy.copy(destinationFolder).getResource();
            } else {
                return folderToCopy.copy(destinationFolder, newName).getResource();
            }
        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }

    /**
     * Move folder to destination folder while optionally giving it a new name.
     * 
     * @param folderId
     *            - the id of folder to move.
     * @param destinationFolderId
     *            - the id of the destination folder.
     * @param newName
     *            - the new name of moved folder; if <code>newName</code> is
     *            <code>null</code>, the moved folder has same name as the
     *            original.
     * @return The moved folder.
     */
    public BoxFolder moveFolder(String folderId, String destinationFolderId, String newName) {
        try {
            LOG.debug("Moving folder(id=" + folderId + ") to destination_folder(id=" + destinationFolderId + ")"
                    + (newName == null ? "" : " with new name '" + newName + "'"));
            if (folderId == null) {
                throw new IllegalArgumentException("Parameter 'folderId' can not be null");
            }
            if (destinationFolderId == null) {
                throw new IllegalArgumentException("Parameter 'destinationFolderId' can not be null");
            }
            BoxFolder folderToMove = new BoxFolder(boxConnection, folderId);
            BoxFolder destinationFolder = new BoxFolder(boxConnection, destinationFolderId);
            if (newName == null) {
                return (BoxFolder) folderToMove.move(destinationFolder).getResource();
            } else {
                return (BoxFolder) folderToMove.move(destinationFolder, newName).getResource();
            }
        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }

    /**
     * Rename folder giving it the name <code>newName</code>
     * 
     * @param folderId
     *            - the id of folder to rename.
     * @param newFolderName
     *            - the new name of folder.
     * @return The renamed folder.
     */
    public BoxFolder renameFolder(String folderId, String newFolderName) {
        try {
            LOG.debug("Renaming folder(id=" + folderId + ") to '" + newFolderName + "'");
            if (folderId == null) {
                throw new IllegalArgumentException("Parameter 'folderId' can not be null");
            }
            if (newFolderName == null) {
                throw new IllegalArgumentException("Parameter 'newFolderName' can not be null");
            }
            BoxFolder folderToRename = new BoxFolder(boxConnection, folderId);
            folderToRename.rename(newFolderName);
            return folderToRename;
        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }

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

    /**
     * Get folder information.
     * 
     * @param folderId
     *            - the id of folder.
     * @param fields
     *            - the information fields to retrieve; if <code>null</code> all
     *            information fields are retrieved.
     * @return The folder information.
     */
    public BoxFolder.Info getFolderInfo(String folderId, String... fields) {
        try {
            LOG.debug("Getting info for folder(id={})", folderId);
            if (folderId == null) {
                throw new IllegalArgumentException("Parameter 'folderId' can not be null");
            }

            BoxFolder folder = new BoxFolder(boxConnection, folderId);

            if (fields == null || fields.length == 0) {
                return folder.getInfo();
            } else {
                return folder.getInfo(fields);
            }
        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }

    /**
     * Update folder information.
     * 
     * @param folderId
     *            - the id of folder to update.
     * @param info
     *            - the updated information
     * @return The updated folder.
     */
    public BoxFolder updateFolderInfo(String folderId, BoxFolder.Info info) {
        try {
            LOG.debug("Updating info for folder(id={})", folderId);
            if (folderId == null) {
                throw new IllegalArgumentException("Parameter 'folderId' can not be null");
            }
            if (info == null) {
                throw new IllegalArgumentException("Parameter 'info' can not be null");
            }
            BoxFolder folder = new BoxFolder(boxConnection, folderId);
            folder.updateInfo(info);
            return folder;
        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }

    /**
     * Create a shared link to folder.
     * 
     * @param folderId
     *            - the id of folder to create shared link on.
     * @param access
     *            - the access level of the shared link.
     * @param unshareDate
     *            - the date and time at which time the created shared link will
     *            expire; if <code>unsharedDate</code> is <code>null</code> then
     *            a non-expiring link is created.
     * @param permissions
     *            - the permissions of the created link; if
     *            <code>permissions</code> is <code>null</code> then the created
     *            shared link is create with default permissions.
     * @return The created shared link.
     */
    public BoxSharedLink createFolderSharedLink(String folderId, BoxSharedLink.Access access, Date unshareDate,
            BoxSharedLink.Permissions permissions) {
        try {
            LOG.debug("Creating shared link for folder(id=" + folderId + ") with access=" + access
                    + (unshareDate == null ? ""
                            : " unsharedDate=" + DateFormat.getDateTimeInstance().format(unshareDate)
                                    + " permissions=" + permissions));

            if (folderId == null) {
                throw new IllegalArgumentException("Parameter 'folderId' can not be null");
            }
            if (access == null) {
                throw new IllegalArgumentException("Parameter 'access' can not be null");
            }

            BoxFolder folder = new BoxFolder(boxConnection, folderId);
            return folder.createSharedLink(access, unshareDate, permissions);
        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }

}
