import java.applet.Applet;
import java.awt.Label;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.net.URL;
import java.net.MalformedURLException;


/**
 * A simple applet that will to 'vote' for something on the web by
 * requesting a preset URL. The vote url is hard-coded so that 'other'
 * people cannot use this very same applet for the same 'election' to their
 * own use, e.g. steal a vote from me. 
 *
 * <p>Possible parameters are:<br><ol>
 * <li>Number of threads that will vote simultaneously: <tt>threads</tt>
 * </ol>
 *
 * <p>This applet will not circumvent 'smart' checks on the 
 * server side. But it will be a lesson to those script kiddies that thought
 * they didn't need to check if 'someone' already has cast a vote. </p>
 *
 * @author Jeroen Pulles
 */
public class Vote extends Applet
{
	private int          m_count; // totals
	private String       m_voteurl;
	private Label        m_numLabel;
	private VoteWorker[] m_workers;
	
	public Vote()
	{
		m_count = 0;
		m_workers = new VoteWorker[5];
		m_numLabel = new Label("0");
		// better off to put stuff in init() instead.
	}
	

	/**
	 * The applet is loaded, or reloaded. 
	 */
	public void init()
	{
		m_voteurl = getParameter("url");
		m_numLabel.setText(String.valueOf(m_count));
		m_numLabel.setLocation(8,8);
		add(m_numLabel);
		validate();
	}

	
	public void start()
	{
		System.out.println("Vote version 0.1");
		showStatus("Vote applet starting to vote.");
		try {
			for (int i = 0; i < m_workers.length; i++) {
				m_workers[i] = new VoteWorker(
					m_voteurl, this);
			}
		} catch (MalformedURLException e) {
			showStatus(
				"Malformed URL: " + e.getMessage());
			System.out.println(
				"Malformed URL: " + e.getMessage());
		} catch (SecurityException e) {
			System.out.println(
				"Security Exception: " + e.getMessage());
		}
		
	}
	
	
	public void stop()
	{
		// stop all voteworkers:
		for (int i = 0; i < m_workers.length; i++) {
			VoteWorker v = m_workers[i];
			if (v != null) {
				v.stop();
			}
		}
		m_count = 0;
		showStatus("Vote applet stopped.");
	}

	
	public void destroy()
	{
	}


	public synchronized void incrementCount()
	{
		m_numLabel.setText(String.valueOf(++m_count));
	}

	
	/** 
	 * Does the work of voting, by making a HTTP GET request to the URL.
	 */
	private class VoteWorker implements Runnable
	{
		private URL            m_url;
		private Vote           m_panel;
		private StringBuffer   m_result;
		private int            m_total;
		private Thread         m_VoteThread;

		public VoteWorker(String url, Vote vw) throws MalformedURLException
		{
			m_url = new URL(url);
			m_panel = vw;
			m_result = new StringBuffer();
			m_total = 0;
			m_VoteThread = new Thread(this, "VoteWorker");
			m_VoteThread.start();
		}
		
		public void run()
		{
			String line = "--->"; 
			BufferedReader in = null;
			Thread currentThread = Thread.currentThread();
			while (currentThread == m_VoteThread) {
				System.out.println("GET " + m_url.toString());
				try {
					in = new BufferedReader(
						new InputStreamReader(
							m_url.openStream())
						);
					while ((line = in.readLine()) != null) {
						m_result.append(line);
						// TODO ignore response after a few lines :-)
					}
					m_total++;
					m_panel.incrementCount();
				} catch (IOException e) {
					System.out.println(e.getMessage());
					// TODO show status message
				} catch (ClassCastException c) {
					System.out.println(c.getMessage());
				}
				try {
					in.close();
				} catch (IOException e) {
				} catch (NullPointerException e) {
				}
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
				}
			}
		}

		public String getResponse()
		{
			return m_result.toString();
		}

		public synchronized void stop()
		{
			m_VoteThread = null;
		}

		public int total()
		{	
			return m_total;
		}
	}
	
} // Vote.java

