/*
 * $Id: SysLinkAction.java,v 1.22 2007/08/08 12:14:51 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: SysLinkAction.java,v $
 * Revision 1.22  2007/08/08 12:14:51  marbobo
 * + License-Funktionalität komplett umgeschrieben
 * + Bugfix bzgl. Beschreibungsfelder von Entitäten
 * + Bugfix mailing
 *
 * Revision 1.21  2007/07/20 14:18:03  marbobo
 * + Max. Anzahl von Benutzern die im System gleichzeitig angemeldet sein dürfen ist jetzt konfiguriebar
 *
 * Revision 1.20  2006/10/04 03:14:32  marbobo
 * + Vollständige Unterstützung für Templates implementiert
 * + Alles von Virtoweb auf ProCoBa umgestellt
 *
 * Revision 1.19  2006/05/13 19:04:28  marbobo
 * + Optimierungen bzgl. der verschiedenen Sichten
 *
 * Revision 1.18  2006/04/29 18:39:45  marbobo
 * + Refactoriengs und eine Ausgaben vereinheitlicht
 *
 * Revision 1.17  2006/02/27 16:15:58  marbobo
 * + Systemsichten hinzugefügt
 * + SysLinks angepasst
 * + Benutzer können falls gewünscht Dokumentqueries anlegen
 *
 * Revision 1.16  2005/11/23 14:56:13  marbobo
 * - "dynamische Gruppen zuordnen" entfernt
 *
 * Revision 1.15  2005/09/19 12:50:28  marbobo
 * + Bei Ungültigen Verweisen auf Dokumente und Kategorien wird nun eine Info-Meldung ausgegeben
 *
 * Revision 1.14  2005/09/01 13:11:51  marbobo
 * + Einige Anpassung zur SysLink
 *
 * Revision 1.13  2005/09/01 08:31:58  korowa
 * Es werden mehrere URL angeboten, welche direkten Zugriff auf Dateien
 *  und automatisches Anmelden als Gast erlauben.
 *
 * Revision 1.12  2005/08/31 11:04:12  marbobo
 * + Bugfix
 *
 * Revision 1.11  2005/08/30 13:30:28  jonyp
 * ask if a documents category requested is in the trash
 *
 * Revision 1.10  2005/08/30 13:23:47  jonyp
 * ask if a category requested is in the trash
 *
 * Revision 1.9  2004/12/08 14:42:44  marbobo
 * + Bei Dokumentlinks wird zur aktuellsten Version verwiesen
 *
 * Revision 1.8  2004/11/10 15:28:37  koppy
 * +accessLog
 *
 * Revision 1.7  2004/11/10 15:02:45  koppy
 * Projektweite Überarbeitung von Error-Logs, Stacktraces,..
 *
 * Revision 1.6  2004/10/28 19:44:00  marbobo
 * + Anpassung wegen Loginseite
 *
 * Revision 1.5  2004/09/05 19:17:28  marbobo
 * + Redirectanpassung ( Loginseite )
 * + Bugfix
 *
 * Revision 1.4  2004/04/01 20:49:08  marbobo
 * + getVirtowebSysLink()
 *
 * Revision 1.3  2004/03/30 20:33:32  marbobo
 * Externer-Link-Aufruf überarbeitet
 *
 * Revision 1.2  2004/02/18 14:52:09  marbobo
 * /sysLink.do anpassung
 *
 * Revision 1.1  2004/02/18 01:17:20  marbobo
 * Initiale Version
 *
 */
package vkc.view.action;

import java.io.UnsupportedEncodingException;
import java.sql.Timestamp;
import java.util.Date;

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

import org.apache.struts.Globals;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import vkc.db.entities.VKCCategory;
import vkc.db.entities.VKCDocument;
import vkc.db.entities.VKCLanguage;
import vkc.db.entities.VKCLicense;
import vkc.db.entities.VKCUser;
import vkc.db.serializer.VKCLanguageSerializer;
import vkc.db.serializer.VKCLicenseSerializer;
import vkc.db.serializer.VKCSysParameterSerializer;
import vkc.exception.DBException;
import vkc.misc.VKCLogManager;
import vkc.util.ServletUtils;
import vkc.util.CategoryUtils;
import vkc.util.StringUtils;
import vkc.view.PageId;
import vkc.view.WebShare;
import vkc.view.bean.UserTrackingInfo;
import vkc.view.form.SysLinkForm;

