import com.plumtree.remote.prc.collaboration.project.IProject;
import com.plumtree.remote.prc.collaboration.project.IProjectManager;
import com.plumtree.remote.prc.collaboration.document.*;
import com.plumtree.remote.prc.IRemoteSession;
import com.plumtree.remote.prc.RemoteSessionFactory;

import java.net.URL;
import java.io.*;

/**
 * To change this example to run on any collaboration server, be sure to change the endpointURL, username and password
 * which are all set at the beginning of the main method.
 */
public class DocumentCommandLineExample
{
    static IDocumentManager documentManager;
    static IProjectManager projectManager;

    public static void main(String[] args) throws Exception
    {
        //Change the values below to match your configuration
        URL endpointURL = new URL("http://localhost:8080/ptapi/services/QueryInterfaceAPI");
        String username = "Administrator";
        String password = "";

        //Connect to create a session & retrieve the document manager
        IRemoteSession remoteSession = RemoteSessionFactory.getExplicitLoginContext(endpointURL, username, password);
        documentManager = remoteSession.getCollaborationFactory().getDocumentManager();
        projectManager = remoteSession.getCollaborationFactory().getProjectManager();

        //Create a project to work in
        IProject exampleProject = projectManager.createProject("document example project", "example document project");
        //Store it
        exampleProject.store();

        /*** Create new objects ***/
        //Create a new folder
        IDocumentFolder newFolder = createAndInsertNewFolder(exampleProject, "example folder");

        //Create a new document
        IDocument newDocument = createAndInsertNewDocument(newFolder);

        /*** Edit the document ***/
        //Check it out for editing
        documentManager.checkOutDocument(newDocument);

        //We can query here, and get the checked out document
        IDocument[] checkedOutDocuments = findCheckedOutDocumentsInProject(exampleProject);

        //Check in a new version
        checkInNewDocumentVersion(newDocument);

        //Retrieve the content back, and store it to a file
        storeDocumentContent(newDocument);

        //Create a another folder...
        IDocumentFolder newFolder2 = createAndInsertNewFolder(exampleProject, "example folder 2");

        //Then copy the new document to it
        copyDocumentToFolder(newDocument, newFolder, newFolder2);

        //We can query here, and get the two created folders
        IDocumentFolder[] rootFolders = findFirstLevelFolders(exampleProject);

        /*** Remove the objects ***/
        //Remove the document
        documentManager.removeDocument(newDocument);
        
        //Remove the folder
        documentManager.removeDocumentFolder(newFolder);

        //Remove the main project (which removes all contained objects)
        projectManager.removeProject(exampleProject);
    }

    public static IDocumentFolder[] findFirstLevelFolders(IProject project) throws Exception
    {
        //Create the new query filter
        IDocumentFolderFilter filter = documentManager.createDocumentFolderFilter();

        //Set to order by name
        DocumentFolderQueryOrder nameOrder = new DocumentFolderQueryOrder(DocumentFolderAttribute.NAME, true);
        DocumentFolderQueryOrder[] orders = new DocumentFolderQueryOrder[]{nameOrder};
        filter.setQueryOrders(orders);

        //To find folders in a project, we must look in the top level folder
        IDocumentFolder topLevelFolder = documentManager.getTopLevelFolder(project);
        IDocumentFolder[] foundFolders = documentManager.queryFolders(topLevelFolder, filter);

        return foundFolders;
    }

    public static IDocument[] findCheckedOutDocumentsInProject(IProject project) throws Exception
    {
        //Create the new query filter
        IDocumentFilter filter = documentManager.createDocumentFilter();

        //Set it to only search for checked-out documents
        filter.setFilterType(DocumentFilterType.CHECKED_OUT_BY_CURRENT_USER);

        //Set to order by size, then last modified date
        DocumentQueryOrder sizeOrder = new DocumentQueryOrder(DocumentAttribute.NUM_BYTES, true);
        DocumentQueryOrder lastModifiedOrder = new DocumentQueryOrder(DocumentAttribute.LAST_MODIFIED, true);
        DocumentQueryOrder[] orders = new DocumentQueryOrder[]{sizeOrder, lastModifiedOrder};
        filter.setQueryOrders(orders);

        //Perform query
        IDocument[] foundDocuments = documentManager.queryDocuments(project, filter);
        return foundDocuments;
    }

    public static void copyDocumentToFolder(IDocument documentToCopy, IDocumentFolder sourceFolder, IDocumentFolder targetFolder) throws Exception
    {
        //Documents to copy
        IDocument[] documentsToCopy = new IDocument[]{documentToCopy};

        //We won't copy any folders
        IDocumentFolder[] foldersToCopy = new IDocumentFolder[0];

        //Copy the document, inheriting the security from the target folder
        documentManager.copyToFolder(sourceFolder, targetFolder, documentsToCopy,  foldersToCopy, true, "copied from original sample folder");
    }

    public static void checkInNewDocumentVersion(IDocument originalDocument) throws Exception
    {
        //Open an inputstream for the document contents
        FileInputStream fileInputStream = new FileInputStream("c:\\report2.doc");

        //Check in the new version
        documentManager.checkInDocument(originalDocument, "this is an updated version of the example document", fileInputStream, "en", false);
    }

    public static IDocument createAndInsertNewDocument(IDocumentFolder containingFolder) throws Exception
    {
        //Create the document
        IDocument newDocument = documentManager.createNewDocument("my new document", "this is a test document created by the samples");

        //Set optional properties
        newDocument.setAuthor("joe bloggs");

        //Set content-type
        newDocument.setContentType("text/vnd.ms-word");

        //Open an inputstream for the document contents
        FileInputStream fileInputStream = new FileInputStream("c:\\report.doc");

        //Insert the document, inheriting the containing folder's security
        IDocument storedDocument = documentManager.insertNewDocument(containingFolder, newDocument, "initial check-in", fileInputStream, "en", true);

        return storedDocument;
    }

    public static IDocumentFolder createAndInsertNewFolder(IProject containingProject, String name) throws Exception
    {
        //Create the folder
        IDocumentFolder newFolder = documentManager.createNewFolder(name, "this is a test folder created by the examples");

        //Could now set optional properties such as security on newFolder before store...

        //Get the top level folder of the project to insert the document into
        IDocumentFolder topLevelFolder = documentManager.getTopLevelFolder(containingProject);

        //Insert the folder, inheriting the top level folder's security
        IDocumentFolder storedFolder = documentManager.insertNewFolder(topLevelFolder, newFolder, true);

        return storedFolder;
    }

    public static void storeDocumentContent(IDocument toStore) throws Exception
    {
        //Generate a file name to store the content to
        String nameToUse = toStore.getName() + ".doc";

        //Create an output stream to store the data
        FileOutputStream fileOutputStream = new FileOutputStream(nameToUse);

        InputStream documentContentStream = null;

        try
        {
            //Get the content stream
            documentContentStream = toStore.getContentAsInputStream();

            //Pump it out to a file
            byte[] buf = new byte[32 * 1024];
            int read = documentContentStream.read(buf);

            while(read > -1)
            {
                fileOutputStream.write(buf, 0, read);
                read = documentContentStream.read(buf);
            }
        }
        finally //make sure the stream is closed
        {
            documentContentStream.close();
            fileOutputStream.close();
        }
    }
}
