/*
A Christmas gift from RealApplets
Http://www.realapplets.com
By Bavo Bruylandt
You are allowed to make changes as long as you
give me any credit for the surviving code :)
Enjoy!
*/




import java.awt.*;
import java.applet.*;
import java.net.*;

public class RealSnow extends Applet implements Runnable
{
	private Thread animThread;
	private Graphics buffG;
	private Image buff;
	private Image bgimage;
	private Dimension dim;
	private boolean running;
	private int delay= 40;
	private Wind [] winds;
	private Snow [] flakes;
	private int numberOfFlakes = 500;
	private int numberOfWinds = 0;
	private int nsbug;

	public void init() 
	{
		
		setBackground(Color.black);
		dim = getSize();
		buff = createImage(dim.width,dim.height);
		buffG = buff.getGraphics();
		String bg = getParameter("Background");
		numberOfFlakes = Integer.parseInt(getParameter("NumberOfFlakes"));
		numberOfWinds = Integer.parseInt(getParameter("Turbulence"));
		bgimage =  getImage(getDocumentBase(),bg);
		initWind();
		initSnow();
		System.out.println("Starting life and struggling to survive");
	}
	
		public void start() 
	{
		System.out.println("Started");
		nsbug = 0;
		if (animThread == null) 
		{
			running = true;
			animThread = new Thread(this);
			animThread.start();
			
		}
	}
	
	public void stop() 
	{
		if (nsbug <30) 
		{
			System.out.println("Early kill by NS, ignoring ("+nsbug+")");
		}
		else 
		{
			System.out.println("Stop called, ending ("+nsbug+")");
			running = false;
	    	animThread = null;
		}
	}
	
	public void destroy() 
	{
		System.out.println("Destroy called, bye bye");
		running = false;
		animThread = null;
		
	}
	
	private void initSnow() 
	{
		flakes = new Snow [getNumberOfFlakes()];
		for (int a=0;a<getNumberOfFlakes();a++) 
		{
			flakes[a] = new Snow(dim.width,dim.height);
		}
	}
	
	private void initWind() 
	{
		winds = new Wind [getNumberOfWinds()];
		for (int a=0;a<getNumberOfWinds();a++) 
		{
		winds[a] = new Wind(dim.width,dim.height);
		}
	}
	
	private int getNumberOfFlakes() 
	{
		return numberOfFlakes;
	}
	
	private int getNumberOfWinds() 
	{
		return numberOfWinds;
	}
	

	
	
	public void paint(Graphics g) 
	{
		buffG.setColor(Color.black);
		buffG.fillRect(0,0,dim.width,dim.height);
		buffG.drawImage(bgimage,0,0,this);
		buffG.setColor(Color.white);
		for (int a=0;a<getNumberOfFlakes();a++) 
		{
			if (flakes[a].isAlive())
			{
				
				buffG.drawRect(flakes[a].getXco(),flakes[a].getYco(),flakes[a].getSize(),flakes[a].getSize());
				
			}
		}
		
		g.drawImage(buff,0,0,this);
	}
	
	public void update(Graphics g) 
	{
		paint(g);
	}
	
	private void moveSnowFlakes() 
	{
		for (int a=0;a<getNumberOfFlakes();a++) 
		{
			flakes[a].move();
		}
	}
	
	private void makeWind() 
	{
		for (int a=0;a<getNumberOfWinds();a++) 
		{
		if (!winds[a].isAlive()) winds[a].newWind();
		else winds[a].move();
		}
	}
	
	private void dodgeFlakes() 
	{
		for (int c=0;c<getNumberOfWinds();c++)  
		{
			Wind wind = winds[c];
		for (int a=0;a<getNumberOfFlakes();a++)
		{
			if (flakes[a].getDepth() == wind.getDepth()) 
			{
			if (flakes[a].isAlive()) 
			{
				if (wind.isAlive()) 
				{
					if (wind.getXco() < flakes[a].getXco() && wind.getXco()+wind.getWidth() > flakes[a].getXco()) 
					{
						if (wind.getYco() < flakes[a].getYco() && wind.getYco()+wind.getHeight() > flakes[a].getYco()) 
						{
							flakes[a].dodge(wind.getSign()*wind.getStrength());
						}
					}
				}
			}
			}
		}
		}
	}
	
	private void makeFlakes() 
	{
		for (int a = 0;a<4;a++) 
		{
			for (int b = 0;b<getNumberOfFlakes();b++) 
			{
				if (!flakes[b].isAlive()) 
				{
					flakes[b].newFlake();
					break;
				}
			}
		}
	}
				
		
		
	
	public void run() 
	{
		while (running) 
		{
			try 
			{
				nsbug++;
				makeFlakes();
				makeWind();
				dodgeFlakes();
				moveSnowFlakes();
				repaint();
				animThread.sleep(delay);
				
			}
			catch (Exception e) 
			{
				System.out.println("Thread Mesg: "+e);
			}
		}
	}
}