package org.gcube.application.cms.implementations;

import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.gcube.application.geoportal.common.model.configuration.Archive;
import org.gcube.application.geoportal.common.model.document.filesets.RegisteredFile;
import org.gcube.application.geoportal.common.model.rest.ConfigurationException;
import org.gcube.application.geoportal.common.utils.Files;
import org.gcube.common.storagehub.client.dsl.FileContainer;
import org.gcube.common.storagehub.client.dsl.FolderContainer;
import org.gcube.common.storagehub.client.dsl.StorageHubClient;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;

import java.io.InputStream;

@Slf4j
public class WorkspaceManager {

	private static final String APP_FOLDER=".GNA_RECORDS";


	private StorageHubClient sgClient=null;
	@Getter
	private FolderContainer appBase=null;

	@Getter
	@Setter
	@AllArgsConstructor
	@RequiredArgsConstructor
	public static class FolderOptions{
		@NonNull
		private String folderName;
		private String folderDescription;
		private FolderContainer parent;
	}
	
	@Getter
	@Setter
	@AllArgsConstructor
	@RequiredArgsConstructor
	public static class FileOptions{
		@NonNull
		private String fileName;
		@NonNull
		private InputStream is;
		
		private String fileDescription;
		private FolderContainer parent;
		
	}

	public Archive getConfiguration(){
		Archive toReturn = new Archive("W-STORAGE");
		toReturn.put("folder_id",appBase.getId());
		return toReturn;
	}

	public WorkspaceManager() throws ConfigurationException, StorageHubException {
		sgClient= ImplementationProvider.get().getProvidedObjectByClass(StorageHubClient.class);
		appBase=getApplicationBaseFolder(sgClient);
	}

	public FolderContainer createFolder(FolderOptions opts) throws StorageHubException {
		if(opts.getParent()==null)
			opts.setParent(appBase);
		return createFolderRoutine(opts);
	}

	public FileContainer getFileById(String id) throws StorageHubException {
		return sgClient.open(id).asFile();
	}

	public FolderContainer getFolderById(String id) throws StorageHubException {
		return sgClient.open(id).asFolder();
	}

	public void removeFolderById(String id) throws StorageHubException {
		sgClient.open(id).asFolder().delete();
	}

	public FolderContainer getSubFolder(FolderContainer parentFolder,String path) throws StorageHubException {		
		try{
			return parentFolder.openByRelativePath(path).asFolder();
		}catch(StorageHubException e) {			
			log.debug("Missing subPath "+path);
			FolderContainer targetParent=parentFolder;
			String targetName=path;
			if(path.contains("/")) {
				String parent=path.substring(0, path.lastIndexOf("/"));
				log.debug("Checking intermediate "+parent);
				targetParent=getSubFolder(parentFolder,parent);
				targetName=path.substring(path.lastIndexOf("/")+1);
			}
			log.debug("Creating "+targetName);
			return createFolder(new FolderOptions(targetName,"",targetParent));
		}
	}


//	public WorkspaceContent storeToWS(FileOptions opts) throws FileNotFoundException, StorageHubException {
//		FileContainer item=createFileRoutine(opts);
//		item=sgClient.open(item.getId()).asFile();
//
//		WorkspaceContent content=new WorkspaceContent();
//		content.setLink(item.getPublicLink().toString());
//		content.setMimetype(item.get().getContent().getMimeType());
//		content.setStorageID(item.getId());
//		content.setName(item.get().getName());
//		return content;
//
//	}

	public RegisteredFile registerFile(FileOptions opts) throws StorageHubException {
		FileContainer item=createFileRoutine(opts);
		item=sgClient.open(item.getId()).asFile();

		RegisteredFile file=new RegisteredFile();
		
		
		file.setLink(item.getPublicLink().toString());
		file.setMimetype(item.get().getContent().getMimeType());
		file.setStorageID(item.getId());
		file.setName(item.get().getName());
		return file;

	}
	
	
//	public void deleteFromWS(WorkspaceContent toDelete) throws StorageHubException {
//		sgClient.open(toDelete.getStorageID()).asFile().forceDelete();
//	}

	public void deleteItem(String itemId)throws StorageHubException{
		sgClient.open(itemId).asItem().forceDelete();
	}

	// STATIC SYNCH METHODS 
	
	@Synchronized
	public static FolderContainer getApplicationBaseFolder(StorageHubClient sgClient) throws StorageHubException {
		FolderContainer vre=sgClient.openVREFolder();
		try {
			return vre.openByRelativePath(APP_FOLDER).asFolder();
		}catch(StorageHubException e) {
			log.debug("APP Fodler missing. Initializing..");
			FolderContainer toReturn= vre.newFolder(APP_FOLDER, "Base folder for GNA records");
			toReturn.setHidden();
			return toReturn;
		}
	}

	@Synchronized
	private static FolderContainer createFolderRoutine(FolderOptions opts) throws StorageHubException {
		opts.setFolderName(Files.fixFilename(opts.getFolderName()));
		return opts.getParent().newFolder(opts.getFolderName(),opts.getFolderDescription());
	}
	
	@Synchronized
	private static FileContainer createFileRoutine(FileOptions opts) throws StorageHubException {
		opts.setFileName(Files.fixFilename(opts.getFileName()));
		return opts.getParent().uploadFile(opts.getIs(), opts.getFileName(), opts.getFileDescription());
	}
}
