/* 
	Snow.java

	[ more java @ mlab - 10-17.1.2000 - juhuu@katastro.fi ]
*/

import java.applet.Applet;
import java.awt.*;
import java.net.*;
import java.util.*;
import Flake;

public class Snow extends Applet implements Runnable{	Image		imgDoubleBuffer;
	Graphics	gDoubleBuffer;
	Thread		engine = null;  	int			nMousex, nMousey;
	boolean 	bMouse_down;
		Image 		imgPic;
	Image 		imgPic2;
	Image 		imgBackground;
	Image 		imgBack2;
	Graphics	gBack2;

	int			nSnow_amount;
	Flake[]		flakes;	int[]		nSnow_pile;
	
	int			nScr_width;
	int			nScr_height;
	public void init() {
		// initialize double buffering		imgDoubleBuffer = createImage(size().width, size().height);		gDoubleBuffer = imgDoubleBuffer.getGraphics();		gDoubleBuffer.setColor(Color.white);		gDoubleBuffer.fillRect(0, 0, size().width, size().height);

		imgBack2		= createImage(size().width, size().height);		gBack2			= imgBack2.getGraphics();
		nScr_width		= size().width;
		nScr_height		= size().height;
		nMousex 		= 0;
		nMousey 		= 0;
		bMouse_down		= false;

		// amount of snow flakes		nSnow_amount	= 450;
		// flakes
		flakes			= new Flake[nSnow_amount];
		// initialize flakes
		for (int i = 0 ; i < nSnow_amount; i++)		{
			flakes[i] = new Flake(nScr_width * Math.random(), nScr_height * Math.random());		}
		// counters for the snow pile - width of the screen / size of the flake
		nSnow_pile		= new int[nScr_width / 2];				// initialize snow pile counters
		for (int i = 0 ; i < nScr_width / 2; i++)		{
			nSnow_pile[i] = nScr_height;
		}		// let's load the images
		imgPic				= null;

		String sBackground	= "background.jpg";
		String sPic			= "snow.jpg";
		String sPic2		= "snow_purewhite.jpg";

		MediaTracker med	= new MediaTracker(this);

		imgPic = getImage(getDocumentBase(), sPic);
		med.addImage(imgPic, 0);
		imgBackground = getImage(getDocumentBase(), sBackground);
		med.addImage(imgBackground, 1);
		imgPic2 = getImage(getDocumentBase(), sPic2);
		med.addImage(imgPic2, 2);

		try
		{
			for (int i=0 ; i<= 2 ; i++)
			{
		        med.waitForID(i);
			}
		} catch (InterruptedException e) {
			System.out.println("Error loading images...");
			stop();
			return;
		}

		gBack2.drawImage(imgBackground, 0, 0, null);	}

//----------------------------------------------------

	public void paint(Graphics g) {

	  // clear the screen

	//    	gDoubleBuffer.setColor(Color.white);
	//    	gDoubleBuffer.fillRect(0, 0, size().width, size().height);

		if (imgBack2 != null)
		{
			gDoubleBuffer.drawImage(imgBack2, 0, 0, null);

			if (imgPic != null)
			{					int nX_coord_old;
				int nY_coord_old;

				int nX_coord;
				int nY_coord;
				for (int i = 0 ; i < nSnow_amount; i++)				{
					// get the old coordinate									nX_coord_old = flakes[i].getX();
					nY_coord_old = flakes[i].getY();

					// draw the flake					gDoubleBuffer.drawImage(imgPic, nX_coord_old, nY_coord_old, null);
					flakes[i].updatecoords();
										// get the new coordinate					nX_coord = flakes[i].getX();
					nY_coord = flakes[i].getY();
				
					// flake on the screen in x direction ?					if(nX_coord >= 0 && nX_coord < nScr_width)
					{						// if the y coordinate is equal to the amount						// of snow at the current location, draw a snow
						// flake to the current location at the background image						if (nY_coord == (nSnow_pile[nX_coord / 2] - 2))
						{							// draw a flake to the background image
							nSnow_pile[nX_coord / 2] -= 2;							gBack2.drawImage(imgPic2, 2 * (nX_coord / 2), nSnow_pile[nX_coord / 2], null);
							flakes[i] = new Flake(nScr_width * Math.random(), 0);						// if the flake hits the snowpile from the side
						// (the y coordinate is more than the snow amount in current location),
						// return the flake to the previous x coordinate but keep on
						// adding the y coordinate							} else if (nY_coord >= (nSnow_pile[nX_coord / 2] - 2)) {
							flakes[i].setX_keep(2 * (nX_coord_old / 2));							nX_coord = 2 * (nX_coord_old / 2);							// if it didn't help to restore the flake to the
							// old x coordinate (it still hits the pile),
							// then draw the flake to the background image							if(nX_coord >= 0 && nX_coord < nScr_width)
							{								if(nY_coord >= (nSnow_pile[nX_coord / 2] - 2))
								{									// prevent drawing if the coord is way much bigger than									// the pile (avoid the biiig stack at the left end of the									// screen when the flakes coming from outside the screen									// hit the pile)
									if(nY_coord - (nSnow_pile[nX_coord / 2] - 2) < 5)									{
										nSnow_pile[nX_coord / 2] -= 2;										gBack2.drawImage(imgPic2, 2 * (nX_coord / 2), nSnow_pile[nX_coord / 2], null);
									}
									flakes[i] = new Flake(nScr_width * Math.random(), 0);								}
							} else {								flakes[i] = new Flake(nScr_width * Math.random(), 0);							}
						}
					} else if(nY_coord > nScr_height) {					// if flake is not on the screen in x direction
					// and is more than the screen height in y direction,
					// create a new flake						flakes[i] = new Flake(nScr_width * Math.random(), 0);					}				}			}
		}

	  // draw all the stuff from the double buffer to the screen
	  g.drawImage(imgDoubleBuffer, 0, 0, null);				
	}


//----------------------------------------------------


	// start the applet
	public void start() {
		if (engine == null)		{
			engine = new Thread(this);
			engine.start();		}
		showStatus(getAppletInfo());
	} 

	// stop the applet
	public void stop() {
		if (engine != null && engine.isAlive())
		{
			engine.stop();
		}		engine = null; 
	}

	public void run()
	{                  
		while (true)
		{			try			{
				repaint();
				Thread.sleep(10);
			} catch (InterruptedException e) {
				stop();
			}
		}
	}

	public void update(Graphics g) {    
	  paint(g);
	}

	// print to the console & browserstatus
	private void print(String s) {
		System.out.println(s); 		// console
		showStatus(s);         		// browser status  
	}

//---

	public boolean mouseDown(Event e, int x, int y) {
		bMouse_down = true;
		return true;  
	}

	public boolean mouseUp(Event e, int x, int y) {
		bMouse_down = false;
		return true;  
	}

	public boolean mouseMove(Event e, int x, int y)
	{
		nMousex = x;
		nMousey = y;
		return true;  
	}

	public boolean mouseDrag(Event e, int x, int y)
	{
		nMousex = x;
		nMousey = y;
		return true;  
	}
//---
}
