/**
 * 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.
 */

/*
 * Camel Api Route test generated by camel-component-util-maven-plugin
 * Generated on: Tue Jun 24 22:42:08 PDT 2014
 */
package org.apache.camel.component.box;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import com.box.boxjavalibv2.dao.BoxFile;
import com.box.boxjavalibv2.dao.BoxPreview;
import com.box.boxjavalibv2.dao.BoxSharedLinkAccess;
import com.box.boxjavalibv2.exceptions.BoxServerException;
import com.box.boxjavalibv2.filetransfer.IFileTransferListener;
import com.box.boxjavalibv2.jsonentities.BoxSharedLinkRequestEntity;
import com.box.boxjavalibv2.requests.requestobjects.BoxFileRequestObject;
import com.box.boxjavalibv2.requests.requestobjects.BoxImageRequestObject;
import com.box.boxjavalibv2.requests.requestobjects.BoxItemCopyRequestObject;
import com.box.boxjavalibv2.requests.requestobjects.BoxSharedLinkRequestObject;
import com.box.restclientv2.requestsbase.BoxFileUploadRequestObject;
import org.apache.camel.CamelExecutionException;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.box.internal.BoxApiName;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Test class for com.box.boxjavalibv2.resourcemanagers.IBoxFilesManager APIs.
 */
public class IBoxFilesManagerIntegrationTest extends AbstractBoxTestSupport {

    private static final Logger LOG = LoggerFactory.getLogger(IBoxFilesManagerIntegrationTest.class);
    private static final String PATH_PREFIX = BoxApiName.FILES.getName();
    private static final BoxImageRequestObject BOX_IMAGE_REQUEST_OBJECT = BoxImageRequestObject.previewRequestObject();
    private static final String PNG_EXTENSION = "png";
    private static final String TEST_UPLOAD_FILE = "/log4j.properties";
    private static final String PREVIEW_UNAVAILABLE = "Requested preview unavailable";

    public BoxFile copyFile() throws Exception {
        final Map<String, Object> headers = new HashMap<String, Object>();
        // parameter type is String
        headers.put("CamelBox.fileId", testFileId);
        // parameter type is com.box.boxjavalibv2.requests.requestobjects.BoxItemCopyRequestObject
        final BoxItemCopyRequestObject requestObject =
                BoxItemCopyRequestObject.copyItemRequestObject("0");
        requestObject.setName(CAMEL_TEST_FILE);
        headers.put("CamelBox.itemCopyRequest", requestObject);
        BoxFile result = requestBodyAndHeaders("direct://COPYFILE", null, headers);

        assertNotNull("copyFile result", result);
        LOG.debug("copyFile: " + result);

        return result;
    }

    @Test
    public void testCreateSharedLink() throws Exception {
        final BoxFile boxFile = copyFile();

        try {
            final Map<String, Object> headers = new HashMap<String, Object>();
            // parameter type is String
            headers.put("CamelBox.fileId", boxFile.getId());
            // parameter type is com.box.boxjavalibv2.requests.requestobjects.BoxSharedLinkRequestObject
            final BoxSharedLinkRequestEntity sharedLink = new BoxSharedLinkRequestEntity(BoxSharedLinkAccess.OPEN);
            final BoxSharedLinkRequestObject requestObject =
                    BoxSharedLinkRequestObject.createSharedLinkRequestObject(sharedLink);
            headers.put("CamelBox.sharedLinkRequest", requestObject);

            BoxFile result = requestBodyAndHeaders("direct://CREATESHAREDLINK", null, headers);

            assertNotNull("createSharedLink result", result);
            LOG.debug("createSharedLink: " + result);
        } finally {
            deleteFile(boxFile.getId());
        }
    }

    public void deleteFile(String fileId) throws Exception {
        final Map<String, Object> headers = new HashMap<String, Object>();
        // parameter type is String
        headers.put("CamelBox.fileId", fileId);
        // parameter type is com.box.restclientv2.requestsbase.BoxDefaultRequestObject
        headers.put("CamelBox.defaultRequest", null);
        requestBodyAndHeaders("direct://DELETEFILE", null, headers);
    }

