/*
 * $Id: ShowCategoryForm.java,v 1.60 2007/08/14 14:50:03 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: ShowCategoryForm.java,v $
 * Revision 1.60  2007/08/14 14:50:03  marbobo
 * + Licenseverwaltung komplett umgeschrieben
 * + Kategoriesuche und verlorene Kategorien anzeigen komplett umgeschrieben
 * + Fehler beim Speichern von Beschreibenungsfeldern für Entitäten beseitigt.
 *
 * Revision 1.59  2007/05/29 08:18:32  korowa
 * Suchen nach Kategorien hinzugefügt
 *
 */
 
package vkc.view.form;

import java.text.CollationKey;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMapping;

import vkc.db.entities.VKCCategory;
import vkc.db.entities.VKCDocument;
import vkc.db.entities.VKCDocumentStatus;
import vkc.db.entities.VKCEntity;
import vkc.db.entities.VKCSubCategory;
import vkc.db.serializer.VKCCategorySerializer;
import vkc.db.serializer.VKCDocumentSerializer;
import vkc.db.serializer.VKCDocumentStatusSerializer;
import vkc.exception.DBException;
import vkc.misc.VKCLogManager;
import vkc.util.CategoryUtils;
import vkc.util.DocumentUtils;
import vkc.util.StringUtils;
import vkc.util.VKCStringUtils;
import vkc.view.WebShare;
import vkc.view.bean.CategorySettings;
import vkc.view.bean.VKCCountCatDocs;

public class ShowCategoryForm extends BasicActionForm {
	public final static int CATEGORY_SORT_NAME_UP   		= 1;
	public final static int CATEGORY_SORT_NAME_DOWN 		= 2;

	public final static int DOCUMENT_SORT_PUBLISHING_DATE_UP   	= 1;
	public final static int DOCUMENT_SORT_PUBLISHING_DATE_DOWN 	= 2;

	public final static int DOCUMENT_SORT_TITLE_UP  			= 3;
	public final static int DOCUMENT_SORT_TITLE_DOWN			= 4;

	public final static int DOCUMENT_SORT_AUTHOR_UP 			= 5;
	public final static int DOCUMENT_SORT_AUTHOR_DOWN			= 6;
	
	public final static int DOCUMENT_SORT_SIZE_UP  				= 7;
	public final static int DOCUMENT_SORT_SIZE_DOWN 			= 8;

	public final static int DOCUMENT_SORT_TYPE_UP  				= 9;
	public final static int DOCUMENT_SORT_TYPE_DOWN 			= 10;

	public final static int DOCUMENT_SORT_PUBLISHER_UP 			= 13;
	public final static int DOCUMENT_SORT_PUBLISHER_DOWN		= 14;

	public final static int DOCUMENT_SORT_CREATION_DATE_UP   	= 15;
	public final static int DOCUMENT_SORT_CREATION_DATE_DOWN 	= 16;

	protected boolean notuptodate = false;
	protected boolean showCountCatDocs = false;
    protected boolean searchCategories = false;

	protected CategorySettings categoryInfo = null;

	protected HttpSession session = null;

	protected Integer categoryId = VKCEntity.ID_UNDEFINED;
	protected Integer documentId = VKCEntity.ID_UNDEFINED;
	protected Integer selectedId = VKCEntity.ID_UNDEFINED;
	protected Integer[] showDocumentDetails = new Integer[0];
	protected Integer[] showDocuments = new Integer[0];
	
	protected List accessibleSubCategories = null;
	protected List documentStati = null;
	protected List toBePublishedDocuments = null;
	protected List virtualDocuments = null;
	
	protected String clipboardAction = "";
    protected String searchCategoryName = null;
	protected String searchFromHereText = null;
	protected String searchFromHere = null;
	protected String[] selectedCategoryIds = {};
	protected String[] selectedDocumentIds = {};

	protected VKCCategory category = null;
	protected VKCCountCatDocs accessibleCountCatDocs = null;

