/*
 * $Id: ClipBoard.java,v 1.11 2005/09/13 00:24:25 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: ClipBoard.java,v $
 * Revision 1.11  2005/09/13 00:24:25  marbobo
 * + Flag-Unterstützung für Dokumente und Kategorien
 *
 * Revision 1.10  2005/08/26 14:59:09  jonyp
 * chnages due to new parameter WebShare.database.delete method
 *
 * Revision 1.9  2004/12/23 00:58:38  koppy
 * Anpassung aufgrund geänderter GenericDBImpl.move()-Methode
 *
 * Revision 1.8  2004/11/02 21:49:30  marbobo
 * + Alle Clipboard-Operationen für Gast-Benutzer gesperrt
 *
 * Revision 1.7  2004/10/31 18:19:36  marbobo
 * + Bei den Kopier- und Verschiebefunktionen   Benutzerrechte berücksichtigen
 * + Der Benutzer der Kopier- und Verschiebefunktionen ausführt bekommt standardmäßig alle Rechte
 *
 * Revision 1.6  2004/10/31 03:03:22  marbobo
 * + ClipBoard-Funktionen überarbeitet
 *
 * Revision 1.4  2004/01/17 02:45:15  koppy
 * + pasteAsProject
 *
 * Revision 1.2  2003/07/17 19:25:04  koppy
 * + COPY-Operation
 *
 * Revision 1.1  2003/07/12 13:59:44  koppy
 * Initiale Version
 *
 */
package vkc.view;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import vkc.db.entities.VKCCategory;
import vkc.db.entities.VKCDocument;
import vkc.db.entities.VKCUser;
import vkc.db.serializer.VKCAclSerializer;
import vkc.db.serializer.VKCCategorySerializer;
import vkc.exception.DBException;
import vkc.security.PermissionManager;
import vkc.util.CategoryUtils;
import vkc.util.DocumentUtils;

/**
 * This class represents a ClipBoard
 * for storing the document- and categoryIds
 * 
 * @author koppy
 */
public class ClipBoard implements Serializable {
	public static final int NO_OPERATION   	 = 0;
	public static final int COPY_OPERATION   = 1;
	public static final int MOVE_OPERATION   = 2;
	public static final int CUT_OPERATION    = 3;
	public static final int PASTE_OPERATION  = 4;
	public static final int DELETE_OPERATION = 5;

	private int operation = NO_OPERATION;

	private Integer sourceCategoryId = null;
	private Integer targetCategoryId = null;
	private Integer categoryFlag = VKCCategory.FLAG_ACTIVE;
	private Integer documentFlag = VKCDocument.FLAG_PUBLISHED;
	
	private Set documentIds = new HashSet();
	private Set categoryIds = new HashSet();
	
	private Set allCategoryIds = null;
	private Set allDocumentIds = null;
	
	private VKCUser user = null;
	
	public boolean execute() throws DBException {
        boolean successful = false;
	    
	    switch (getOperation()) {
	    	case COPY_OPERATION: {
	    	    successful = isOperationPossible();
	    	    break;
	    	}
	    	
	    	case CUT_OPERATION: {
	    	    successful = isOperationPossible();
	    	    break;
	    	}
	    	
	    	case DELETE_OPERATION: {
				if (isOperationPossible()) {
				    WebShare.database.delete(getSourceCategoryId(), getCategoryIds(), getDocumentIds(), getUser());
				    successful = true;
				}
				
	    	    break;
	    	}
	    	
	    	case PASTE_OPERATION: {
	    	    if (isOperationPossible()) {
					WebShare.database.copy(getTargetCategory(), getCategoryIds(), getDocumentIds(), getUser());						
	    	        successful = true;
	    	    }
	    	    
	    	    break;
	    	}
	    	
	    	case MOVE_OPERATION: {
	    	    if (isOperationPossible()) {
					WebShare.database.move(getSourceCategory(), getTargetCategory(), getCategoryIds(), getDocumentIds(), getUser());                        
	    	        successful = true;
	    	    }
	    	    
	    	    break;
	    	}
	    	
	    	default: {
	    	    successful = false;
	    		break;
	    	}
	    }
    
	    return successful;
	}
	
	public Set getAllCategoryIds() throws DBException {
		if (allCategoryIds == null) {
		    allCategoryIds = new HashSet();
		    Iterator it = getCategoryIds().iterator();
		    
		    while (it.hasNext()) {
		        Integer categoryId = (Integer)it.next();
		        allCategoryIds.addAll(CategoryUtils.getAllSubCategoryIdsRecursiv(categoryId));
		        allCategoryIds.add(categoryId);
		    }
		}
	    
	    return allCategoryIds;
	}

	public Set getCategoryIds() {
		return categoryIds;
	}

	public void setCategoryIds(Set set) {
		categoryIds = set;
	}

	public Set getAllDocumentIds() throws DBException {
		if (allDocumentIds == null) {
		    allDocumentIds = new HashSet();
		    Iterator it = getCategoryIds().iterator();
		    
		    while (it.hasNext()) {
		        Integer categoryId = (Integer)it.next();
		        allDocumentIds.addAll(DocumentUtils.getAllDocumentIdsRecursiv(categoryId, getDocumentFlag()));
		    }
		    
		    allDocumentIds.addAll(getDocumentIds());
		}
	    
	    return allDocumentIds;
	}