/**
 * @author marbobo
 */
public class SysLinkAction extends Action {

	public ActionForward execute(ActionMapping mapping, 
	        					 ActionForm f,
	        					 HttpServletRequest request,
	        					 HttpServletResponse response)
	throws Exception {
		SysLinkForm form = (SysLinkForm)f;	
		String actionPath = null;
		VKCUser user = ServletUtils.getUser(request);

		if (user == null) {
		    if (!SysLinkForm.LOGINTYPE_GUEST_USER.equals(form.getLoginType())) {
			    // Session ist abgelaufen oder User ist nicht angemeldet
				actionPath = WebShare.getLoginPage() + "?linkType=" + form.getLinkType() + "&objectId=" + form.getObjectId();
				VKCLogManager.accessLog(request.getRemoteHost(), null, null, request.getContextPath() + "/sysLink.do?linkType=" + form.getLinkType() + "&objectId=" + form.getObjectId(), 403, 0);

				return new ActionForward(actionPath, true);
		    }

            int maxAllowedUsers = VKCSysParameterSerializer.retrieveIntValue("LOGIN", "MaxAllowedUsers", 0);
            int activeUsersCount = WebShare.getActiveUsers().length;
            
            if (maxAllowedUsers > 0 && activeUsersCount >= maxAllowedUsers) {
                if (request.getLocale() == null) {
                    VKCLanguage lang = VKCLanguageSerializer.getDefaultLanguage();
                    setLocale(request, lang.getLocale());
                }

                //Maximale Anzahl an erlaubten Benutzer wurde überschritten
                actionPath = WebShare.getLoginPage() + "?linkType=" + form.getLinkType() + "&objectId=" + form.getObjectId();
                VKCLogManager.accessLog(request.getRemoteHost(), null, null, request.getContextPath() + "/sysLink.do?linkType=" + form.getLinkType() + "&objectId=" + form.getObjectId(), 403, 0);
                ActionErrors errors = new ActionErrors();
                errors.add("maxAllowedUsers", new ActionError("error.maxallowedusers.exceeded"));
                request.getSession().setAttribute(Globals.ERROR_KEY, errors);

                return new ActionForward(actionPath, true);
            }

            HttpSession session = request.getSession();
	        user = VKCUser.createGuestUser();
            VKCLicense license = VKCLicenseSerializer.retrieveActiveLicense(); 
            
            if (Integer.parseInt(WebShare.getSysParameterValue("LICENSE", "EnableLicensemanagement", "0")) != 0 &&  license != null) {
                request.getSession().setAttribute(WebShare.TEMP_USER_KEY, user);
                
                return new ActionForward("/loginLicense.do", false);
            }

	        // alle Objekte aus der Session entfernen
	        ServletUtils.removeSessionAttributes(session);

	        if (request.getLocale() == null) {
	        	VKCLanguage lang = VKCLanguageSerializer.getDefaultLanguage();
	        	user.setLanguage(lang);
	            setLocale(request, lang.getLocale());
	        } else {
	            VKCLanguage lang = VKCLanguageSerializer.getLanguageByShortName(request.getLocale().getLanguage());
	            
	            if (lang != null) {
	                user.setLanguage(lang);
	                setLocale(request, lang.getLocale());
	            } else {
	            	lang = VKCLanguageSerializer.getDefaultLanguage();
	            	user.setLanguage(lang);
	                setLocale(request, lang.getLocale());
	            }
	        }

            Timestamp loginTime = new Timestamp(System.currentTimeMillis());
            user.setMostRecentLogin(loginTime);
	        session.setAttribute(WebShare.USER_KEY, user);
	        session.setAttribute(WebShare.LOCALE_KEY, user.getLanguage().getLocale());

	        String log = "User 'guest' logged on in session " + session.getId() + " with locale: " + user.getLanguage().getLocale();

	        VKCLogManager.infoLog(this, log);

			UserTrackingInfo bean = new UserTrackingInfo (user.getUserId(),
			                                              user.getLastnameLabel(),
			        									  request.getSession(),
			        									  request.getRemoteAddr(),
			        									  new Date(loginTime.getTime()));

			session.setAttribute(WebShare.USER_TRACKING_KEY, bean);
	        session.setAttribute(WebShare.SYSTEMVIEWTYPEID_KEY, user.getSystemViewTypeId());
		}

		if (form.isValidSysLink()) {
			if (form.getLinkType().equals(SysLinkForm.CATEGORY_LINK)) {
				actionPath = getCategoryLinkPath(form, request, user);
			} else if (form.getLinkType().equals(SysLinkForm.DOCUMENT_LINK)) {
				actionPath = getDocumentLinkPath(form, request, user);
			} else if (form.getLinkType().equals(SysLinkForm.DOCUMENT_OPEN_LINK)) {
				actionPath = getDocumentOpenLinkPath(form, request, user);
			} else if (form.getLinkType().equals(SysLinkForm.PROCOBA_FUNCTIONAL_LINK)) {
				actionPath = getProcobaFunctionalLinkPath();
			} else if (form.getLinkType().equals(SysLinkForm.PROCOBA_PROJECT_LINK)) {
				actionPath = getProcobaProjectLinkPath();
			} else {
				actionPath = WebShare.HOME_PAGE + "?sysLinkMessageKey=vkc.info.syslink.invalid";
			}
		} else {
			actionPath = WebShare.HOME_PAGE + "?sysLinkMessageKey=vkc.info.syslink.invalid";
		}
		
		ActionForward forward = new ActionForward(actionPath, true);
		
		return forward;
	}