	/**
	 * Reset all properties to their default values.
	 *
	 * @param mapping The mapping used to select this instance
	 * @param request The servlet request we are processing
	 */
	public void reset(ActionMapping mapping, HttpServletRequest request) {
		super.reset(mapping, request);		
		notuptodate = false;		
        searchCategories = false;
		category = null;
		categoryId = null;
		documentId = null;
		selectedId = null;
		selectedCategoryIds = new String[0];
		selectedDocumentIds = new String[0];
		clipboardAction = "";
		accessibleSubCategories = null;
		accessibleCountCatDocs = null;
		documentStati = null;
		categoryInfo = (CategorySettings) request.getAttribute("categorySettings");
		showCountCatDocs = false;
		showDocumentDetails = new Integer[0];
		showDocuments = new Integer[0];
        searchFromHereText = getResources().getMessage(getLocale(), "vkc.search.searchFieldText");
        searchCategoryName = getResources().getMessage(getLocale(), "vkc.search.searchFieldText");
		session = request.getSession();

		//Nachsehen ob in der Session Einstellungen für die Sortierung existiert
		if (session.getAttribute("categoryViewCategorySortMode") == null) {
       		session.setAttribute("categoryViewCategorySortMode", new Integer(CATEGORY_SORT_NAME_UP));
		}

		//Nachsehen ob in der Session Einstellungen für die Sortierung existiert
		if (session.getAttribute("categoryViewDocumentSortMode") == null) {
			//Wenn nicht werden die Einstellungen aus dem User-Objekt geholt
        	if (getUser() != null && getUser().getCategoryViewDocumentSortMode() != null) {
            	session.setAttribute("categoryViewDocumentSortMode", getUser().getCategoryViewDocumentSortMode());
        	} else {
            	session.setAttribute("categoryViewDocumentSortMode", new Integer(DOCUMENT_SORT_PUBLISHING_DATE_DOWN));
        	}
		}
	}	
	
	
	public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
		ActionErrors errors = new ActionErrors();
		
		try {
			if (!CategoryUtils.existsCategory(getCategoryId(), VKCCategory.FLAG_DELETED, false)) {
				request.setAttribute(WebShare.INFO_KEY, "vkc.info.categorydeleted");
				setCategoryId(new Integer(VKCCategory.ROOT_CATEGORY_ID));
				notuptodate = true;
			} else if (getDocumentId() != null && getDocumentId().intValue() > 0) {
				VKCDocument document = VKCDocumentSerializer.retrieveDocument(getDocumentId());
				
				if (document  == null || document.getFlag().equals(VKCDocument.FLAG_DELETED)) {
					request.setAttribute(WebShare.INFO_KEY, "vkc.info.documentdeleted");
					notuptodate = true;
				} else if (!document.getTopVersionDocumentId().equals(getDocumentId())) {
					request.setAttribute(WebShare.INFO_KEY, "vkc.info.notuptodate");
					notuptodate = true;
				}
			}
		} catch (Exception e) {
			VKCLogManager.errorLog(this, "", e.getMessage(), e);
			errors.add("error", new ActionError("error.general", e.getMessage()));
		}

