package org.inria.bmajwatcher.server;


import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
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 org.apache.log4j.Logger;
import org.inria.biomaj.sql.SQLConnection;
import org.inria.biomaj.sql.SQLConnectionFactory;
import org.inria.bmajwatcher.client.services.BankDetailService;
import org.inria.bmajwatcher.server.data.BankRetriever;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;



public class BankDetailServiceImpl extends RemoteServiceServlet implements BankDetailService {
	
	static final long serialVersionUID = 1L;
	private static Logger log = Logger.getLogger(BankDetailServiceImpl.class);
	private Element root = null;

	@Override
	public Map<String, String> getDetailedBankInfo(String bankName) {
		
		return BankRetriever.getInstance().getBankDetail(bankName);
		
	}
	
	@Override
	public List<String> getTypes(String login) {
		List<String> list = new ArrayList<String>();
		String key = "";
		
		if (login != null && !login.trim().isEmpty()) {
			String query = "SELECT auth_key FROM bw_user WHERE login='" + login + "'";
			SQLConnection connection = SQLConnectionFactory.getConnection();
			Statement stat = connection.getStatement();
			
			ResultSet rs = connection.executeQuery(query, stat);
			
			try {
				if (rs.next()) {
					key = rs.getString(1);
				}
			} catch (SQLException e) {
				log.error(e);
			}
			
			SQLConnectionFactory.closeConnection(stat);
		}
		
		list.addAll(BankQueryingService.getDBTypes(key));
		Collections.sort(list);
		return list;
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		
		
		String bankName;
		
		if ((bankName = req.getParameter("getxml")) != null) {
			String userKey = req.getParameter("auth_key");
			String parentId = req.getParameter("parent");
			fetchBankData(bankName, (userKey == null ? "" : userKey), (parentId == null ? "" : parentId), resp.getWriter());
		} else
			super.doGet(req, resp);
	}
	
	private void fetchBankData(String bankName, String userKey, String parentId, PrintWriter out) {
		out.write(BankRetriever.getInstance().getBankInfo(bankName, parentId, userKey));
		out.flush();
	}
	
	@Override
	public Map<String, List<String>> getFields(boolean restricted) {
		if (root == null) {
			SAXBuilder xmlBuilder = new SAXBuilder("org.apache.xerces.parsers.SAXParser", false);
			try {
				File file = new File(getServletContext().getRealPath("/") + "/bankFields.xml");
				if (file.exists()) {
					Document document = xmlBuilder.build(file);
					root = document.getRootElement();
				} else {
					log.warn("'bankFields.xml' doesn't exisits.");
					return null;
				}
			} catch (JDOMException e) {
				log.error("Malformed xml file", e);
				return null;
			} catch (IOException e) {
				log.error("", e);
				return null;
			}
		}
		
		Map<String, List<String>> res = new HashMap<String, List<String>>();
		List<?> sections = root.getChildren("section");
		for (Object elt : sections) {
			Element e = (Element) elt;
			String key = e.getAttributeValue("name");
			if (restricted == true || restricted == false && Boolean.valueOf(e.getAttributeValue("restricted")) == restricted) {
				
				List<String> atts = new ArrayList<String>();
				List<?> attributes = e.getChildren("attribute");
				for (Object att : attributes) {
					Element elem = (Element) att;
					if (restricted == true || restricted == false && Boolean.valueOf(elem.getAttributeValue("restricted")) == restricted)
						atts.add(elem.getAttributeValue("key") + "_:_" + elem.getAttributeValue("title"));
				}
				res.put(key, atts);
			}
		}
		
		return res;
	}

	@Override
	public Map<String, String> getDependencies(String bankName) {
		Map<String, String> res = new HashMap<String, String>();
		BankRetriever.getInstance().getBankDependencies(bankName, res);
		return res;
	}
}