	private String getCategoryLinkPath(SysLinkForm form, HttpServletRequest request, VKCUser user) throws DBException {
		String actionPath = "";
		Integer viewId = getSystemViewTypeId(request, user);
		VKCCategory category = form.getCategory(form.getObjectId());
		
		if (PageId.CATEGORY_VIEW.equals(viewId) || user.hasAdminPrivileges() || user.isAllowManageSystemViewType()) {
			actionPath = getCategoryPath(form, category);
			
			if (StringUtils.isEmpty(actionPath)) {
				actionPath = WebShare.HOME_PAGE + "?sysLinkMessageKey=vkc.info.category.nomore.exist";
			}
		} else if (PageId.FUNCTIONAL_VIEW.equals(viewId)) {
			actionPath = getCategoryFunctionalPath(form, category);
			
			if (StringUtils.isEmpty(actionPath)) {
				actionPath = getCategoryProjectPath(form, category);

				if (StringUtils.isEmpty(actionPath)) {
					actionPath = WebShare.HOME_PAGE + "?procoba=true&functionalView=true&sysLinkMessageKey=vkc.info.category.nomore.exist";
				}
			}
		} else if (PageId.PROJECT_VIEW.equals(viewId)) {
			actionPath = getCategoryProjectPath(form, category);

			if (StringUtils.isEmpty(actionPath)) {
				actionPath = getCategoryFunctionalPath(form, category);
				
				if (StringUtils.isEmpty(actionPath)) {
					actionPath = WebShare.HOME_PAGE + "?procoba=true&projectView=true&sysLinkMessageKey=vkc.info.category.nomore.exist";
				}
			}
		}
		
		return actionPath;
	}

	private String getCategoryProjectPath(SysLinkForm form, VKCCategory category) throws DBException {
		String actionPath = "";
		Integer projectRootId = new Integer(VKCSysParameterSerializer.getProjectsRootCategoryId());

		if (category != null && !CategoryUtils.isInTrash(form.getObjectId()) && CategoryUtils.isInTree(projectRootId, category.getCategoryId()) && !projectRootId.equals(category.getCategoryId())) {
			Integer projectViewId = getProjectViewId(category.getCategoryId());

			actionPath = WebShare.HOME_PAGE + 
						 "?procoba=true&projectView=true" + 
						 "&projectId=" + projectViewId +
						 "&subfolderId=" + category.getCategoryId();
		}
		
		return actionPath;
	}

	private String getCategoryFunctionalPath(SysLinkForm form, VKCCategory category) throws DBException {
		String actionPath = "";
		Integer functionalRootId = new Integer(VKCSysParameterSerializer.getFunctionalViewsRootCategoryId());

		if (category != null && !CategoryUtils.isInTrash(form.getObjectId()) && CategoryUtils.isInTree(functionalRootId, category.getCategoryId()) && !functionalRootId.equals(category.getCategoryId())) {
			Integer functionalViewId = getFunctionalViewId(category.getCategoryId());
			
			actionPath = WebShare.HOME_PAGE + 
						 "?procoba=true&functionalView=true" + 
						 "&functionalViewId=" + functionalViewId +
						 "&subfolderId=" + category.getCategoryId();
		}
		
		return actionPath;
	}

