//Search for         // APPLET
// to correct 

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package csa.tiletools.particle.JH;

/*
 * Copyright Jerry Huxtable 1999
 *
 * Feel free to do anything you like with this code.
 */

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;
import java.io.*;
import csa.tiletools.particle.JH.filters.*;
import csa.tiletools.particle.JH.images.*;

/**
 * An applet which animates a simple particle system.
 */
public class ParticleImage 
//extends Applet implements Runnable, MouseListener 
{

    protected MemoryImageSource source;
	protected Image image;
	protected boolean newImage = true;
	protected ColorModel colorModel;
	protected Thread thread;
	protected byte[] pixels1, pixels2;
	protected int width=100, height=100;
	protected Image offscreen;
	protected Graphics offscreenG;
	public Action[] actions;
	protected Filter[] filters;
	protected Object[] gradients;
	private boolean running = false;
	private boolean startAnimation = false;

	public ParticleImage() 
        {
	}

        // APPLET
        // applet stuff TODO
        private String getParameter(String s)
        {
            // TODO - not implemented yet
            return s;
        }
        public ParticleImage(int w, int h) 
        {
            width = w;
            height = h;
	}
	
        Dimension getSize()
        {
            return new Dimension (width, height);
        }
        
	public void init() {
		try {
			ObjectInputStream ois = new ObjectInputStream(getClass().getResourceAsStream("gradients.ser"));
			gradients = (Object[])ois.readObject();
			ois.close();
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		//addMouseListener(this);
		setGradient(3);
		int numFilters = 8;
		filters = new Filter[numFilters];
		filters[0] = new ShiftDownFilter();
		filters[1] = new ShiftUpFilter();
		filters[2] = new ConvolveFilter();
		filters[3] = new BlurHFilter();
		filters[4] = new BlurVFilter();
		filters[5] = new ThingFilter();
		filters[6] = new WaterFilter();
		filters[7] = new ClearFilter();
		filters[3].setEnabled(true);
		filters[4].setEnabled(true);

		int numActions = 1;
		actions = new Action[numActions];
		int numParticles = getIntParameter("numParticles", 100);
		Particles particles = new Particles(numParticles, width/2, height/2, width, height);
		actions[0] = particles;
		actions[0].setEnabled(true);
		particles.rate = getIntParameter("rate", 100);
		particles.speed = (getIntParameter("speed", 0) << 8) / 10;
		particles.angle = getIntParameter("angle", 0);
		particles.spread = getIntParameter("spread", 360);
		particles.gravity = getIntParameter("gravity", 0);
		particles.color = getIntParameter("color", 255);
		particles.scatter = getIntParameter("scatter", 0);
		particles.hscatter = getIntParameter("hscatter", 0);
		particles.vscatter = getIntParameter("vscatter", 0);
		particles.randomness = getIntParameter("randomness", 0);
		particles.size = getIntParameter("size", 2);
		particles.x = getIntParameter("x", width/2);
		particles.y = getIntParameter("y", height/2);
		particles.lifetime = getIntParameter("lifetime", 50);
		particles.speedVariation = (getIntParameter("speedVariation", 0) << 8) / 10;
		particles.decay = getIntParameter("decay", 0);
		startAnimation = getIntParameter("startAnimation", 1) != 0;
		int colormap = getIntParameter("colormap", 4);
		setGradient(colormap);
                
                
		String actions = getParameter("actions");
		if (actions != null) {
			String s = "duchvtwc";
			for (int i = 0; i < s.length(); i++)
				filters[i].setEnabled(actions.indexOf(s.charAt(i)) != -1);
		}
	}

	private int getIntParameter(String name, int defaultValue) {
		if (name != null) {
			try {
				return Integer.parseInt(getParameter(name));
			}
			catch (NumberFormatException e) {
			}
		}
		return defaultValue;
	}
	
	public void setGradient(int n) {
		n = Math.max(0, Math.min(n, gradients.length-1));
		byte[] r = new byte[256];
		byte[] g = new byte[256];
		byte[] b = new byte[256];
		for (int i = 0; i < 256; i++) {
			int rgb = ((Gradient)gradients[n]).getColor((float)(i/255.0));
			r[i] = (byte)((rgb >> 16) & 0xff);
			g[i] = (byte)((rgb >> 8) & 0xff);
			b[i] = (byte)(rgb & 0xff);
		}
		colorModel = new IndexColorModel(8, 256, r, g, b);
	}
	
	public Dimension getPreferredSize() {
		return new Dimension(width, height);
	}

        /*
        public void mousePressed(MouseEvent e) {
		requestFocus();
		startAnimation = true;
		if (thread == null && !running)
			start();
		else
			running = false;
	}
	*/
	
	public void start() {
		if (startAnimation && thread == null) {
			// APPLET
                        //thread = new Thread(this);
			thread.start();
		}
	}
	
	public void stop() {
		if (thread != null) {
			thread.stop();
			thread = null;
		}
	}
	
	public void run() {
		try {
			running = true;
			while (running) {
				repaintImage();
//				synchronized(this) {
//					wait();
//				}
				Thread.sleep(5);
			}
		}
		catch (InterruptedException e) {
		}
		thread = null;
	}
	
	public void update(Graphics g) {
		paint(g);
	}

	public synchronized void paint(Graphics g) {
		Dimension size = getSize();
		int w = size.width;
		int h = size.height;
		if (newImage || image == null)
			image = makeImage(w, h);
                // APPLET
                //g.drawImage(image, 0, 0, this);
		if (!running) {
			String s = "Click to Start";
			FontMetrics fm = g.getFontMetrics();
			int x = (size.width-fm.stringWidth(s))/2;
			int y = (size.height-fm.getAscent())/2;
			g.setColor(Color.white);
			g.drawString(s, x, y);
		}
		notify();
	}

	private Image makeImage(int w, int h) {
		if (pixels1 == null) {
			int i = 0;
			pixels1 = new byte[width*height];
			pixels2 = new byte[width*height];
			for (i = 0; i < actions.length; i++)
				if (actions[i].isEnabled())
					actions[i].apply(pixels1, width, height);
		} else {
			for (int i = 0; i < filters.length; i++) {
				if (filters[i].isEnabled()) {
					filters[i].apply(pixels1, pixels2, width, height);
					byte[] t = pixels1;
					pixels1 = pixels2;
					pixels2 = t;
				}
			}
			for (int i = 0; i < actions.length; i++)
				if (actions[i].isEnabled())
					actions[i].apply(pixels1, width, height);
		}
		newImage = false;
		if (image == null) {
                        // APPLET
			//image = createImage(source = new MemoryImageSource(w, h, colorModel, pixels1, 0, w));
			source.setAnimated(true);
		} else
			source.newPixels(pixels1, colorModel, 0, w);
		return image;
	}
	
	private void repaintImage() {
		newImage = true;
		// APPLET
                //repaint();
	}
	
}


