/**
 * 
 */
package org.gcube.portlets.widgets.workspacesharingwidget.server;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.gcube.common.homelibrary.home.User;
import org.gcube.common.homelibrary.home.exceptions.InternalErrorException;
import org.gcube.common.homelibrary.home.workspace.WorkspaceItem;
import org.gcube.common.homelibrary.home.workspace.WorkspaceSharedFolder;
import org.gcube.common.homelibrary.home.workspace.accessmanager.ACLType;
import org.gcube.common.homelibrary.home.workspace.folder.FolderItem;
import org.gcube.common.homelibrary.home.workspace.folder.items.ExternalFile;
import org.gcube.common.homelibrary.home.workspace.folder.items.ExternalImage;
import org.gcube.common.homelibrary.home.workspace.folder.items.ExternalPDFFile;
import org.gcube.common.homelibrary.home.workspace.folder.items.gcube.Document;
import org.gcube.common.homelibrary.home.workspace.folder.items.gcube.ImageDocument;
import org.gcube.portlets.widgets.workspacesharingwidget.server.util.UserUtil;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.ACL_TYPE;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.FileModel;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.FolderModel;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.GXTFolderItemTypeEnum;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.InfoContactModel;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.WorkspaceACL;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.WorkspaceACL.USER_TYPE;
import org.gcube.vomanagement.usermanagement.model.UserModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it
 * @Feb 25, 2014
 * 
 */
public class GWTWorkspaceSharingBuilder {

	protected Logger logger = LoggerFactory.getLogger(GWTWorkspaceSharingBuilder.class);

	private InfoContactModel userLogged;

	protected static HashMap<String, InfoContactModel> hashTestUser = null;

	/**
	 * Used in test mode
	 * 
	 * @return
	 */
	public static HashMap<String, InfoContactModel> getHashTestUsers() {

		if (hashTestUser == null) {
			hashTestUser = new HashMap<String, InfoContactModel>();
			
			hashTestUser.put("federico.defaveri", 
					new InfoContactModel(
					"federico.defaveri", "federico.defaveri",
					"Federico de Faveri", false));
			
			hashTestUser.put("antonio.gioia", 
					new InfoContactModel(
					"antonio.gioia", "antonio.gioia", "Antonio Gioia", false));
			
			hashTestUser.put("fabio.sinibaldi",
					new InfoContactModel(
					"fabio.sinibaldi", "fabio.sinibaldi", "Fabio Sinibaldi",false));
			
			hashTestUser.put("pasquale.pagano", 
					new InfoContactModel(
					"pasquale.pagano", "pasquale.pagano", "Pasquale Pagano",false));
			
			hashTestUser.put("francesco.mangiacrapa", 
					new InfoContactModel(
					"francesco.mangiacrapa", "francesco.mangiacrapa",
					"Francesco Mangiacrapa",false));
			
			hashTestUser.put("massimiliano.assante", 
					new InfoContactModel(
					"massimiliano.assante", "massimiliano.assante",
					"Massimiliano Assante",false));
			
			hashTestUser.put("leonardo.candela", 
					new InfoContactModel(
					"leonardo.candela", "leonardo.candela",
					"Leonardo Candela",false));
			
			hashTestUser.put("valentina.marioli", 
					new InfoContactModel(
					"valentina.marioli", "valentina.marioli",
					"Valentina Marioli",false));
			
//			hashTestUser.put(WsUtil.TEST_USER.toString(), 
//					new InfoContactModel(
//					WsUtil.TEST_USER, WsUtil.TEST_USER,
//					WsUtil.TEST_USER_FULL_NAME));

		}

		return hashTestUser;
	}

	/**
	 * @param infoContactModel
	 */
	public void setUserLogged(InfoContactModel infoContactModel) {
		this.userLogged = infoContactModel;
	}

	/**
	 * 
	 * @param listUsers
	 * @return
	 * @throws InternalErrorException
	 */
	public List<InfoContactModel> buildGXTListContactsModel(List<UserModel> listUsers) throws InternalErrorException {

		List<InfoContactModel> listContactsModel = new ArrayList<InfoContactModel>();

		if (listUsers == null)
			return listContactsModel;

		logger.info("List<UserModel> size returned from Portal VO is: "
				+ listUsers.size());

		logger.info("Building list contact model list user model");
		for (UserModel userModel : listUsers) {
			String fullName = userModel.getFullname();

			//TODO ISGROUP?
			if (fullName != null && !fullName.isEmpty())
				listContactsModel.add(new InfoContactModel(userModel.getUserId() + "",userModel.getScreenName(), fullName,false));
			else
				logger.info("buildGXTListContactsModel doesn't return user: "
						+ userModel.getScreenName()
						+ "because name is null or empty");
		}
		logger.info("List contact model completed, return "
				+ listContactsModel.size() + " contacts");

		return listContactsModel;
	}

