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.HttpServlet;
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.SparqlResultSet;
import jp.ac.osaka_u.sanken.sparql.TargetPredicate;
import net.arnx.jsonic.JSON;

/**
 * Servlet implementation class GetViewQuery
 */
public class GetViewQuery extends SparqlServletBase {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public GetViewQuery() {
        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;
		}
		
		find(request, response, session);

	}

	private void find(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws ServletException, IOException {
		String param = (String)request.getParameter("param"); // 検索条件
		param = URLDecoder.decode(param, "UTF-8");

		
		
		List<Map<String, String>> findConditionMap = null;
		if (param != null){
			findConditionMap = (List<Map<String, String>>)JSON.decode(param);
		}
		List<FindCondition> findConditions = new ArrayList<FindCondition>();

		List<Map<String, String>> targetList = null;
		String target = (String)request.getParameter("target"); // 検索対象
		if (target != null){
			targetList = (List<Map<String, String>>)JSON.decode(target);
		}
		List<TargetPredicate> targetPredicates = new ArrayList<TargetPredicate>();
		
		String limitStr = (String)request.getParameter("limit"); // リミット
		Integer limit = null;
		if (limitStr != null){
			limit = Integer.parseInt(limitStr);
		}

		String offsetStr = (String)request.getParameter("offset"); // オフセット
		Integer offset = null;
		if (offsetStr != null){
			offset = Integer.parseInt(offsetStr);
		}

		
		
		String head = (String)request.getParameter("head"); // 検索ヘッダ
		if (head != null){
			head = URLDecoder.decode(head, "UTF-8");
		}

		if (findConditionMap != null && targetList != null){
			for (Map<String, String> p : findConditionMap){
				findConditions.add(new FindCondition(URLDecoder.decode(p.get("predicate"), "UTF-8"), URLDecoder.decode(p.get("word"), "UTF-8"), p.get("type"), p.get("and_or")));
			}
			for (Map<String, String> t : targetList){
				if (t.get("valiable") != null && t.get("pred") != null){
					targetPredicates.add(new TargetPredicate(t.get("valiable"), t.get("pred")));
				}
			}

			find(head, findConditions, targetPredicates, limit, offset, request, response);

		}
	}
	
	private void find(String head, List<FindCondition> conditions, List<TargetPredicate> targetList, Integer limit, Integer offset, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		EndpointSettings es = getEndpointSettings(request);

		if (es == null){
			error(request, response, "endpoint hasn't set");
			return;
		}
		
		String json = find(head, conditions, targetList, limit, offset, es);
		
		if (json != null){
			response(request, response, json);
			
		} else {
			error(request, response, "json error");
		}

	}
	
	private String find(String head, List<FindCondition> conditions, List<TargetPredicate> targetList, Integer limit, Integer offset, EndpointSettings es) throws ServletException, IOException {
		
		SparqlAccessor sa = SparqlAccessorFactory.createSparqlAccessor(es);

		try {
			String query = sa.getQuery(conditions, targetList, head, limit, offset);
			
			Map<String, String> ret = new HashMap<String, String>();
			ret.put("query", query);
			
			return JSON.encode(ret);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;

	}
}

