package eu.dnetlib.enabling.aas.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import eu.dnetlib.enabling.aas.utils.dump.IDumpable;
import eu.dnetlib.enabling.aas.utils.invalidate.IInvalidatable;
import eu.dnetlib.enabling.aas.utils.invalidate.InvalidationException;


/**
 * AAS2 Administration servlet.
 * @author mhorst
 *
 */
public class AdministrationServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = -9063805316074093658L;

	private static final Logger log = Logger.getLogger(AdministrationServlet.class);

	
	/* errors */
	private static final String MSG_NO_ACTION_PARAMETER = "No action parameter specified!";
	
	private static final String MSG_UNSUPPORTED_ACTION_PARAMETER = "Unsupported action parameter specified!";
	
	private static final String MSG_NO_RESOURCE_PARAMETER = "No resource parameter specified!";
	
	private static final String MSG_UNSUPPORTED_RESOURCE_PARAMETER = "Unsupported resource parameter specified!";
	
	/* infos */
	private static final String MSG_INVALIDATION_FINISHED = "Invalidation completed!";
	
	/* params */
	private static final String PARAM_ACTION = "action";
	
	private static final String PARAM_RESOURCE = "resource";
	
	/* actions */
	private static final String ACTION_INVALIDATE = "invalidate";

	private static final String ACTION_DUMP = "dump";
	
	/**
	 * Map of dumpable modules.
	 */
	protected Map<String, IDumpable> dumpables;
	
	/**
	 * Map of invalidatable modules.
	 */
	protected Map<String, IInvalidatable> invalidatables;
	
	
	/* (non-Javadoc)
	 * @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
	 */
	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
	}
	
	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse res)
			throws ServletException, IOException {
		
		String actionValue = req.getParameter(AdministrationServlet.PARAM_ACTION);
		if (actionValue==null) {
			log.error(MSG_NO_ACTION_PARAMETER);
			res.sendError(HttpServletResponse.SC_BAD_REQUEST, MSG_NO_ACTION_PARAMETER);
			return;
		} 
		
		String resourceValue = req.getParameter(AdministrationServlet.PARAM_RESOURCE);
		if (resourceValue==null) {
			log.error(MSG_NO_RESOURCE_PARAMETER);
			res.sendError(HttpServletResponse.SC_BAD_REQUEST, MSG_NO_RESOURCE_PARAMETER);
			return;
		}
		
		if (actionValue.equals(AdministrationServlet.ACTION_INVALIDATE)) {
			if (invalidatables!=null && invalidatables.containsKey(resourceValue)) {
				try {
					invalidatables.get(resourceValue).invalidate();
					putMessageToResponse(MSG_INVALIDATION_FINISHED,res);
					log.info("invalidation performed successfully for module " + resourceValue);
					return;
				} catch(InvalidationException e) {
					log.error("reloading policies failed!", e);
					throw new ServletException(e);
				}
			} else {
				log.error(MSG_UNSUPPORTED_RESOURCE_PARAMETER);
				res.sendError(HttpServletResponse.SC_BAD_REQUEST, MSG_UNSUPPORTED_RESOURCE_PARAMETER);
				return;
			}
			
		} else if (actionValue.equals(AdministrationServlet.ACTION_DUMP)) {
			if (dumpables!=null && dumpables.containsKey(resourceValue)) {
				dumpables.get(resourceValue).dump(res.getOutputStream());
				log.info("dumping performed successfully for module " + resourceValue);
				return;
			} else {
				log.error(MSG_UNSUPPORTED_RESOURCE_PARAMETER);
				res.sendError(HttpServletResponse.SC_BAD_REQUEST, MSG_UNSUPPORTED_RESOURCE_PARAMETER);
				return;
			}
		} else {
			log.error(MSG_UNSUPPORTED_ACTION_PARAMETER);
			res.sendError(HttpServletResponse.SC_BAD_REQUEST, MSG_UNSUPPORTED_ACTION_PARAMETER);
			return;
		}
	}
	
	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	@Override
	protected void doPost(HttpServletRequest arg0, HttpServletResponse arg1)
			throws ServletException, IOException {
		doGet(arg0, arg1);
	}
	
	/**
	 * Puts message given as parameter to the response.
	 * 
	 * @param msg
	 * @param response
	 * @throws IOException
	 */
	private void putMessageToResponse(String msg, HttpServletResponse response)
			throws IOException {
		response.setContentType("text/plain");
		response.setCharacterEncoding("utf-8");
		PrintWriter out = response.getWriter();
		out.write(msg);
		out.write('\n');
		// out.close();
	}

	/**
	 * Sets map of dumpable modules.
	 * @param dumpables
	 */
	public void setDumpables(Map<String, IDumpable> dumpables) {
		this.dumpables = dumpables;
	}

	/**
	 * Sets map of invalidatable modules.
	 * @param invalidatables
	 */
	public void setInvalidatables(Map<String, IInvalidatable> invalidatables) {
		this.invalidatables = invalidatables;
	}
}

