package org.w2mind.net;

import org.w2mind.soml.Message;
import org.w2mind.soml.MessageParser;
import java.net.URL;
import java.net.URLEncoder;
import java.net.URLDecoder;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.io.PrintWriter;
import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
	This class can be used to send a single message to a URL and get a response.
	You should use the classes and wrappers available in the org.w2mind.soml package to create and parse the messages.
*/
public class Proxy extends Thread {

	private URL url;
	private Message sentMessage = null;
	private Message returnedMessage = null;
	private RunError error;
	private boolean finished = false;
	private String raw;

	/**
		Connect to a given URL to send an SOML message. The message can then be retreived using the <code>getmessage</code> method.
		Since it might take some time to retreive the message, the <code>finished</code> method will return true when a response has been received.
	*/
	public Proxy(String url, Message sentMessage) {
		try {
			this.url = new URL(url);
		} catch (MalformedURLException e) {}
		this.sentMessage = sentMessage;
	}

	public Proxy(String url, String raw) {
		this.raw = raw;
		try {
			this.url = new URL(url);
		} catch (MalformedURLException e) {}
		this.sentMessage = sentMessage;
	}

	/**
		This method (or the <code>start</code> method) should not be called outside the class, as it is called by the constructor.
	*/
	public void run() {
		try {
			URLConnection connection = url.openConnection();
			connection.setDoOutput(true);
			PrintWriter outs = new PrintWriter(connection.getOutputStream());
			outs.println("q=" + (raw == null ? sentMessage.toSOML() : raw));
			outs.close();

			StringBuffer returnedText = new StringBuffer();
			BufferedReader ins = new BufferedReader(new InputStreamReader(connection.getInputStream()));
			String l;
			while((l = ins.readLine()) != null) {
				returnedText.append(l);
			}
			ins.close();
			MessageParser messageParser = new MessageParser();
			messageParser.turnOffValidation();
			returnedMessage = messageParser.parse(returnedText.toString());
			if(returnedMessage.getStatus() != null && !returnedMessage.getStatus().equals("100")) {
				error = new RunError(returnedMessage.getStatus(), returnedMessage.getStatusText() == null ? "" : returnedMessage.getStatusText());
			}
		} catch(Exception e) {
			error = new RunError("400", "Could not get message from service (" + e.getMessage() + ")");
		}
		finished = true;
	}
	
	/**
		Returns true when a message has been received
	*/	
	public boolean finished() {
		return finished;
	}

	/**
		Returns the response received or an Error/Exception.
	*/
	public Message getMessage() throws RunError {
		if(error != null) throw error;
		return returnedMessage;
	}
}
