/*
 * $Id: SearchRelatedDocumentsAction.java,v 1.21 2006/12/18 15:50:22 lawern Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 * 
 * $Log: SearchRelatedDocumentsAction.java,v $
 * Revision 1.21  2006/12/18 15:50:22  lawern
 * Korowas Änderungen überarbeitet.
 *
 * Revision 1.19  2006/10/12 12:15:08  marbobo
 * + Ranking für das ähnlichste Dokument wird kleiner 1.0 genommen falls vorhanden
 *
 * Revision 1.18  2006/10/10 17:10:40  marbobo
 * + Ähnlichkeitssuche optimiert (alle Ergebnisse werden bzgl. des Ähnlichsten Dokuments (Rank 1) normiert und alle mit Rank kleiner als 0.1 verworfen)
 *
 * Revision 1.17  2006/09/29 21:10:07  marbobo
 * + Sucheoptimiert
 *
 * Revision 1.16  2006/09/07 14:11:13  marbobo
 * + Zurück-Button implementiert
 *
 * Revision 1.15  2005/08/14 18:14:02  marbobo
 * + Alternative-Sicht implementiert
 *
 * Revision 1.14  2004/11/02 21:42:30  marbobo
 * + Einige Funktionen für Gast-Benutzer gesperrt
 * + WebShare.LOGIN_PAGE mit WebShare.getLoginPage() ersetzt
 *
 * Revision 1.13  2004/07/20 08:36:54  jonyp
 * added copyright info + cvs log
 *
 */
 
package vkc.search.action;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;

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

import org.apache.lucene.search.Hits;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import vkc.search.Search;
import vkc.search.SearchResultEntry;
import vkc.search.form.SearchRelatedDocumentsForm;

/**
 * Klasse führt die Suche nach ähnlichen Dokumenten durch
 * 
 * <p></p>
 *
 * @author bigmac
 */
public final class SearchRelatedDocumentsAction extends Action {
	private ActionForward DEFAULT_FORWARD_ANCHORRESULT = new ActionForward("/templates/${template.name}/search/searchRelatedDocuments.jsp?anchor=results");

    public ActionForward execute( ActionMapping mapping, 
    							  ActionForm f,
        						  HttpServletRequest request, 
        						  HttpServletResponse response  )
    throws Exception {
        SearchRelatedDocumentsForm form = (SearchRelatedDocumentsForm)f;

		if (request.getParameter("action.back") != null) { 
			return handleBackAction(form, request);
		} else if (request.getParameter("action.change.page") != null) {
            return handleChangeCurrentPageAction(form, request);
        } else if (request.getParameter("action.show.document.details") != null) {
			return handleShowDocumentDetailsAction(form, request);
		} else if (request.getParameter("action.hide.document.details") != null) {
			return handleHideDocumentDetailsAction(form, request);
		} else if (request.getParameter("action.show.documents") != null) {
			return handleShowDocumentsAction(form, request);
		} else if (request.getParameter("action.hide.documents") != null) {
			return handleHideDocumentsAction(form, request);
		} else {
			return handleInitialzeAction(form, request);
		}
    }

	private ActionForward handleBackAction(SearchRelatedDocumentsForm form, HttpServletRequest request) {
    	String forwardURL = "/showCategory.do?categoryId=" + form.getCategoryId() + "&anchor=doc" + form.getDocumentId();

    	return new ActionForward(forwardURL, true);
	}

    private ActionForward handleChangeCurrentPageAction(SearchRelatedDocumentsForm form, HttpServletRequest request) throws Exception {
		synchronizeForm(form, request);
        
		return DEFAULT_FORWARD_ANCHORRESULT;
    }

    private ActionForward handleHideDocumentDetailsAction(SearchRelatedDocumentsForm form, HttpServletRequest request) throws Exception {
		List ids = new ArrayList(Arrays.asList(form.getShowDocumentDetails()));
		ids.remove(form.getSelectedId());
		form.setShowDocumentDetails((Integer[])ids.toArray(new Integer[0]));
		synchronizeForm(form, request);

		return new ActionForward("/templates/${template.name}/search/searchRelatedDocuments.jsp?anchor=doc" + form.getSelectedId(), false);
	}

