//------------------------------------------------------------------------------
//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  enable to use tag to filte search results

			_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 if (strUmaType.equalsIgnoreCase("udt")){//show the search icon for udt
						Field shapeImage=doc.getField("searchicon");
						if(shapeImage!=null){
							String si=shapeImage.stringValue();
							if(si!=null){
								String searchIcon="./../../"+si;
								searchResultXML.append(" icon=\"").append(searchIcon).append("\"");
							}
						}else{
							searchResultXML.append(" icon=\"").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;		
	}

}