    @Test
    public void testDownloadFile() throws Exception {
        final Map<String, Object> headers = new HashMap<String, Object>();
        // parameter type is String
        headers.put("CamelBox.fileId", testFileId);
        // parameter type is com.box.restclientv2.requestsbase.BoxDefaultRequestObject
//        headers.put("CamelBox.defaultRequest", null);
        InputStream result = requestBodyAndHeaders("direct://DOWNLOADFILE", null, headers);

        assertNotNull("downloadFile result", result);
        LOG.debug("downloadFile: " + result);
        result.close();
    }

    @Test
    public void testDownloadFile1() throws Exception {
        final Map<String, Object> headers = new HashMap<String, Object>();
        // parameter type is String
        headers.put("CamelBox.fileId", testFileId);
        // parameter type is java.io.File
        final File tempFile = File.createTempFile("CamelTest", "download");
        headers.put("CamelBox.destination", tempFile);
        // parameter type is com.box.boxjavalibv2.filetransfer.IFileTransferListener
        final FileTransferListener fileTransferListener = new FileTransferListener();
        headers.put("CamelBox.listener", fileTransferListener);
        // parameter type is com.box.restclientv2.requestsbase.BoxDefaultRequestObject
//        headers.put("CamelBox.defaultRequest", null);

        requestBodyAndHeaders("direct://DOWNLOADFILE_1", null, headers);

        assertTransferSuccess(fileTransferListener);
        assertTrue("downloadFile file", tempFile.exists());
    }

    private void assertTransferSuccess(FileTransferListener fileTransferListener) throws InterruptedException {
        long bytesTransferred;
        do {
            bytesTransferred = fileTransferListener.getBytesTransferred();
            Thread.sleep(2000);
        } while (fileTransferListener.getBytesTransferred() != bytesTransferred);
//        assertEquals("downloadFile status", "success", fileTransferListener.getStatus());
        assertNull("downloadFile exception", fileTransferListener.getException());
    }

    @Test
    public void testDownloadFile2() throws Exception {
        final Map<String, Object> headers = new HashMap<String, Object>();
        // parameter type is String
        headers.put("CamelBox.fileId", testFileId);
        // parameter type is java.io.OutputStream[]
        final OutputStream[] outputStreams = new OutputStream[]{new ByteArrayOutputStream()};
        headers.put("CamelBox.outputStreams", outputStreams);
        // parameter type is com.box.boxjavalibv2.filetransfer.IFileTransferListener
        final FileTransferListener fileTransferListener = new FileTransferListener();
        headers.put("CamelBox.listener", fileTransferListener);
        // parameter type is com.box.restclientv2.requestsbase.BoxDefaultRequestObject
//        headers.put("CamelBox.defaultRequest", null);

        requestBodyAndHeaders("direct://DOWNLOADFILE_2", null, headers);

        assertTransferSuccess(fileTransferListener);
        assertNotNull("downloadFile OutputStream", outputStreams[0].toString());
    }

    @Test
    public void testDownloadThumbnail() throws Exception {
        final Map<String, Object> headers = new HashMap<String, Object>();
        // parameter type is String
        headers.put("CamelBox.fileId", testFileId);
        // parameter type is String
        headers.put("CamelBox.extension", PNG_EXTENSION);
        // parameter type is com.box.boxjavalibv2.requests.requestobjects.BoxImageRequestObject
        headers.put("CamelBox.imageRequest", BOX_IMAGE_REQUEST_OBJECT);

        InputStream result = requestBodyAndHeaders("direct://DOWNLOADTHUMBNAIL", null, headers);

        assertNotNull("downloadThumbnail result", result);
        LOG.debug("downloadThumbnail: " + result);
        result.close();
    }

    @Test
    public void testGetFile() throws Exception {
        final Map<String, Object> headers = new HashMap<String, Object>();
        // parameter type is String
        headers.put("CamelBox.fileId", testFileId);
        // parameter type is com.box.restclientv2.requestsbase.BoxDefaultRequestObject
//        headers.put("CamelBox.defaultRequest", null);

        BoxFile result = requestBodyAndHeaders("direct://GETFILE", null, headers);

        assertNotNull("getFile result", result);
        LOG.debug("getFile: " + result);
    }

    @Test
    public void testGetFileComments() throws Exception {
        final Map<String, Object> headers = new HashMap<String, Object>();
        // parameter type is String
        headers.put("CamelBox.fileId", testFileId);
        // parameter type is com.box.restclientv2.requestsbase.BoxDefaultRequestObject
//        headers.put("CamelBox.defaultRequest", null);

        com.box.boxjavalibv2.dao.BoxCollection result = requestBodyAndHeaders("direct://GETFILECOMMENTS", null, headers);

        assertNotNull("getFileComments result", result);
        LOG.debug("getFileComments: " + result);
    }

