package kr.co.kihyun.beans.user;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.Transaction;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kr.co.kihyun.beans.entity.MDept;
import kr.co.kihyun.beans.entity.MUser;
import kr.co.kihyun.beans.entity.Organization;
import kr.co.kihyun.beans.entity.util.*;
import kr.co.kihyun.lang.MString;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@WebServlet("/servlet/kr.co.kihyun.beans.user.HttpOrgSearch")
public class HttpOrgSearch extends HttpServlet {
	class OrgComparator implements Comparator<Organization<?>> {
		PersistenceManager pm;

		public int compare(Organization<?> left, Organization<?> right) {
			List<MDept> leftPath = left.getOrgTreePath(pm);
			List<MDept> rightPath = right.getOrgTreePath(pm);
			Collections.reverse(leftPath);
			Collections.reverse(rightPath);

			int i = 0;
			for (i = 0; i < leftPath.size() && i < rightPath.size(); i++)
				if (leftPath.get(i).getPriority() != rightPath.get(i).getPriority())
					break;

			try {
				int comp = leftPath.size() - rightPath.size();
				comp = (int) (comp == 0 ? leftPath.get(i).getPriority() - rightPath.get(i).getPriority() : comp);
				comp = comp == 0 ? leftPath.get(i).getId().compareTo(rightPath.get(i).getId()) : comp;
				return comp;
			} catch (IndexOutOfBoundsException ioobe) {
				int comp = leftPath.size() - rightPath.size();
				if (comp == 0) {
					if (left instanceof MUser && right instanceof MDept)
						return -1;
					else if (left instanceof MDept && right instanceof MUser)
						return 1;
				}
				comp = (int) (comp == 0 ? left.getPriority() - right.getPriority() : comp);
				comp = comp == 0 ? ((Comparable) left.getId()).compareTo(right.getId()) : comp;
				return comp;
			}
		}
	}

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static final Logger LOG = LoggerFactory.getLogger(HttpOrgSearch.class);

	public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		doPost(req, res);
	}

	public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		res.setContentType("text/xml;charset=utf-8");
		PrintWriter out = res.getWriter();
		String keyWord = URLDecoder.decode(MString.checkNull(req.getParameter("keyword")), "UTF-8");
		LOG.debug("keyword: {}", keyWord);

		PersistenceManager pm = new MPersistenceManager(PMF.get().getPersistenceManager());
		Transaction tx = pm.currentTransaction();
		try {
			QueryImpl userQuery = new QueryImpl(pm, MUser.class);
			userQuery.setSearchFilter("name", keyWord);
			List<MUser> userResults = (List<MUser>) userQuery.execute();
			QueryImpl deptQuery = new QueryImpl(pm, MDept.class);
			deptQuery.setSearchFilter("name", keyWord);
			List<MDept> deptResults = (List<MDept>) deptQuery.execute();
			List<Organization<?>> results = new ArrayList<Organization<?>>();
			results.addAll(userResults);
			results.addAll(deptResults);
			OrgComparator deptComparator = new OrgComparator();
			deptComparator.pm = pm;
			Collections.sort(results, deptComparator);

			tx.begin();

			StringBuilder outXml = new StringBuilder("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
			outXml.append("<result>");
			for (Organization<?> result : results) {
				String typeName = result instanceof MUser ? "user" : "dept";
				outXml.append("<node>").append("<type>").append(typeName).append("</type>").append("<id>")
						.append(result.getId()).append("</id>").append("<name>").append(result instanceof MUser ? ((MUser) result).getName(pm) : result.getName())
						.append("</name>");
				for (MDept path : (List<MDept>) result.getOrgTreePath(pm))
					outXml.append("<path>").append(path.getId()).append("</path>");
				outXml.append("</node>");
			}
			outXml.append("</result>");

			tx.rollback();

			LOG.debug("search result:\n{}", outXml.toString());
			out.println(outXml.toString());
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			pm.close();
		}
	}
}