	private String getCategoryPath(SysLinkForm form, VKCCategory category) throws DBException {
		String actionPath = "";

		if (category != null && !CategoryUtils.isInTrash(form.getObjectId())) {
			actionPath = WebShare.HOME_PAGE + "?categoryId=" + category.getCategoryId();
		}
		
		return actionPath;
	}

	private String getDocumentLinkPath(SysLinkForm form, HttpServletRequest request, VKCUser user) throws DBException {
		String actionPath = "";
		Integer viewId = getSystemViewTypeId(request, user);
		VKCDocument document = form.getDocument(form.getObjectId());
		
		if (PageId.CATEGORY_VIEW.equals(viewId) || user.hasAdminPrivileges() || user.isAllowManageSystemViewType()) {
			actionPath = getDocumentPath(form, document);
			
			if (StringUtils.isEmpty(actionPath)) {
				actionPath = WebShare.HOME_PAGE + "?sysLinkMessageKey=vkc.info.document.nomore.exist";
			}
		} else if (PageId.FUNCTIONAL_VIEW.equals(viewId)) {
			actionPath = getDocumentFunctionalPath(form, document);

			if (StringUtils.isEmpty(actionPath)) {
				actionPath = getDocumentProjectPath(form, document);

				if (StringUtils.isEmpty(actionPath)) {
					actionPath = WebShare.HOME_PAGE + "?procoba=true&functionalView=true&sysLinkMessageKey=vkc.info.document.nomore.exist";
				}
			}
		} else if (PageId.PROJECT_VIEW.equals(viewId)) {
			actionPath = getDocumentProjectPath(form, document);

			if (StringUtils.isEmpty(actionPath)) {
				actionPath = getDocumentFunctionalPath(form, document);

				if (StringUtils.isEmpty(actionPath)) {
					actionPath = WebShare.HOME_PAGE + "?procoba=true&projectView=true&sysLinkMessageKey=vkc.info.document.nomore.exist";
				}
			}
		}

		return actionPath;
	}

	private String getDocumentProjectPath(SysLinkForm form, VKCDocument document) throws DBException {
		String actionPath = "";
		Integer projectRootId = new Integer(VKCSysParameterSerializer.getProjectsRootCategoryId());
		
		if (document != null) {
			if (document.getCategoryId() != null && !CategoryUtils.isInTrash(document.getCategoryId()) && CategoryUtils.isInTree(projectRootId, document.getCategoryId()) && !projectRootId.equals(document.getCategoryId())) {
				Integer projectViewId = getProjectViewId(document.getCategoryId());
				
				actionPath = WebShare.HOME_PAGE + 
							 "?procoba=true&projectView=true" + 
							 "&projectId=" + projectViewId +
							 "&subfolderId=" + document.getCategoryId() +
							 "&anchor=doc" + document.getDocumentId();
			} else {
			    document = form.getTopDocument(document.getDocumentId());
			    
			    if (document != null && !CategoryUtils.isInTrash(document.getCategoryId()) && CategoryUtils.isInTree(projectRootId, document.getCategoryId()) && !projectRootId.equals(document.getCategoryId())) {
					Integer projectViewId = getProjectViewId(document.getCategoryId());
					
					actionPath = WebShare.HOME_PAGE + 
								 "?procoba=true&projectView=true" + 
								 "&projectId=" + projectViewId +
								 "&subfolderId=" + document.getCategoryId() +
								 "&anchor=doc" + document.getDocumentId();
			    }
			}
		}
		
		return actionPath;
	}

	private String getDocumentFunctionalPath(SysLinkForm form, VKCDocument document) throws DBException {
		String actionPath = "";
		Integer functionalRootId = new Integer(VKCSysParameterSerializer.getFunctionalViewsRootCategoryId());
		
		if (document != null) {
			if (document.getCategoryId() != null && !CategoryUtils.isInTrash(document.getCategoryId()) && CategoryUtils.isInTree(functionalRootId, document.getCategoryId()) && !functionalRootId.equals(document.getCategoryId())) {
				Integer functionalViewId = getFunctionalViewId(document.getCategoryId());
				
				actionPath = WebShare.HOME_PAGE + 
							 "?procoba=true&functionalView=true" + 
							 "&functionalViewId=" + functionalViewId +
							 "&subfolderId=" + document.getCategoryId() +
							 "&anchor=doc" + document.getDocumentId();
			} else {
			    document = form.getTopDocument(document.getDocumentId());
			    
			    if (document != null && !CategoryUtils.isInTrash(document.getCategoryId()) && CategoryUtils.isInTree(functionalRootId, document.getCategoryId()) && !functionalRootId.equals(document.getCategoryId())) {
					Integer functionalViewId = getFunctionalViewId(document.getCategoryId());
					
					actionPath = WebShare.HOME_PAGE + 
								 "?procoba=true&functionalView=true" + 
								 "&functionalViewId=" + functionalViewId +
								 "&subfolderId=" + document.getCategoryId() +
								 "&anchor=doc" + document.getDocumentId();
			    }
			}
		}
		
		return actionPath;
	}