    @Test
    public void testGetFileVersions() throws Exception {
        final Map<String, Object> headers = new HashMap<String, Object>();
        // parameter type is String
        headers.put("CamelBox.fileId", testFileId);
        // parameter type is com.box.restclientv2.requestsbase.BoxDefaultRequestObject
//        headers.put("CamelBox.defaultRequest", null);

        java.util.List result = requestBodyAndHeaders("direct://GETFILEVERSIONS", null, headers);

        assertNotNull("getFileVersions result", result);
        LOG.debug("getFileVersions: " + result);
    }

    @Test
    public void testGetPreview() throws Exception {
        final Map<String, Object> headers = new HashMap<String, Object>();
        // parameter type is String
        headers.put("CamelBox.fileId", testFileId);
        // parameter type is String
        headers.put("CamelBox.extension", PNG_EXTENSION);
        // parameter type is com.box.boxjavalibv2.requests.requestobjects.BoxImageRequestObject
        headers.put("CamelBox.imageRequest", BOX_IMAGE_REQUEST_OBJECT);
        com.box.boxjavalibv2.dao.BoxPreview result = null;
        try {
            result = requestBodyAndHeaders("direct://GETPREVIEW", null, headers);
        } catch (CamelExecutionException e) {
            boolean ignore = false;
            if (e.getCause().getCause() instanceof BoxServerException) {
                BoxServerException exception = (BoxServerException) e.getCause().getCause();
                if (PREVIEW_UNAVAILABLE.equals(exception.getMessage())) {
                    // ignore unavailable preview errors
                    result = new BoxPreview();
                    ignore = true;
                }
            }
            if (!ignore) {
                throw e;
            }
        }

        assertNotNull("getPreview result", result);
        LOG.debug("getPreview: " + result);
    }

    @Test
    public void testGetThumbnail() throws Exception {
        final Map<String, Object> headers = new HashMap<String, Object>();
        // parameter type is String
        headers.put("CamelBox.fileId", testFileId);
        // parameter type is String
        headers.put("CamelBox.extension", PNG_EXTENSION);
        // parameter type is com.box.boxjavalibv2.requests.requestobjects.BoxImageRequestObject
        headers.put("CamelBox.imageRequest", BOX_IMAGE_REQUEST_OBJECT);
        com.box.boxjavalibv2.dao.BoxThumbnail result = requestBodyAndHeaders("direct://GETTHUMBNAIL", null, headers);

        LOG.debug("getThumbnail: " + result);
    }

    @Test
    public void testUpdateFileInfo() throws Exception {
        final Map<String, Object> headers = new HashMap<String, Object>();
        // parameter type is String
        headers.put("CamelBox.fileId", testFileId);
        // parameter type is com.box.boxjavalibv2.requests.requestobjects.BoxFileRequestObject
        final BoxFileRequestObject requestObject = BoxFileRequestObject.getRequestObject();
        requestObject.setTags(new String[]{CAMEL_TEST_TAG});
        headers.put("CamelBox.fileRequest", requestObject);
        BoxFile result = requestBodyAndHeaders("direct://UPDATEFILEINFO", null, headers);

        assertNotNull("updateFileInfo result", result);
        LOG.debug("updateFileInfo: " + result);
    }

    public BoxFile uploadFile() throws Exception {
        // using com.box.restclientv2.requestsbase.BoxFileUploadRequestObject message body for single parameter "fileUploadRequest"
        final BoxFileUploadRequestObject requestObject =
                BoxFileUploadRequestObject.uploadFileRequestObject("0", CAMEL_TEST_FILE,
                        getClass().getResourceAsStream(TEST_UPLOAD_FILE));
        final FileTransferListener fileTransferListener = new FileTransferListener();
        requestObject.setListener(fileTransferListener);

        BoxFile result = requestBody("direct://UPLOADFILE", requestObject);

        assertTransferSuccess(fileTransferListener);
        assertNotNull("uploadFile result", result);
        LOG.debug("uploadFile: " + result);

        // wait a moment for the file to show up in subsequent calls
        Thread.sleep(2000);
        return result;
    }

