package jp.ac.osaka_u.sparql;

import java.io.IOException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.RDFNode;

import jp.ac.osaka_u.sanken.sparql.EndpointSettings;
import jp.ac.osaka_u.sanken.sparql.FindCondition;
import jp.ac.osaka_u.sanken.sparql.SparqlAccessor;
import jp.ac.osaka_u.sanken.sparql.SparqlAccessorFactory;
import jp.ac.osaka_u.sanken.sparql.TargetPredicate;
import net.arnx.jsonic.JSON;

/**
 * Servlet implementation class GetMenuCondition
 */
public class GetMenuCondition extends SparqlServletBase {
	private static final long serialVersionUID = 1L;

    /**
     * Default constructor. 
     */
    public GetMenuCondition() {
    	super();
    }

	@Override
	protected void process(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		HttpSession session = request.getSession(false);
		if (session == null){
			error(request, response, "init error");
			return;
		}
		
		
		getMenuCondition(request, response, session);
	}

	private void getMenuCondition(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws ServletException, IOException {
		String param = (String)request.getParameter("param"); // 述語
		List<FindCondition> conds = new ArrayList<FindCondition>();
		List<Map<String, String>> paramList = null;
		if (param != null){
			paramList = (List<Map<String, String>>)JSON.decode(param);
		}
		if (paramList != null){
			for (Map<String, String> p : paramList){
				conds.add(new FindCondition(URLDecoder.decode(p.get("predicate"), "UTF-8"), URLDecoder.decode(p.get("word"), "UTF-8"), p.get("type"), p.get("and_or")));
			}
		}
		count(conds, request, response);
	}

	private void count(List<FindCondition> conditions, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Map<String, String> ret = new HashMap<String, String>();
		EndpointSettings es = getEndpointSettings(request);

		if (es == null){
			error(request, response, "endpoint hasn't set");
			return;
		}
		int count = count(conditions, es);
		JSON enc = new JSON();
		enc.setSuppressNull(true);
		ret.put("query", "{\"label\": \"label(" + String.valueOf(count) + ")\", \"query\":\"" +enc.format(conditions).replaceAll("\"", "\\\\\"") + "\"},");
		ret.put("count", String.valueOf(count));

		String json = enc.format(ret);
		
		response(request, response, json);
	}
	
	private int count(String query, EndpointSettings es){

		SparqlAccessor sa = SparqlAccessorFactory.createSparqlAccessor(es);
		try {

			List<Map<String, RDFNode>> results = sa.executeQuery(query);

			if (results != null){
				for (Map<String, RDFNode> result : results){

					RDFNode node = result.get("count");
					if (node.isLiteral()){
						Literal l = node.asLiteral();
						return l.getInt();
					}
				}
			}

		} catch (Exception e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}


		return -1;
	}
	
	private int count(List<FindCondition> conditions, EndpointSettings es){
		SparqlAccessor sa = SparqlAccessorFactory.createSparqlAccessor(es);
		String query = sa.getQuery(conditions, new ArrayList<TargetPredicate>(), null, null, null);

		int index = query.indexOf("{");
		if (index > 0){
			query = query.substring(index);
			query = "select (count(?s) as ?count) \n" + query;
		}
		return count(query, es);

	}
}
