/*******************************************************************************
 * Copyright (c) 2008 IBM Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.cosmos.internal.dr.drs.service.handler.common;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.eclipse.cosmos.provisional.dr.drs.service.handler.common.AbstractServletHandler;
import org.eclipse.cosmos.provisional.dr.drs.service.handler.common.IIDResolver;
import org.eclipse.cosmos.provisional.dr.drs.service.handler.common.IOutputter;
import org.eclipse.cosmos.provisional.dr.drs.service.handler.common.IOutputterContext;
import org.eclipse.cosmos.provisional.dr.drs.service.handler.common.IOutputterFactory;
import org.eclipse.cosmos.provisional.dr.drs.service.handler.common.IOutputterParameters;
import org.eclipse.cosmos.provisional.dr.drs.service.handler.common.IParameters;

public class OutputterDelegator extends AbstractServletHandler {
	static final long serialVersionUID = -5991590204597891023L;
	private static ILogger logger = LoggerWrapper.getLogger(OutputterDelegator.class);

	@Override
	public void doGet(HttpServletRequest req, StringWriter resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		delegateRequest(req, resp);
	}
	
	protected IIDResolver getIDResolver(HttpServletRequest request){
		IIDResolver idResolver;
		idResolver = new SessionResolveFixedTreeIDs(request.getSession());
		idResolver.clear();
		return idResolver;
	
	}	

	@Override
	public void doPost(HttpServletRequest req, StringWriter resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		delegateRequest(req, resp);
	}

	protected IOutputterContext createOutputterContext(HttpServletRequest req){
		return new SessionOutputterContextImpl(req);		
	}
	protected void delegateRequest(HttpServletRequest req, StringWriter resp)
	throws ServletException, IOException {
		try {
			String service = req.getParameter("service"); //$NON-NLS-1$
			IParameters parameters = new RequestParametersImpl(req);
			IOutputter outputter = createOutputter(service, req.getSession());
			List<IOutputterParameters> invalidParam = outputter.getInvalidInput(parameters);
			if (invalidParam.size() == 0){
				outputter.setIdResolver(getIDResolver(req));
				IOutputterContext context  = createOutputterContext(req);
				outputter.initalize(context, parameters);
				outputter.render(new PrintWriter(resp), parameters);
			}
			else{
				String nullParameters = "";  //$NON-NLS-1$
				for (int x = 0 ; x < invalidParam.size(); x++){
					nullParameters += invalidParam.get(x).getName() + " "; //$NON-NLS-1$
				}
				sendError(new Exception(MessageFormat.format(Messages.getString("URLDelegator.PARAM_REQUIRED_ERR"),new Object[] {nullParameters})), resp); //$NON-NLS-1$ //$NON-NLS-2$
			}
		} catch (Exception e) {
			try{
				sendError(e, resp);
				req.getSession().getServletContext().log(e.getMessage(), e);
			}
			catch (Exception exc){
				throw new ServletException(exc);
			}
		}
	}
	
   protected static String HTMLEntityEncode( String s ) throws Exception
   {
	   if (s == null)
		   return ""; //$NON-NLS-1$
	   return URLEncoder.encode(s,"UTF-8"); //$NON-NLS-1$
   }
	   
	protected void sendError(Exception e, StringWriter resp) throws Exception{
		//start a new writer and igore the previous writer
		resp.append("{_error_:true, message:'"+HTMLEntityEncode(e.getLocalizedMessage())+"', detail:'"); //$NON-NLS-1$ //$NON-NLS-2$
		StringWriter sw = new StringWriter();
		PrintWriter pwExc = new PrintWriter(sw);
		//log error
		logger.error(e);
		e.printStackTrace(pwExc);
		pwExc.flush();
		resp.append(HTMLEntityEncode(sw.getBuffer().toString()));		
		resp.append("'}"); //$NON-NLS-1$
		pwExc.close();
		sw.close();
		
	}


	protected IOutputter createOutputter(String id, HttpSession session) throws Exception{
		IOutputterFactory factory= (IOutputterFactory)session.getAttribute("OUTPUTTER_FACTORY"); //$NON-NLS-1$
		if (factory == null){
			factory = new OutputterFactoryImpl();
			session.setAttribute("OUTPUTTER_FACTORY", factory); //$NON-NLS-1$
		}
		return factory.createOutputter(id);
	}	
}