    @Test
    public void testUploadNewVersion() throws Exception {
        final BoxFile boxFile = uploadFile();

        try {
            final Map<String, Object> headers = new HashMap<String, Object>();
            // parameter type is String
            headers.put("CamelBox.fileId", boxFile.getId());
            // parameter type is com.box.restclientv2.requestsbase.BoxFileUploadRequestObject
            final BoxFileUploadRequestObject requestObject =
                    BoxFileUploadRequestObject.uploadNewVersionRequestObject(CAMEL_TEST_FILE,
                            getClass().getResourceAsStream(TEST_UPLOAD_FILE));
            final FileTransferListener fileTransferListener = new FileTransferListener();
            requestObject.setListener(fileTransferListener);

            headers.put("CamelBox.fileUploadRequest", requestObject);
            BoxFile result = requestBodyAndHeaders("direct://UPLOADNEWVERSION", null, headers);

            assertTransferSuccess(fileTransferListener);
            assertNotNull("uploadNewVersion result", result);
            LOG.debug("uploadNewVersion: " + result);
        } finally {
            deleteFile(boxFile.getId());
        }
    }

    @Override
    protected RouteBuilder createRouteBuilder() throws Exception {
        return new RouteBuilder() {
            public void configure() {
                // test route for copyFile
                from("direct://COPYFILE")
                        .to("box://" + PATH_PREFIX + "/copyFile");

                // test route for createSharedLink
                from("direct://CREATESHAREDLINK")
                        .to("box://" + PATH_PREFIX + "/createSharedLink");

                // test route for deleteFile
                from("direct://DELETEFILE")
                        .to("box://" + PATH_PREFIX + "/deleteFile");

                // test route for downloadFile
                from("direct://DOWNLOADFILE")
                        .to("box://" + PATH_PREFIX + "/downloadFile");

                // test route for downloadFile
                from("direct://DOWNLOADFILE_1")
                        .to("box://" + PATH_PREFIX + "/downloadFile");

                // test route for downloadFile
                from("direct://DOWNLOADFILE_2")
                        .to("box://" + PATH_PREFIX + "/downloadFile");

                // test route for downloadThumbnail
                from("direct://DOWNLOADTHUMBNAIL")
                        .to("box://" + PATH_PREFIX + "/downloadThumbnail");

                // test route for getFile
                from("direct://GETFILE")
                        .to("box://" + PATH_PREFIX + "/getFile");

                // test route for getFileComments
                from("direct://GETFILECOMMENTS")
                        .to("box://" + PATH_PREFIX + "/getFileComments");

                // test route for getFileVersions
                from("direct://GETFILEVERSIONS")
                        .to("box://" + PATH_PREFIX + "/getFileVersions");

                // test route for getPreview
                from("direct://GETPREVIEW")
                        .to("box://" + PATH_PREFIX + "/getPreview");

                // test route for getThumbnail
                from("direct://GETTHUMBNAIL")
                        .to("box://" + PATH_PREFIX + "/getThumbnail");

                // test route for updateFileInfo
                from("direct://UPDATEFILEINFO")
                        .to("box://" + PATH_PREFIX + "/updateFileInfo");

                // test route for uploadFile
                from("direct://UPLOADFILE")
                        .to("box://" + PATH_PREFIX + "/uploadFile?inBody=fileUploadRequest");

                // test route for uploadNewVersion
                from("direct://UPLOADNEWVERSION")
                        .to("box://" + PATH_PREFIX + "/uploadNewVersion");

            }
        };
    }

    private static class FileTransferListener implements IFileTransferListener {
        private String status;
        private long bytesTransferred;
        private IOException exception;

        public String getStatus() {
            return status;
        }

        public long getBytesTransferred() {
            return bytesTransferred;
        }

        private IOException getException() {
            return exception;
        }

        @Override
        public void onComplete(String status) {
            LOG.debug("Download completed with status " + status);
            this.status = status;
        }

        @Override
        public void onCanceled() {
            LOG.debug("Download canceled");
        }

        @Override
        public void onProgress(long bytesTransferred) {
            LOG.debug("Downloaded bytes " + bytesTransferred);
            this.bytesTransferred = bytesTransferred;
        }

        @Override
        public void onIOException(IOException e) {
            LOG.debug("Download exception " + e.getMessage(), e);
            this.exception = e;
        }
    }
}
