/*

 Copyright 2004 (C) John Wilson. All Rights Reserved.

 Redistribution and use of this software and associated documentation
 ("Software"), with or without modification, are permitted provided
 that the following conditions are met:

 1. Redistributions of source code must retain copyright
    statements and notices.  Redistributions must also contain a
    copy of this document.

 2. Redistributions in binary form must reproduce the
    above copyright notice, this list of conditions and the
    following disclaimer in the documentation and/or other
    materials provided with the distribution.

 3. The name "groovy" must not be used to endorse or promote
    products derived from this Software without prior written
    permission of The Codehaus.  For written permission,
    please contact info@codehaus.org.

 4. Products derived from this Software may not be called "groovy"
    nor may "groovy" appear in their names without prior written
    permission of The Codehaus. "groovy" is a registered
    trademark of The Codehaus.

 5. Due credit should be given to The Codehaus -
    http://groovy.codehaus.org/

 THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
 ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
 THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 OF THE POSSIBILITY OF SUCH DAMAGE.

 */

package groovy.net.xmlrpc;

import groovy.lang.Closure;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import groovy.lang.GroovyObjectSupport;
import groovy.lang.GroovyRuntimeException;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import uk.co.wilson.net.http.MinMLHTTPServer;
import uk.co.wilson.net.xmlrpc.XMLRPCMessageProcessor;

/**
 * @author John Wilson (tug@wilson.co.uk)
 *
 */
public class XMLRPCServer extends GroovyObjectSupport {
private byte[] base64 = new byte[600];
{
	for (int i = 0; i != this.base64.length; i++) {
		this.base64[i] = (byte)i;
	}
}
public byte[] getBase64() { return this.base64;} // bodge to allow testing

	private static byte[] host;
	static {
		try {
			host  = ("Host: " + InetAddress.getLocalHost().getHostName() +"\r\n").getBytes();
		} catch (UnknownHostException e) {
			host = "Host: unknown\r\n ".getBytes();
		}
	}
	private static final byte[] userAgent = "User-Agent: Groovy XML-RPC\r\n".getBytes();
	private static final byte[] contentTypeXML = "Content-Type: text/xml\r\n".getBytes();
	private static final byte[] contentLength = "Content-Length: ".getBytes();
	private static final byte[] startResponse = ("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" + 
												 "<methodResponse>\n" +
												 "\t<params>\n" +
												 "\t\t<param>\n").getBytes();
	private static final byte[] endResponse = ("\n" +
											   "\t\t</param>\n" +
											   "\t</params>\n" +
											   "</methodResponse>").getBytes();
	private static final byte[] startError = ("<?xml version=\"1.0\"?>\n" + 
											  "<methodResponse>\n" +
											  "\t<fault>\n" +
											  "\t\t<value>\n" +
											  "\t\t\t<struct>\n" +
											  "\t\t\t\t<member>\n" +
											  "\t\t\t\t\t<name>faultCode</name>\n" +
											  "\t\t\t\t\t<value><int>0</int></value>\n" +
											  "\t\t\t\t</member>\n" +
											  "\t\t\t\t<member>\n" +
											  "\t\t\t\t\t<name>faultString</name>\n" +
											  "\t\t\t\t\t<value><string>").getBytes();
	
	private static final byte[] endError = ("</string></value>\n" +
											"\t\t\t\t</member>\n" +
											"\t\t\t</struct>\n" +
											"\t\t</value>\n" +
											"\t</fault>\n" +
											"</methodResponse>\n").getBytes();
	
	private MinMLHTTPServer server = null;
	private final int minWorkers;
	private final int maxWorkers;
	private final int maxKeepAlives;
	private final int workerIdleLife;
	private final int socketReadTimeout;
	private final StringBuffer propertyPrefix = new StringBuffer();
	private final Map registeredMethods = new HashMap();

	/**
	 * @param minWorkers
	 * @param maxWorkers
	 * @param maxKeepAlives
	 * @param workerIdleLife
	 * @param socketReadTimeout
	 */
	public XMLRPCServer(final int minWorkers,
						final int maxWorkers,
						final int maxKeepAlives,
						final int workerIdleLife,
						final int socketReadTimeout)
	{
		this.minWorkers = minWorkers;
		this.maxWorkers = maxWorkers;
		this.maxKeepAlives = maxKeepAlives;
		this.workerIdleLife = workerIdleLife;
		this.socketReadTimeout = socketReadTimeout;
	}
	
	/**
	 * 
	 */
	public XMLRPCServer() {
		this(2, 10, 8, 60000, 60000);
	}
	
