//------------------------------------------------------------------------------
//Copyright (c) 2004, 2007 IBM Corporation.  All Rights Reserved.
//------------------------------------------------------------------------------
package org.eclipse.epf.web.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Locale;
import java.util.Properties;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.search.Hits;
import org.eclipse.epf.web.search.IndexLoader;
import org.eclipse.epf.web.search.IndexSearch;
import org.eclipse.epf.web.search.SearchResources;
import org.eclipse.epf.web.search.utils.DebugUtil;
import org.eclipse.epf.web.search.utils.UNCUtil;
import org.eclipse.epf.web.search.utils.XMLUtil;
import org.eclipse.epf.web.search.utils.XSLTProcessor;

public class SearchServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	private static final String DefaultEncoding = "iso-8859-1";
	private static final String ServletEncoding = "utf-8";

	private int _hitsPerPage = 10;
	private static String _indexPath = null;
	private static String _xslURL;
	private static String _pathDocumentBase;
	private static String _siteFolderName = null;
	private String _currentSearchString;
	private String _queryString;
	private String _webAppName;
	private Hits _hits;
	private int _numHits;
	private int _currentPage;
	private String analyzerName;

	private HttpServletResponse _response;

	// Empty HTML.
	public static final String EMPTY_HTML = "<html></html>"; //$NON-NLS-1$

	private Properties xslParams = null;

	public void init(ServletConfig config) throws ServletException {
		super.init(config);

		try {
			_indexPath = config.getServletContext().getRealPath(
					config.getInitParameter("searchIndex"));
			_xslURL = config.getServletContext().getRealPath(
					config.getInitParameter("xslFile"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		HttpSession session = request.getSession();		
		
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();

		_response = response;
		request.setCharacterEncoding("UTF-8");
		String requestUrl = request.getRequestURL().toString();
		_pathDocumentBase = requestUrl.substring(0, requestUrl.lastIndexOf('/'));		

		try {
			_siteFolderName = IndexLoader.getSiteFolderName(_pathDocumentBase);
			analyzerName = IndexLoader.getAnalyzerName();
			
			synchronized(session) {
				String results;
				String action = request.getParameter("action");
				_webAppName = request.getContextPath();

				if (action != null && action.length() > 0) {
					
					_hits = (Hits) session.getAttribute("hits");					
					_queryString = (String) session.getAttribute("queryString");
					_numHits = ((Integer) session.getAttribute("numHits")).intValue();
					_currentPage = ((Integer) session.getAttribute("currentPage")).intValue();

					if (action.indexOf("next") > -1) {
						results = getPageResult(true);
						session.setAttribute("numHits", new Integer(_numHits));
						session.setAttribute("currentPage", new Integer(_currentPage));
						out.println(results);
					} else {
						results = getPageResult(false);
						session.setAttribute("numHits", new Integer(_numHits));
						session.setAttribute("currentPage", new Integer(_currentPage));
						out.println(results);
					}
				} else {
					
					String searchString = request.getParameter("searchString");
					if (DebugUtil.DEBUG) {
						System.out.println("LD> searchString: " + searchString);
						System.out.println("LD> documentBasePath: " + _pathDocumentBase);
						System.out.println("LD> siteFolderName: " + _siteFolderName);
					}
					
					if (searchString == null || searchString.length() == 0) {
						response.sendError(HttpServletResponse.SC_NO_CONTENT);
						return;
					}
					
					//Bugzilla288074 searchString = convert(searchString);
					
					//searchString = URLEncoder.encode(searchString, "UTF-8");

					String resultsPerPage = request.getParameter("hitsPerPage");
					if (resultsPerPage != null && resultsPerPage.length() > 0) {
						_hitsPerPage = Integer.parseInt(resultsPerPage);
					}
					results = runSearch(searchString);
					session.setAttribute("hits", _hits);
					session.setAttribute("queryString", _queryString);
					session.setAttribute("numHits", new Integer(_numHits));
					session.setAttribute("currentPage", new Integer(_currentPage));
					out.println(results);					
				}
			}

		} catch (Exception ex) {
			// ex.printStackTrace();
			writeOutputError(response.getOutputStream(), SearchResources
					.getString("SearchFailed"), ex);
		}
	}

	private String convert(String str) {
		try {	
			byte[] bytes = str.getBytes(DefaultEncoding);
			String newStr =  new String(bytes, ServletEncoding);
			
			System.out.println("convert " + str + " -> " + newStr);
			return newStr;
			
		} catch (Exception ex) {
			
		}
		
		return str;
	}
	/**
	 * Performs the advanced search.
	 */
	private String runSearch(final String searchString) {

		try {

			_queryString = searchString.replace(':', ' '); // RATLC00251228

			_currentSearchString = IndexSearch.detectHyphenated(_queryString); // wordBuffer.toString();

			if (_currentSearchString.length() == 0) {
				return EMPTY_HTML;
			}

			boolean safe = runQuery("contents");

			String result = updateOutput(safe);

			return (result == null) ? EMPTY_HTML : result;

		} catch (Exception e) {
			e.printStackTrace();
		}

		return EMPTY_HTML;
	}

	private boolean runQuery(String searchField) {
		boolean result = false;
		//_currentSearchString = "\u57FA\u672C\u539F\u5247";
		try {
			if (DebugUtil.DEBUG) {
				System.out.println("LD> _indexPath: " + _indexPath);//$NON-NLS-1$
				System.out.println("LD> _currentSearchString: " + _currentSearchString);//$NON-NLS-1$
			}
			if (_currentSearchString != null) {
				if (DebugUtil.DEBUG) {
					System.out.println("LD> unicodes: " + 
						escapeUnicodeString(_currentSearchString, false));//$NON-NLS-1$
				}
			}
			
			if (DebugUtil.DEBUG) {
				System.out.println("LD> analyzerName: " + analyzerName);//$NON-NLS-1$
			}
			
			_hits = IndexSearch.search(_indexPath, _currentSearchString, searchField, analyzerName);// new
			if (DebugUtil.DEBUG) {
				System.out.println("LD> _hits: " + 
						(_hits == null ? "null" : Integer.toString(_hits.length())));//$NON-NLS-1$ //$NON-NLS-2$
			}
			
			// SortedHits(hits);

			_numHits = _hits.length();

			result = true;
		} catch (Exception e1) {
			e1.printStackTrace();
			_numHits = 0;
			_hits = null;
		}
		_currentPage = 0;

		return result;
	}

	/**
	 * Updates the results panel with the search output.
	 */
	private String updateOutput(boolean safe) {
		String output = null;

		if (safe) {
			output = generateOutput(_numHits, _currentPage);
		} else {
			_hits = null;
		}

		return output;
	}

	/**
	 * Generates the HTML representation for the given process search hits.
	 */
	private String generateOutput(int numHits, int pageNum) {
		int init = pageNum * _hitsPerPage;
		int max = Math.min(numHits, init + _hitsPerPage);
		boolean nextEnabled = numHits > (_currentPage + 1) * _hitsPerPage;
		boolean prevEnabled = _currentPage > 0;

		if (_hits == null) {
			return null;
		}
		try {

			StringBuffer searchResultXML = new StringBuffer();

			// encodeURL is just planning ahead in case this servlet is ever used in
			// an application that does session tracking. If cookies are turned off,
			// session tracking is usually accomplished by URL rewriting, so all URLs
			// returned by servlets should be sent through encodeURL.

			searchResultXML
					.append("<SearchResult") //$NON-NLS-1$
					.append(" totalHits=\"").append(numHits) //$NON-NLS-1$		
					.append("\" initPageNum=\"").append((init > 0) ? init + 1 : (numHits < 1) ? 0 : 1) //$NON-NLS-1$
					.append("\" maxPageNum=\"").append(max) //$NON-NLS-1$
					.append("\" hitsPerPage=\"").append(_hitsPerPage) //$NON-NLS-1$
					.append("\" nextEnabled=\"").append(nextEnabled) //$NON-NLS-1$
					.append("\" prevEnabled=\"").append(prevEnabled) //$NON-NLS-1$
					.append("\" nextText=\"").append(SearchResources.getString("nextActionText")) //$NON-NLS-1$
					.append("\" prevText=\"").append(SearchResources.getString("previousActionText")) //$NON-NLS-1$
					.append("\" imagePath=\"").append(_pathDocumentBase + "/search/images/") //$NON-NLS-1$
					.append("\" searchString=\"").append(XMLUtil.escape(_queryString)) //$NON-NLS-1$			
					.append("\" nextHref=\"").append(_response.encodeURL(_webAppName + "/SearchServlet?action=next")) //$NON-NLS-1$
					.append("\" prevHref=\"").append(_response.encodeURL(_webAppName + "/SearchServlet?action=prev")) //$NON-NLS-1$
					.append("\">"); //$NON-NLS-1$

			for (int i = init; i < max; i++) {
				Document doc = _hits.doc(i);
				Field url = doc.getField("url"); //$NON-NLS-1$
				Field title = doc.getField("title"); //$NON-NLS-1$
				Field summary = doc.getField("summary"); //$NON-NLS-1$
				Field umaType = doc.getField("uma.type"); //$NON-NLS-1$

				searchResultXML.append("<SearchHit"); //$NON-NLS-1$

				if (url != null) {
					StringBuffer bufferURL = new StringBuffer();
					String strUrl = url.stringValue();
					bufferURL.append(_pathDocumentBase).append(
							strUrl.substring(strUrl.indexOf(_siteFolderName)
									+ _siteFolderName.length()));

					if (strUrl != null) {
						strUrl = XMLUtil.escape(strUrl);
						searchResultXML.append(" url=\"") //$NON-NLS-1$
								.append(
										UNCUtil
												.convertFilenameToUNC(bufferURL
														.toString())).append("\""); //$NON-NLS-1$
					}
				}

				if (title != null) {
					String strTitle = title.stringValue();
					if (strTitle != null) {
						strTitle = XMLUtil.escape(strTitle);
						searchResultXML.append(" title=\"") //$NON-NLS-1$
								.append(strTitle).append("\""); //$NON-NLS-1$
					}
				}

				if (summary != null) {
					String strSummary = summary.stringValue();
					if (strSummary != null) {
						strSummary = XMLUtil.escape(strSummary);
						searchResultXML.append(" summary=\"") //$NON-NLS-1$
								.append(strSummary).append("\""); //$NON-NLS-1$
					}
				}

				if (umaType != null) {
//					String[] keyWords = { "Product", "Descriptor", "Process", "Pattern",
//							"Type", "Definition", "Asset", "Considerations", "Category", 
//							"Material", "Grouping", "Set", "Tool" };
//
//					String strUmaType = StrUtil.convertFirstLetterCase(umaType
//							.stringValue(), keyWords);
					
					String strUmaType = getImageNameFromUmaTypeStr(umaType.stringValue());
					
					if (strUmaType.equalsIgnoreCase("General_content")) {
						searchResultXML.append(" icon=\"") //$NON-NLS-1$
							.append("Other.gif").append("\""); //$NON-NLS-1$
					} else {
						strUmaType = XMLUtil.escape(strUmaType);
						searchResultXML.append(" icon=\"") //$NON-NLS-1$
							.append(strUmaType).append(".gif").append("\""); //$NON-NLS-1$
					}					
				}
				searchResultXML.append("/>"); //$NON-NLS-1$	
			}

			searchResultXML.append("</SearchResult>"); //$NON-NLS-1$

			StringWriter result = new StringWriter();

			// System.out.println(searchResultXML.toString());

			XSLTProcessor.transform(_xslURL, searchResultXML.toString(), xslParams,
					result);

			//System.out.println(result.toString());

			return result.toString();
		} catch (Exception e) {
			e.printStackTrace();
			return EMPTY_HTML;
		}
	}

	private String getPageResult(boolean isNext) {
		if (isNext)
			_currentPage++;
		else
			_currentPage--;
		String result = updateOutput(true);

		return (result == null) ? EMPTY_HTML : result;
	}

	private void writeOutputError(ServletOutputStream os, String message, Exception ex)
			throws ServletException {
		Throwable t = ex;
		System.out.println("Exceptio: " + ex);
		if (ex instanceof java.lang.reflect.InvocationTargetException)
			t = ((java.lang.reflect.InvocationTargetException) ex).getTargetException();
		try {
			os.println("<hr>" + message + "<hr>");
			t.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	//for debug
	private static String escapeUnicodeString(String str, boolean escapeAscii) {
		StringBuffer ostr = new StringBuffer();

		for (int i = 0; i < str.length(); i++) {

			char ch = str.charAt(i);

			if (!escapeAscii && ((ch >= 0x0020) && (ch <= 0x007e))) {
				ostr.append(ch);
			} else {

				ostr.append("\\u") ;	//$NON-NLS-1$

				String hex = Integer.toHexString(str.charAt(i) & 0xFFFF);
				for (int j = 0; j < 4 - hex.length(); j++)
					ostr.append("0");//$NON-NLS-1$)

				ostr.append(hex.toUpperCase(Locale.ENGLISH));

			}

		}

	  return (new String(ostr));

	}
	
	private String getImageNameFromUmaTypeStr(String umaTypeStr) {
		String[] imageNamesForSearchResult =
		                      {"Activity", "Artifact", "CapabilityPattern", "Checklist", "Concept", "CustomCategory",
				               "Deliverable", "DeliveryProcess", "Discipline", "DisciplineGrouping", "Domain", "EstimationConsiderations",
				               "Example", "Guideline", "Iteration", "Milestone", "Outcome", "Phase",
				               "Practice", "Report", "ReusableAsset", "Roadmap", "Role", "RoleDescriptor",
				               "RoleSet", "RoleSetGrouping", "Summary", "SupportingMaterial", "Task", "TaskDescriptor",
				               "Template", "TermDefinition", "Tool", "Toolmentor", "Whitepaper", "WorkProductDescriptor",
				               "WorkProductType"};
		
		for (int i = 0; i < imageNamesForSearchResult.length; i++) {
			if (umaTypeStr.equalsIgnoreCase(imageNamesForSearchResult[i])) {
				return imageNamesForSearchResult[i];
			}			
		}
		
		return umaTypeStr;		
	}

}
