package org.gcube.application.geoportal.common.utils;

import org.bson.Document;
import org.gcube.application.geoportal.common.model.document.access.Access;
import org.gcube.application.geoportal.common.model.legacy.InputStreamDescriptor;
import org.gcube.application.geoportal.common.model.rest.RegisterFileSetRequest;
import org.gcube.application.geoportal.common.model.rest.TempFile;
import org.gcube.contentmanagement.blobstorage.transport.backend.RemoteBackendException;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collection;

public class FileSets {

    public static class RequestBuilder {
        RegisterFileSetRequest theRequest=new RegisterFileSetRequest();

        public RequestBuilder addAll(Collection<? extends TempFile> toAdd){
            if(theRequest.getStreams()==null)
                theRequest.setStreams(new ArrayList<TempFile>());
            theRequest.getStreams().addAll(toAdd);
            return this;
        }
        public RequestBuilder add(TempFile... f){
            if(theRequest.getStreams()==null)
                theRequest.setStreams(new ArrayList<TempFile>());
            for(TempFile temp: f )
                theRequest.getStreams().add(temp);
            return this;
        }

        public RequestBuilder add(TempFile f){
            if(theRequest.getStreams()==null)
                theRequest.setStreams(new ArrayList<TempFile>());
            theRequest.getStreams().add(f);
            return this;
        }

        public RequestBuilder setFieldDefinitionPath(String path){
            theRequest.setFieldDefinitionPath(path);
            return this;
        }

        public RequestBuilder setParentPath(String path){
            theRequest.setParentPath(path);
            return this;
        }

        public RequestBuilder setFieldName(String fieldName){
            theRequest.setFieldName(fieldName);
            return this;
        }

        public RequestBuilder setClashPolicy(RegisterFileSetRequest.ClashOptions path){
            theRequest.setClashOption(path);
            return this;
        }

        public RequestBuilder setAttributes(Document attributes){
            theRequest.setAttributes(attributes);
            return this;
        }

        public RegisterFileSetRequest getTheRequest(){
            if(theRequest.getClashOption()==null)
                // default Clash Policy
                setClashPolicy(RegisterFileSetRequest.ClashOptions.REPLACE_EXISTING);
            return theRequest;}

        public RequestBuilder setAccess(Access access){
            theRequest.setToSetAccess(access);
            return this;
        }

    }


    public static RequestBuilder build(String parent,String fieldName, String fieldDefinition) {
        return new RequestBuilder().setParentPath(parent).setFieldDefinitionPath(fieldDefinition).setFieldName(fieldName);
    }

    public static RequestBuilder build(String parent,String fieldName, String fieldDefinition, TempFile...files) {
        return build(parent,fieldName,fieldDefinition).add(files);
    }

    public static TempFile asTemp(StorageUtils storage,InputStreamDescriptor descriptor) throws RemoteBackendException, FileNotFoundException {
        return storage.putOntoStorage(descriptor.getStream(), descriptor.getFilename());
    }

    public static TempFile[] asTemp(StorageUtils storage,InputStreamDescriptor... descriptors) throws RemoteBackendException, FileNotFoundException {
        ArrayList<TempFile> toReturn=new ArrayList<TempFile>();
        for(InputStreamDescriptor desc:descriptors)
            toReturn.add(storage.putOntoStorage(desc.getStream(), desc.getFilename()));
        return toReturn.toArray(new TempFile[toReturn.size()]);
    }

    public static RegisterFileSetRequest prepareRequestFromFolder(StorageUtils storage,
                                                                  String parentPath,String fieldName,String fieldDefinition, File directory) throws FileNotFoundException {

        File[] children =directory.listFiles();
        InputStreamDescriptor[] iss=new InputStreamDescriptor[children.length];
        return prepareRequest(storage,parentPath,fieldName,fieldDefinition,children);

    }

    public static RegisterFileSetRequest prepareRequest(StorageUtils storage,
                                                        String parentPath,String fieldName,String fieldDefinition, File... toUpload) throws FileNotFoundException {

        FileSets.RequestBuilder builder = FileSets.build(parentPath,fieldName,fieldDefinition);
        for (File f : toUpload) {
            if(!f.isDirectory())
            builder.add(FileSets.asTemp(storage, new InputStreamDescriptor(new FileInputStream(f), f.getName())));
        }
        return builder.getTheRequest();
    }
}