	public Set getDocumentIds() {
		return documentIds;
	}

	public void setDocumentIds(Set set) {
		documentIds = set;
	}

	public VKCCategory getSourceCategory() throws DBException {
		return VKCCategorySerializer.retrieveCategory(getSourceCategoryId());
	}

	public Integer getSourceCategoryId() {
		return sourceCategoryId;
	}

	public void setSourceCategoryId(Integer i) {
		sourceCategoryId = i;
		
	}

	public VKCCategory getTargetCategory() throws DBException {
		return VKCCategorySerializer.retrieveCategory(getTargetCategoryId());
	}

	public Integer getTargetCategoryId() {
		return targetCategoryId;
	}

	public void setTargetCategoryId(Integer i) {
		targetCategoryId = i;
		
	}

	public int getOperation() {
		return operation;
	}

	public void setOperation(int i) {
		operation = i;		
	}

	public VKCUser getUser() {
		return user;
	}

	public void setUser(VKCUser u) {
		user = u;		
	}

    public boolean isSourceCategoryId(Integer i) {
        return getSourceCategoryId().equals(i);
    }

    public boolean isDocumentInClipboard(Integer i) throws DBException {
        return getAllDocumentIds().contains(i);
    }

    public boolean isCategoryInClipboard(Integer i) throws DBException {
        return getAllCategoryIds().contains(i);
    }
    
    public boolean isOperationPossible() {
        return isOperationPossible(getOperation());
    }

    private boolean isOperationPossible(int i) {
        try {
            if (getUser().isGuestUser()) {
                return false;
            }
            
            boolean possible = false;
            
            switch (i) {
            	case COPY_OPERATION: {
            	    possible = true;
            	    break;
            	}
            	
            	case CUT_OPERATION:
            	case DELETE_OPERATION: {
            	    if (getCategoryIds().isEmpty() && !getDocumentIds().isEmpty()) {
    				    if (PermissionManager.hasPermission(VKCAclSerializer.getAclByCategoryId(getSourceCategoryId()), getUser(), 'd')) {
    				        possible = true;
    				    }
            	    } else if (!getCategoryIds().isEmpty() && getDocumentIds().isEmpty()) {
                	    possible = true;
    				    Iterator it = getCategoryIds().iterator();
    				    
    				    while (it.hasNext()) {
    				        if (!PermissionManager.hasPermissionsRecursiv((Integer)it.next(), getUser(), "D")) {
    				            possible = false;
    				            break;
    				        }
    				    }
            	    } else if (!getCategoryIds().isEmpty() && !getDocumentIds().isEmpty()) {
                	    possible = true;
    				    Iterator it = getCategoryIds().iterator();
    				    
    				    while (it.hasNext()) {
    				        if (!PermissionManager.hasPermissionsRecursiv((Integer)it.next(), getUser(), "D")) {
    				            possible = false;
    				            break;
    				        }
    				    }
            	        
    				    if (possible && !PermissionManager.hasPermission(VKCAclSerializer.getAclByCategoryId(getSourceCategoryId()), getUser(), 'd')) {
    				        possible = false;
    				    }
            	    }
            	    
            	    break;
            	}
            	
            	case PASTE_OPERATION:
            	case MOVE_OPERATION: {
            	    if (getCategoryIds().isEmpty() && !getDocumentIds().isEmpty()) {
    				    if (PermissionManager.hasPermission(VKCAclSerializer.getAclByCategoryId(getTargetCategoryId()), getUser(), 'w')) {
    				        possible = true;
    				    }
            	    } else if (!getCategoryIds().isEmpty() && getDocumentIds().isEmpty()) {
                	    possible = true;

    				    if (!PermissionManager.hasPermission(VKCAclSerializer.getAclByCategoryId(getTargetCategoryId()), getUser(), 'C')) {
    				        possible = false;
    				    } 
            	    } else if (!getCategoryIds().isEmpty() && !getDocumentIds().isEmpty()) {
                	    possible = true;

    				    if (!PermissionManager.hasPermission(VKCAclSerializer.getAclByCategoryId(getTargetCategoryId()), getUser(), 'C')) {
    				        possible = false;
    				    } 

    				    if (possible && !PermissionManager.hasPermission(VKCAclSerializer.getAclByCategoryId(getTargetCategoryId()), getUser(), 'w')) {
    				        possible = false;
    				    }
            	    }
            	    
            	    break;
            	}
            	
            	default: {
            	    possible = false;
            		break;
            	}
            }
            
            return possible;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * Checks whether a new project can be created
     * from the contents in the clipboard.
     * At now this is true iff a single category
     * is in clipboard, NO documents..
     * 
     * @return true, if a project can be created from the clipboards contents
     */
    public boolean isProjectPastePossible(){
    	return getDocumentIds().isEmpty() && getCategoryIds().size() == 1;
    }
    
    /**
     * Returns the first category id
     * in the set of category ids
     * @return first category id
     */
    public Integer getFirstCategoryId(){
    	return (Integer) getCategoryIds().iterator().next();
    }

	public Integer getCategoryFlag() {
		return categoryFlag;
	}

	public void setCategoryFlag(Integer categoryFlag) {
		this.categoryFlag = categoryFlag;
	}

	public Integer getDocumentFlag() {
		return documentFlag;
	}

	public void setDocumentFlag(Integer documentFlag) {
		this.documentFlag = documentFlag;
	}
}