	/**
	 * 
	 * @param listPortalLogin
	 * @return
	 */
	public List<InfoContactModel> buildGxtInfoContactsFromPortalLogins(List<String> listPortalLogin) {

		List<InfoContactModel> listContact = new ArrayList<InfoContactModel>();
		for (String portalLogin : listPortalLogin)
			listContact.add(buildGxtInfoContactFromPortalLogin(portalLogin));

		return listContact;
	}

	/**
	 * 
	 * @param portalLogin
	 * @return
	 */
	protected InfoContactModel buildGxtInfoContactFromPortalLogin(
			String portalLogin) {

		if (portalLogin == null) {
			logger.warn("portal login is null, return empty");
			portalLogin = "";
		}

		//TODO ISGROUP
		return new InfoContactModel(portalLogin, portalLogin,UserUtil.getUserFullName(portalLogin), false);

	}

	/**
	 * Used in test mode
	 * 
	 * @param listPortalLogin
	 * @return
	 */
	protected List<InfoContactModel> buildGxtInfoContactFromPortalLoginTestMode(
			List<String> listPortalLogin) {

		List<InfoContactModel> listContact = new ArrayList<InfoContactModel>();

		for (String portalLogin : listPortalLogin)
			listContact.add(getHashTestUsers().get(portalLogin));

		return listContact;
	}

	/**
	 * 
	 * @param user
	 * @return
	 * @throws InternalErrorException
	 */
	public InfoContactModel buildGXTInfoContactModel(User user)
			throws InternalErrorException {

		//TODO ISGROUP
		if (user != null)
			return new InfoContactModel(user.getId(), user.getPortalLogin(), UserUtil.getUserFullName(user.getPortalLogin()),false);

		return new InfoContactModel();
	}

	public List<WorkspaceACL> getWorkspaceACLFromACLs(List<ACLType> types)
			throws Exception {

		List<WorkspaceACL> acls = new ArrayList<WorkspaceACL>();

		for (ACLType acl : types) {

			switch (acl) {

			case ADMINISTRATOR:
				// acls.add(new WorkspaceACL(acl.toString(),
				// ACL_TYPE.ADMINISTRATOR, "Admin", false,
				// USER_TYPE.ADMINISTRATOR, ""));
				break;
			case READ_ONLY:
				acls.add(new WorkspaceACL(acl.toString(), ACL_TYPE.READ_ONLY,
						"Read Only", false, USER_TYPE.OTHER,
						"Users can read any file but cannot update/delete"));
				break;
			case WRITE_OWNER:
				acls.add(new WorkspaceACL(acl.toString(), ACL_TYPE.WRITE_OWNER,
						"Write Own", true, USER_TYPE.OTHER,
						"Users can update/delete only their files"));
				break;

			case WRITE_ALL:
				acls.add(new WorkspaceACL(acl.toString(), ACL_TYPE.WRITE_ANY,
						"Write Any", false, USER_TYPE.OTHER,
						"Any user can update/delete any file"));
				break;

			default:
				acls.add(new WorkspaceACL(acl.toString(), ACL_TYPE.WRITE_OWNER,
						acl.toString(), false, USER_TYPE.OTHER, ""));
				break;
			}
		}

		if (acls.size() == 0)
			throw new Exception("No ACLs rules found!");

		return acls;
	}

	protected FileModel buildGXTFileModelItem(WorkspaceItem item, FileModel parentFolderModel) throws Exception {
		FileModel fileModel = null;

		FileModel parent = parentFolderModel != null ? (FileModel) parentFolderModel: null;

		logger.info("Workspace item converting...");
		
		try{
			switch (item.getType()) {
	
			case FOLDER:
				logger.info("Workspace item is folder...");
				fileModel = new FolderModel(item.getId(), item.getName(), parent, true, false, false);
				fileModel.setType(GXTFolderItemTypeEnum.FOLDER.toString());
				fileModel.setDescription(item.getDescription());
				break;
	
			case FOLDER_ITEM:
				logger.info("Workspace item is folder item...");
				fileModel = new FileModel(item.getId(), item.getName(), parent, false, false);
				FolderItem folderItem = (FolderItem) item;
				fileModel = setFolderItemType(fileModel, folderItem);
				break;
	
			case SHARED_FOLDER:
				logger.info("Workspace item is shared item...");
				WorkspaceSharedFolder shared = (WorkspaceSharedFolder) item;
				String name = shared.isVreFolder() ? shared.getDisplayName() : item.getName();
				fileModel = new FolderModel(item.getId(), name, parent, true, true, shared.isVreFolder());
				fileModel.setType(GXTFolderItemTypeEnum.SHARED_FOLDER.toString());
				fileModel.setDescription(item.getDescription());
				break;
	
			default:
				logger.error("gxt conversion return null for item "+ item.getName());
				break;
	
			}
		}catch (Exception e) {
			logger.error("gxt conversion error: ",e);
			throw new Exception("Error on conversion: ",e);
		}

		return fileModel;

	}

