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

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

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.action.ActionMapping;

import vkc.db.serializer.VKCCategorySerializer;

import vkc.exception.DBException;
import vkc.util.StringUtils;
import vkc.util.VKCStringUtils;

public final class SearchCategoryForm extends BasicActionForm {
    private Integer categoryId = null;
    private String searchQuery = "";

    private List categories = null;

    /**
     * Reset der Eingabefelder auf Defaultwerte
     * 
     * @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);
        categoryId = null;
        searchQuery = "";
        categories = null;
    }

    public List getCategories() throws DBException {
        if (categories == null) {
            if (!isEmpty(getSearchQuery())) {
                String[] xqueries = getDatabaseXmlEntityQueries();
                String[] queries = new String[1 + xqueries.length];
                queries[0] = getDatabaseQuery();
                
                for (int i = 0; i < xqueries.length; i++) {
                    queries[i + 1] = xqueries[i];
                }
                
                categories = VKCCategorySerializer.retrieveCategoriesForUserByQueries(getCategoryId(), getUser(), queries);
            } else {
                categories = new ArrayList();
            }
        }
        
        return categories;
    }

    public Integer getCategoryId() {
        return categoryId;
    }

    public void setCategoryId(Integer categoryId) {
        this.categoryId = categoryId;
    }

    public String getSearchQuery() {
        return searchQuery;
    }

    public void setSearchQuery(String s) {
        searchQuery = StringUtils.normalize(s);
    }

    private String getDatabaseQuery() {
        if (isEmpty(getSearchQuery())) {
            return "";
        }

        String query = VKCStringUtils.filterUnicodeChars(clearAloneEscapeChars(getSearchQuery()));
        query = StringUtils.replaceToken(query, "%", "\\%");
        query = StringUtils.replaceToken(query, "_", "\\_");
        query = replaceLiterals(query, "*", "%");
        query = replaceLiterals(query, "?", "_");
        query = replaceLiterals(query, "\\*", "*");
        query = replaceLiterals(query, "\\?", "?");

        return query;
    }

    private String[] getDatabaseXmlEntityQueries() {
        if (isEmpty(getSearchQuery())) {
            return new String[] {};
        }

        String queries[] = new String[5];
        String query = VKCStringUtils.filterUnicodeChars(clearAloneEscapeChars(getSearchQuery()));
        query = StringUtils.replaceToken(query, "%", "\\%");
        query = StringUtils.replaceToken(query, "_", "\\_");
        query = replaceLiterals(query, "*", "%");
        
        for (int i = 0; i < queries.length; i++) {
            String replacement = "&#";
            
            for (int j = 0; j < i + 1; j++) {
                replacement += "_";
            }
            
            replacement += ";";
            queries[i] = replaceLiterals(query, "?", replacement);
            queries[i] = replaceLiterals(queries[i], "\\*", "*");
            queries[i] = replaceLiterals(queries[i], "\\?", "?");
            queries[i] = queries[i];
        }

        return queries;
    }

    private String clearAloneEscapeChars(String str) {
        StringBuffer sb = new StringBuffer();
        int index = 0;

        while (true) {
            index = str.indexOf("\\");

            if (index < 0) {
                break;
            }

            if (str.startsWith("*", index + 1) || str.startsWith("?", index + 1) || str.startsWith("\\", index + 1)) {
                sb.append(str.substring(0, index + 2));
                str = str.substring(index + 2);
            } else {
                sb.append(str.substring(0, index));
                str = str.substring(index + 1);
            }
        }

        return sb.toString() + str;
    }

    private String replaceLiterals(String str, String literal, String replacement) {
        StringBuffer sb = new StringBuffer();
        int index = 0;

        while (true) {
            index = str.indexOf(literal);

            if (index < 0) {
                break;
            }

            int escapeCount = 0;

            for (int i = index - 1; i >= 0; i--) {
                if (str.charAt(i) == '\\') {
                    escapeCount++;
                } else {
                    break;
                }
            }

            if (escapeCount % 2 == 1) {
                sb.append(str.substring(0, index + literal.length()));
            } else {
                sb.append(str.substring(0, index));
                sb.append(replacement);
            }

            str = str.substring(index + literal.length());
        }

        return sb.toString() + str;
    }
}