	private String getDocumentPath(SysLinkForm form, VKCDocument document) throws DBException {
		String actionPath = "";
		
		if (document != null) {
			if (document.getCategoryId() != null && !CategoryUtils.isInTrash(document.getCategoryId())) {
			    actionPath = WebShare.HOME_PAGE + "?categoryId=" + document.getCategoryId() + "&anchor=doc" + document.getDocumentId();
			} else {
			    document = form.getTopDocument(document.getDocumentId());
			    
			    if (document != null && !CategoryUtils.isInTrash(document.getCategoryId())) {
				    actionPath = WebShare.HOME_PAGE + "?categoryId=" + document.getCategoryId() + "&anchor=doc" + document.getDocumentId();
			    }
			}
		}

		return actionPath;
	}

	private String getDocumentOpenLinkPath(SysLinkForm form, HttpServletRequest request, VKCUser user) throws UnsupportedEncodingException, DBException {
		String actionPath = "";
		VKCDocument document = form.getDocument(form.getObjectId());
		
		if (document != null) {
			if (document.getCategoryId() != null && !CategoryUtils.isInTrash(document.getCategoryId())) {
			    actionPath = document.getDisplayURI();
			    actionPath += ";jsessionid=";
			    actionPath += request.getSession().getId();
			} else {
			    document = form.getTopDocument(document.getDocumentId());
			    
			    if (document != null && !CategoryUtils.isInTrash(document.getCategoryId())) {
				    actionPath = document.getDisplayURI();
				    actionPath += ";jsessionid=";
				    actionPath += request.getSession().getId();
			    } else {
					actionPath = WebShare.HOME_PAGE + "?sysLinkMessageKey=vkc.info.document.nomore.exist";
			    }
			}
		} else {
			actionPath = WebShare.HOME_PAGE + "?sysLinkMessageKey=vkc.info.document.nomore.exist";
		}

		return actionPath;
	}

	private String getProcobaFunctionalLinkPath() {
		String actionPath = "";
		actionPath = WebShare.HOME_PAGE + "?procoba=true&functionalView=true";

		return actionPath;
	}

	private String getProcobaProjectLinkPath() {
		String actionPath = "";
		actionPath = WebShare.HOME_PAGE + "?procoba=true&projectView=true";

		return actionPath;
	}

	private Integer getSystemViewTypeId(HttpServletRequest request, VKCUser user) {
		Integer viewId = (Integer)request.getSession().getAttribute(WebShare.SYSTEMVIEWTYPEID_KEY);
		
		if (viewId == null || PageId.ADMINISTRATION_VIEW.equals(viewId)) {
			viewId = user.getSystemViewTypeId();
			
			if ((PageId.FUNCTIONAL_VIEW.equals(viewId) || PageId.PROJECT_VIEW.equals(viewId)) && !VKCSysParameterSerializer.isProjectManagementEnabled()) {
				viewId = PageId.CATEGORY_VIEW;
			}
		}
		
		return viewId;
	}

	private Integer getFunctionalViewId(Integer categoryId) throws DBException {
		Integer parentId = categoryId;
		Integer functionalRootId = new Integer(VKCSysParameterSerializer.getFunctionalViewsRootCategoryId());

		while (!functionalRootId.equals(parentId)) {
			categoryId = parentId;
			parentId = CategoryUtils.getParentCategoryId(categoryId);
		}
		
		return categoryId;
	}

	private Integer getProjectViewId(Integer categoryId) throws DBException {
		Integer parentId = categoryId;
		Integer projectRootId = new Integer(VKCSysParameterSerializer.getProjectsRootCategoryId());

		while (!projectRootId.equals(parentId)) {
			categoryId = parentId;
			parentId = CategoryUtils.getParentCategoryId(categoryId);
		}
		
		return categoryId;
	}
}