	/**
	 * @param serverSocket
	 */
	public void startServer(final ServerSocket serverSocket) throws IOException {
		if (this.server != null) stopServer();
		
		final MinMLHTTPServer server = new MinMLHTTPServer(serverSocket,
								                           this.minWorkers, 
														   this.maxWorkers, 
														   this.maxKeepAlives, 
														   this.workerIdleLife, 
														   this.socketReadTimeout) {

			/* (non-Javadoc)
			 * @see uk.co.wilson.net.MinMLSocketServer#makeNewWorker()
			 */
			protected Worker makeNewWorker() {
				return new HTTPWorker() {
					protected void processPost(final InputStream in,
											   final OutputStream out,
											   final String uri,
											   final String version)
						throws Exception
					{
						
						try {
						final StringBuffer buffer = new StringBuffer();
						final XMLRPCMessageProcessor requestParser = new XMLRPCMessageProcessor();
							
							out.write(version.getBytes());
							out.write(okMessage);
							out.write(userAgent);
							out.write(host);
							out.write(contentTypeXML);
							writeKeepAlive(out);
							out.write(contentLength);
							
							requestParser.parseMessage(in);
							
							final String methodName = requestParser.getMethodname();
							final List params = requestParser.getParams();
							final Object closure = XMLRPCServer.this.registeredMethods.get(methodName);
							
							if (closure == null) throw new GroovyRuntimeException("XML-RPC method " + methodName + " is not supported on this server");
							
							Object result = ((Closure)closure).call(params.toArray());
							
							if (result == null) result = new Integer(0);
							
							XMLRPCMessageProcessor.emit(buffer, result);
							
//							System.out.println(buffer.toString());
							
							final byte[] response = buffer.toString().getBytes("ISO-8859-1");
							
							out.write(String.valueOf(startResponse.length + response.length + endResponse.length).getBytes());
							out.write(endOfLine);
							out.write(endOfLine);
							out.write(startResponse);
							out.write(response);
							out.write(endResponse);
						}
						catch (final Throwable e) {
//						e.printStackTrace();
						final String message = e.getMessage();
						final byte[] error = ((message == null) ? endError.getClass().getName() : e.getMessage()).getBytes();
							
							out.write(String.valueOf(startError.length + error.length + endError.length).getBytes());
							out.write(endOfLine);
							out.write(endOfLine);
							out.write(startError);
							out.write(error);
							out.write(endError);
						}
					}
				};
			}
		};
		
		this.server = server;
		
		new Thread() {
			public void run() {
				server.start();
			}
		}.start();
	}
	
	public void stopServer() throws IOException {
		this.server.shutDown();
	}
	
	/* (non-Javadoc)
	 * @see groovy.lang.GroovyObject#getProperty(java.lang.String)
	 */
	public Object getProperty(final String property) {
		/**
		 * 
		 * Allow server.a.b.c = {...}
		 * This creates a method with the name "a.b.c"
		 * This technique is shamelessly stolen from the Python XML-RPC implementation
		 * Thanks and credit to Fredrik Lundh
		 * 
		 */

		this.propertyPrefix.append(property).append('.');
		
		return this;
	}
	
	/* (non-Javadoc)
	 * @see groovy.lang.GroovyObject#setProperty(java.lang.String, java.lang.Object)
	 */
	public void setProperty(final String property, final Object method) {
	final String methodName = this.propertyPrefix.append(property).toString();
	final Closure closure;
	
		this.propertyPrefix.setLength(0);
	
		if (method instanceof Closure) {
			try {
				closure = (Closure)(((Closure)method).clone());
				closure.setDelegate(this);
			} catch (CloneNotSupportedException e) {
				throw new GroovyRuntimeException("groovy.lang.Closure doesn't implement Clonable");
			}
		} else if (method instanceof Class) {
			closure = null;
		} else {
		//
		// calling a method on an instance of a class
		//
			
		final Method methods[] = method.getClass().getMethods();
		boolean foundMatch = false;
		int numberofParameters = 0;
		
			for (int i = 0; i != methods.length; i++) {
				if (methods[i].getName().equals(methodName)) {
					if (foundMatch) {
						if (numberofParameters != methods[i].getParameterTypes().length)
							;// TODO: throw exception
					} else {
						foundMatch = true;
						numberofParameters = methods[i].getParameterTypes().length;
					}
				}
			}
			
			if (foundMatch) {
				closure = makeObjectProxy(methodName, numberofParameters);
				closure.setDelegate(method);
			} else {
				// TODO: throw execption
				closure = null;
			}
		}
		
		this.registeredMethods.put(methodName, closure);
	}
	
	private Closure makeObjectProxy(final String methodName, final int numberOfParameters) {
	final String paramIn, paramOut;
	
		if (numberOfParameters == 0) {
			paramIn = paramOut = "";
		} else {
		final StringBuffer params = new StringBuffer();
		
			for (int i = 0; i != numberOfParameters; i++) {
				params.append(", p" + i);
			}
			
			paramOut = params.delete(0, 2).toString();
			paramIn = paramOut + " |";
		}
		
	final String generatedCode = "class X { closure = {" + paramIn + " this." + methodName + "(" + paramOut + ") }}";
	System.out.println(generatedCode);
	
		try {
		final InputStream in = new ByteArrayInputStream(generatedCode.getBytes());
		final GroovyObject groovyObject = (GroovyObject)new GroovyClassLoader().parseClass(in, methodName).newInstance();
			
			return (Closure)(groovyObject.getProperty("closure"));
		} catch (Exception e) {
			throw new GroovyRuntimeException("Can't generate proxy for XML-RPC method " + methodName, e);
		}
	}
}