	protected FileModel setFolderItemType(FileModel fileModel,
			FolderItem worspaceFolderItem) {

		switch (worspaceFolderItem.getFolderItemType()) {
		case EXTERNAL_IMAGE:
			fileModel.setFolderItemType(GXTFolderItemTypeEnum.EXTERNAL_IMAGE);
			ExternalImage extImage = (ExternalImage) worspaceFolderItem;
			fileModel.setType(extImage.getMimeType());
			break;
		case EXTERNAL_FILE:
			fileModel.setFolderItemType(GXTFolderItemTypeEnum.EXTERNAL_FILE);

			ExternalFile extFile = (ExternalFile) worspaceFolderItem;
			fileModel.setType(extFile.getMimeType());
			break;
		case EXTERNAL_PDF_FILE:
			fileModel
					.setFolderItemType(GXTFolderItemTypeEnum.EXTERNAL_PDF_FILE);
			ExternalPDFFile pdfExt = (ExternalPDFFile) worspaceFolderItem;
			fileModel.setType(pdfExt.getMimeType());
			break;
		case EXTERNAL_URL:
			fileModel.setFolderItemType(GXTFolderItemTypeEnum.EXTERNAL_URL);
			break;
		case REPORT_TEMPLATE:
			fileModel.setFolderItemType(GXTFolderItemTypeEnum.REPORT_TEMPLATE);
			break;
		case REPORT:
			fileModel.setFolderItemType(GXTFolderItemTypeEnum.REPORT);
			break;
		case QUERY:
			fileModel.setFolderItemType(GXTFolderItemTypeEnum.QUERY);
			break;
		case TIME_SERIES:
			fileModel.setFolderItemType(GXTFolderItemTypeEnum.TIME_SERIES);
			break;
		case PDF_DOCUMENT:
			fileModel.setFolderItemType(GXTFolderItemTypeEnum.PDF_DOCUMENT);
			break;
		case IMAGE_DOCUMENT:
			fileModel.setFolderItemType(GXTFolderItemTypeEnum.IMAGE_DOCUMENT);
			ImageDocument imgDoc = (ImageDocument) worspaceFolderItem;
			fileModel.setType(imgDoc.getMimeType());
			break;
		case DOCUMENT:
			fileModel.setFolderItemType(GXTFolderItemTypeEnum.DOCUMENT);
			Document doc = (Document) worspaceFolderItem;
			fileModel.setType(doc.getMimeType());
			break;
		case URL_DOCUMENT:
			fileModel.setFolderItemType(GXTFolderItemTypeEnum.URL_DOCUMENT);
			break;
		case METADATA:
			fileModel.setFolderItemType(GXTFolderItemTypeEnum.METADATA);
			break;
		case WORKFLOW_REPORT:
			fileModel.setFolderItemType(GXTFolderItemTypeEnum.WORKFLOW_REPORT);
			break;
		case WORKFLOW_TEMPLATE:
			fileModel
					.setFolderItemType(GXTFolderItemTypeEnum.WORKFLOW_TEMPLATE);
			// logger.info("**************************************DOCUMENTS******* filemodel "+
			// fileModel.getName());
			break;
		case EXTERNAL_RESOURCE_LINK:
			fileModel
					.setFolderItemType(GXTFolderItemTypeEnum.EXTERNAL_RESOURCE_LINK);

			break;
		default:
			fileModel.setFolderItemType(GXTFolderItemTypeEnum.UNKNOWN_TYPE);
			fileModel.setType(GXTFolderItemTypeEnum.UNKNOWN_TYPE.toString());
			// logger.info("**************************************UNKNOWN******* filemodel "+
			// fileModel.getName());
			break;
		}

		return fileModel;
	}

}
