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.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 FindByCondition
 */
public class FindByCondition extends SparqlServletBase {
	private static final long serialVersionUID = 1L;

    /**
     * Default constructor. 
     */
    public FindByCondition() {
    	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;
		}

		this.history = HistoryManager.getHistoryData(DATA_TYPE, request);

		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;
		limit = Integer.parseInt(limitStr);

		String offsetStr = (String)request.getParameter("offset"); // オフセット
		Integer offset = 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")));
				}
			}
			this.history.initHistory();

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

		}
		HistoryManager.updateHistoryData(this.history, DATA_TYPE, request);
	}
	
	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 = new Finder().find(head, conditions, targetList, limit, offset, es);
		
		if (json != null){
			OffsetManager om = new OffsetManager(head, conditions, targetList, limit, offset);
			request.getSession(false).setAttribute("offset", om);
			response(request, response, json);
			
		} else {
			error(request, response, "json error");
		}

	}

}