	private ActionForward handleShowDocumentDetailsAction(SearchRelatedDocumentsForm form, HttpServletRequest request) throws Exception {
		List ids = new ArrayList(Arrays.asList(form.getShowDocumentDetails()));
		ids.add(form.getSelectedId());
		form.setShowDocumentDetails((Integer[])ids.toArray(new Integer[0]));
		synchronizeForm(form, request);

		return new ActionForward("/templates/${template.name}/search/searchRelatedDocuments.jsp?anchor=doc" + form.getSelectedId(), false);
	}

	private ActionForward handleHideDocumentsAction(SearchRelatedDocumentsForm form, HttpServletRequest request) throws Exception {
		List ids = new ArrayList(Arrays.asList(form.getShowDocuments()));
		ids.remove(form.getSelectedId());
		form.setShowDocuments((Integer[])ids.toArray(new Integer[0]));
		synchronizeForm(form, request);
		
		return new ActionForward("/templates/${template.name}/search/searchRelatedDocuments.jsp?anchor=doc" + form.getSelectedId(), false);
	}

	private ActionForward handleShowDocumentsAction(SearchRelatedDocumentsForm form, HttpServletRequest request) throws Exception {
		List ids = new ArrayList(Arrays.asList(form.getShowDocuments()));
		ids.add(form.getSelectedId());
		form.setShowDocuments((Integer[])ids.toArray(new Integer[0]));
		synchronizeForm(form, request);

		return new ActionForward("/templates/${template.name}/search/searchRelatedDocuments.jsp?anchor=doc" + form.getSelectedId(), false);
	}

	private ActionForward handleInitialzeAction(SearchRelatedDocumentsForm form, HttpServletRequest request) throws Exception {
		synchronizeForm(form, request);
		
		return DEFAULT_FORWARD_ANCHORRESULT;
	}

    private void synchronizeForm(SearchRelatedDocumentsForm form, HttpServletRequest request) throws Exception {
		Integer[] positions = new Integer[0];
    	Hits hits = form.getHits();
		
		int hitsSize = hits != null ? hits.length() : 0;
		
		if (hitsSize > 1) {
			HashSet indicies = new HashSet();
			HashSet scores = new HashSet();
			double[] allScores = new double[hitsSize];

			for (int i = 0; i < hitsSize; i++) {
				allScores[i] = hits.score(i);
				scores.add(new Double(allScores[i]));
			}
			
			Double[] orderedScores = (Double[])scores.toArray(new Double[0]);
			Arrays.sort(orderedScores);
			double maxScore = 1.0;
			double minScore = 0.1;
			
			for (int i = orderedScores.length - 2; i >= 0; i--) {
				if (orderedScores[i].doubleValue() < 1.0) {
					maxScore = orderedScores[i].doubleValue();
					break;
				}
			}
			
			for (int i = 0; i < allScores.length; i++) {
				double score = allScores[i];
				
				if (score / maxScore < minScore) {
					continue;
				}
				
				indicies.add(new Integer(i));
			}
			
			positions = (Integer[])indicies.toArray(new Integer[0]);
			
			Arrays.sort(positions);
			hitsSize = positions.length;
		} else if (hitsSize == 1) {
			positions = new Integer[] {new Integer(0)};
		}
	    
		Integer resultsPerPage = new Integer(form.getSelectedNumberOfResultsPerPage());
		Integer currentPageId = form.getCurrentResultPageId();
	    int startIndex = resultsPerPage.intValue() * ((currentPageId.intValue() > 1) ? (currentPageId.intValue() - 1) : 0);
		int endIndex = startIndex + resultsPerPage.intValue();

		form.setHitsCount(new Integer(hitsSize));
		form.setStartIndex(new Integer(startIndex));
			
		if (hitsSize < endIndex) {
			endIndex = hitsSize;
		}
			
		List results = new ArrayList();
			
		for (int i = startIndex; i < endIndex; i++) {
			results.add(SearchResultEntry.toSearchResultEntry(hits.doc(positions[i].intValue()), hits.score(positions[i].intValue())));
		}
        Search.searchFinished();

	    //Anzahl der Ergebnisseiten ermitteln
	    Integer pageCount = new Integer(((form.getHitsCount().intValue() % resultsPerPage.intValue()) == 0)
	              					    ? (form.getHitsCount().intValue() / resultsPerPage.intValue())
	                                    : ((form.getHitsCount().intValue() / resultsPerPage.intValue()) + 1));

	    form.setPageCount(pageCount);
	    form.setResults(results);
   }
}