		return errors;
	}
	
	public CategorySettings getCategorySettings() {
		if (categoryInfo == null) {
			categoryInfo = WebShare.getCategorySettings();
		}
		
		return categoryInfo;
	}

	public VKCCategory getCategory() throws DBException {
		if (category == null) {
			category = VKCCategorySerializer.retrieveCategory(getCategoryId());
		}

		return category;
	}

	public void reloadCategory() throws DBException {
		category = VKCCategorySerializer.retrieveCategory(getCategoryId());
	}

	public Integer getCategoryId() {
		return categoryId;
	}

	public void setCategoryId(Integer integer) {
		categoryId = integer;
		category = null;
	}

    public List getVirtualDocuments() throws DBException {
		if (virtualDocuments == null) {
			virtualDocuments = new ArrayList();
			virtualDocuments.addAll(DocumentUtils.getVirtualDocuments(getCategoryId(), getUser()));
			documentSort(virtualDocuments, getDocumentSortMode());
		}			

		return virtualDocuments; 	
    }
	
	private void categorySort(List categories, Integer sortMode) {
		int mode = sortMode.intValue();

		Comparator c = null;
		final Collator collator = Collator.getInstance(getUser().getLanguage().getLocale());

		if (mode == CATEGORY_SORT_NAME_UP) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCSubCategory s1 = (VKCSubCategory)o1;
					VKCSubCategory s2 = (VKCSubCategory)o2;
					
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(s1.getName()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(s2.getName()));
                	
                	return key1.compareTo(key2);
				}
			};
		} else if (mode == CATEGORY_SORT_NAME_DOWN) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCSubCategory s1 = (VKCSubCategory)o1;
					VKCSubCategory s2 = (VKCSubCategory)o2;

                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(s1.getName()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(s2.getName()));
                	
                	return key2.compareTo(key1);
				}
			};
		}
		
		Collections.sort(categories, c);		
	}

	private void documentSort(List documents, Integer sortMode) {
		int mode = sortMode.intValue();

		Comparator c = null;
		final Collator collator = Collator.getInstance(getUser().getLanguage().getLocale());

		if (mode == DOCUMENT_SORT_PUBLISHING_DATE_UP) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
					return d1.getPublished().after(d2.getPublished()) ? 1 : 0;
				}
			};
		} else if (mode == DOCUMENT_SORT_PUBLISHING_DATE_DOWN) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
					return d1.getPublished().before(d2.getPublished()) ? 1 : 0;
				}
			};
		} else if (mode == DOCUMENT_SORT_CREATION_DATE_UP) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
					if (d1.getCreationDate() != null && d2.getCreationDate() != null) {
						return d1.getCreationDate().after(d2.getCreationDate()) ? 1 : 0;
					}
					
					return -1;
				}
			};
		} else if (mode == DOCUMENT_SORT_CREATION_DATE_DOWN) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
					if (d1.getCreationDate() != null && d2.getCreationDate() != null) {
						return d1.getCreationDate().before(d2.getCreationDate()) ? 1 : 0;
					}
					
					return -1;
				}
			};
		} else if (mode == DOCUMENT_SORT_TITLE_UP) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d1.getTitle()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d2.getTitle()));
                	
                	return key1.compareTo(key2);
				}
			};
		} else if (mode == DOCUMENT_SORT_TITLE_DOWN) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d1.getTitle()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d2.getTitle()));
                	
                	return key2.compareTo(key1);
				}
			};
		} else if (mode == DOCUMENT_SORT_AUTHOR_UP) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d1.getAuthorName()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d2.getAuthorName()));
                	
                	return key1.compareTo(key2);
				}
			};
		} else if (mode == DOCUMENT_SORT_AUTHOR_DOWN) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d1.getAuthorName()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d2.getAuthorName()));
                	
                	return key2.compareTo(key1);
				}
			};
		} else if (mode == DOCUMENT_SORT_PUBLISHER_UP) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d1.getPublisherName()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d2.getPublisherName()));
                	
                	return key1.compareTo(key2);
				}
			};
		} else if (mode == DOCUMENT_SORT_PUBLISHER_DOWN) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d1.getPublisherName()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d2.getPublisherName()));
                	
                	return key2.compareTo(key1);
				}
			};
		} else if (mode == DOCUMENT_SORT_SIZE_UP) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
					return d1.getDocSize().longValue() > d2.getDocSize().longValue() ? 1 : 0;
				}
			};
		} else if (mode == DOCUMENT_SORT_SIZE_DOWN) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
					return d1.getDocSize().longValue() < d2.getDocSize().longValue() ? 1 : 0;
				}
			};
		} else if (mode == DOCUMENT_SORT_TYPE_UP) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d1.getDocumentType().getExtension()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d2.getDocumentType().getExtension()));
                	
                	return key1.compareTo(key2);
				}
			};
		} else if (mode == DOCUMENT_SORT_TYPE_DOWN) {
			c = new Comparator() {
				public int compare(Object o1, Object o2) {
					VKCDocument d1 = (VKCDocument)o1;
					VKCDocument d2 = (VKCDocument)o2;
					
                	CollationKey key1 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d1.getDocumentType().getExtension()));
                	CollationKey key2 = collator.getCollationKey(VKCStringUtils.decodeXmlEntities(d2.getDocumentType().getExtension()));
                	
                	return key2.compareTo(key1);
				}
			};
		}
		
		Collections.sort(documents, c);		
	}

	public boolean getHasChildObjects() throws DBException {
		if (getCategory() == null) {
			return false;
		}

		return !getAccessibleSubcategories().isEmpty() || !getCategory().getDocuments().isEmpty();
	}
		
	public String getClipboardAction() {
		return clipboardAction;
	}

	public void setClipboardAction(String s) {
		clipboardAction = StringUtils.normalize(s);
	}

	public String[] getSelectedCategoryIds() {
		return selectedCategoryIds;
	}

	public String[] getSelectedDocumentIds() {
		return selectedDocumentIds;
	}

	public void setSelectedCategoryIds(String[] strings) {
		selectedCategoryIds = strings;
	}

	public void setSelectedDocumentIds(String[] strings) {
		selectedDocumentIds = strings;
	}

	public String getSearchFromHere() {
		return searchFromHere;
	}

	public String getSearchFromHereText() {
		return searchFromHereText;
	}

	public void setSearchFromHere(String s) {
		searchFromHere = StringUtils.normalize(s);
	}

	public void setSearchFromHereText(String s) {
		searchFromHereText = StringUtils.normalize(s);
	}

	public Integer getDocumentId() {
		return documentId;
	}

	public void setDocumentId(Integer i) {
		documentId = i;
	}

    public List getAccessibleSubcategories() throws DBException {
        if (accessibleSubCategories == null) {
	        if (getUser() != null && getCategory() != null) {
	            accessibleSubCategories = getCategory().getAccessibleSubCategories(getUser());
	            categorySort(accessibleSubCategories, getCategorySortMode());
	        } else {
	            accessibleSubCategories = new ArrayList();
	        }
        }
        
        return accessibleSubCategories;
    }

    public VKCCountCatDocs getAccessibleCountCatDocs() throws DBException {
        if (accessibleCountCatDocs == null) {
	        if (getUser() != null && getCategory() != null) {
	            accessibleCountCatDocs = getCategory().getAccessibleCountCatDocs(getUser());
	        } else {
	            accessibleCountCatDocs = new VKCCountCatDocs();
	        }
        }
        
        return accessibleCountCatDocs;
    }

    public VKCCountCatDocs getAccessibleSubCountCatDocs(String id) throws DBException {
        return (VKCCountCatDocs)getAccessibleCountCatDocs().getSubCatDocs().get(Integer.valueOf(id));
    }

	public List getDocumentStati() {
		if (documentStati == null) {
		    documentStati = VKCDocumentStatusSerializer.getDocumentStati();
		}
		
		return documentStati;
	}
	
	public VKCDocumentStatus getDocumentStatus(Integer id) {
		for(Iterator iter = getDocumentStati().iterator(); iter.hasNext();) {
			VKCDocumentStatus ds = (VKCDocumentStatus)iter.next();

			if (ds.getStatus().equals(id)) {
				return ds;
			}
		}
		
		return null;
	}
	
	public boolean getShowCountCatDocs() {
		return showCountCatDocs;
	}

	public void setShowCountCatDocs(boolean b) {
		showCountCatDocs = b;
	}
	
	public Integer[] getShowDocuments() {
		return showDocuments;
	}

	public void setShowDocuments(Integer[] list) {
		showDocuments = list;
	}

	public boolean getShowDocs(int i) {
		List ids = Arrays.asList(getShowDocuments());

		return ids.contains(new Integer(i));
	}

	public Integer[] getShowDocumentDetails() {
		return showDocumentDetails;
	}

	public void setShowDocumentDetails(Integer[] list) {
		showDocumentDetails = list;
	}

	public boolean getShowDocDetails(int i) {
		List ids = Arrays.asList(getShowDocumentDetails());

		return ids.contains(new Integer(i));
	}

	public Integer getSelectedId() {
		return selectedId;
	}

	public void setSelectedId(Integer i) {
		selectedId = i;
	}

	public Integer getCategorySortMode() {
		return (Integer)session.getAttribute("categoryViewCategorySortMode");
	}

	public void setCategorySortMode(Integer i) {
	    session.setAttribute("categoryViewCategorySortMode", i);
	}
	
	public Integer getDocumentSortMode() {
	    return (Integer)session.getAttribute("categoryViewDocumentSortMode");
	    
	}

	public void setDocumentSortMode(Integer i) {
	    session.setAttribute("categoryViewDocumentSortMode", i);
	}
	
	public boolean getHasDocuments() throws DBException {
		return !getCategory().getDocuments().isEmpty() || !getVirtualDocuments().isEmpty() || !getToBePublishedDocuments().isEmpty();
	}
	
	public List getDocuments() throws DBException {
		List documents = getCategory().getDocuments();
		documentSort(documents, getDocumentSortMode());
		
		return documents;
	}
	
	public List getToBePublishedDocuments() throws DBException {
	    if (toBePublishedDocuments == null) {
		    toBePublishedDocuments = new ArrayList(VKCDocumentSerializer.getToBePublishedDocuments(getUser(), getCategoryId()));
			documentSort(toBePublishedDocuments, getDocumentSortMode());
		}
		
		return toBePublishedDocuments;
	}
	
	public boolean isQuickSearchAction(HttpServletRequest request) {
	    if (request.getParameter("action.search") != null && !isEmpty(getSearchFromHereText())) {
	        return true;
	    }
	    
	    return false;
	}

    public boolean isQuickSearchCategoryAction(HttpServletRequest request) {
        if (request.getParameter("action.search.category") != null && !isEmpty(getSearchCategoryName())) {
            return true;
        }
        
        return false;
    }

	public boolean isNotuptodate() {
		return notuptodate;
	}

	public void setNotuptodate(boolean notuptodate) {
		this.notuptodate = notuptodate;
	}
    
    public String getLockUserInfo(String documentId) {
        String lockUser = vkc.webdav.WebDavServlet.getLockUserName(new Integer(documentId));
        
        if (lockUser != null) {
            return getResources().getMessage(getLocale(), "vkc.string.lockUserInfo", lockUser);
        }
        
        return "";
    }

	public String getSearchCategoryName() {
		return searchCategoryName;
	}

	public void setSearchCategoryName(String searchCategoryName) {
		this.searchCategoryName = searchCategoryName;
	}

	/*
	 * falls false wird schnelle Suche nach Dokumenten gemacht,
	 * sonst sucht man nach Kategorien
	 */
	public boolean isSearchCategories() {
		return searchCategories;
	}

	/*
	 * falls false wird schnelle Suche nach Dokumenten gemacht,
	 * sonst sucht man nach Kategorien
	 */
	public void setSearchCategories(boolean searchCategories) {
		this.searchCategories = searchCategories;
	}
    
    public String getEncodedSearchCategoryQuery() {
        if (!isEmpty(getSearchCategoryName())) {
            String query = VKCStringUtils.filterUnicodeChars(getSearchCategoryName());
            query = VKCStringUtils.base64Encode(query);
            
            return query;
        }
        
        return "";
    }
}