package jp.ac.osaka_u.sparql;

import java.io.IOException;
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 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;

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

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

		List<Map<String, String>> ret = new ArrayList<Map<String, String>>();
		try {
			SparqlResultSet rs = sa.find(conditions, targetList, head, limit, offset);
			List<Map<String, RDFNode>> results = rs.getDefaultResult();
			
			// 結果をまずはlistに追加
			Map<String, String> prevData = new HashMap<String, String>();
			if (results != null){
				for (Map<String, RDFNode> result : results){
					HashMap<String, String> map = new HashMap<String, String>();

					// subjectは必ず指定
					RDFNode s = result.get("s");
					String prevS = prevData.get("s");
					if (prevS != null && s != null && getString(s).equals(prevS)){
						map.put("s", "<same>same</same>"); // TODO 前データと同じ
					} else {
						map.put("s", getString(s));
					}
					prevData.put("s", getString(s));

					for (TargetPredicate preds : targetList){
						String prevRDF = prevData.get(preds.valiable);

						RDFNode valiable = result.get(preds.valiable);
						if (prevRDF != null && valiable != null && getString(valiable).equals(prevRDF)){
							map.put(preds.valiable, "<same>same</same>"); // TODO 前データと同じ
						} else {
							map.put(preds.valiable, getString(valiable));
						}
						prevData.put(preds.valiable, getString(valiable));
					}
					ret.add(map);
				}
			}

			ResultPack rp = new ResultPack();
			rp.setResults(ret);
			rp.setHasNext(rs.isHasNext());
			rp.setHasPrev(offset != null && offset.intValue() > 0);

			
			String json = JSON.encode(rp);
			
			return json;
		} catch (Exception e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}
		return null;

	}

	
	protected String getString(RDFNode node){
		if (node == null){
			return null;
		}
		if (node.isLiteral()){
			return (node.asLiteral()).getString();
		} else {
			return (node.toString());
		}
	}

	
	EndpointSettings getEndpointSettings(HttpServletRequest request){
		HttpSession session = request.getSession(true);
		return (EndpointSettings)session.getAttribute("session");

	}
}
