/** Sakura Applet Copyright(c) 2000-2003 WakuWaku.All Rights Reserved. */
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;

public class Sakura extends Applet implements Runnable, MouseMotionListener,MouseListener
{
	private Thread th=null;
	private Image off;
	private Graphics g;
	private int max=20,a=13,w,h,wait=80,mx,my,iCatch=-1;
;
	private Dimension sz;
	private Color backColor=Color.black;
	private boolean isAsyncLoad=false,isPress=false;
	private String fileSakuraSmall, fileSakuraBig, fileBack;
	
	public void init()
	{
		String backs=getParameter("BGCOLOR");
		Color c;
		if(backs!=null && (c=stringToColor(backs))!=null)
			backColor=c;
		setBackground(backColor);
		
		addMouseMotionListener(this);
		addMouseListener(this);
	}
	public void start()
	{

		String maxs=getParameter("MAX")
			,waits=getParameter("WAIT")
			,loads=getParameter("IMAGE_LOAD")
			,as=getParameter("AMPLITUDE");
		fileBack=getParameter("IMG");
		fileSakuraSmall=getParameter("SAKURA_SMALL");
		fileSakuraBig=getParameter("SAKURA_BIG");
		if(maxs!=null)
			try{
				max=Integer.parseInt(maxs);
			}catch(NumberFormatException e){}
		if(waits!=null)
			try{
				wait=Integer.parseInt(waits);
			}catch(NumberFormatException e){}
		if(loads!=null)
			try{
				isAsyncLoad=Boolean.valueOf(loads).booleanValue();
			}catch(NumberFormatException e){}
		if(as!=null)
			try{
				a=Integer.parseInt(as);
			}catch(NumberFormatException e){}
		if(fileSakuraSmall==null)
			fileSakuraSmall="sakura2.gif";
		if(fileSakuraBig==null)
			fileSakuraBig="sakura.gif";
		sz=getSize();
		off=createImage(w=sz.width,h=sz.height);
		g=off.getGraphics();
		g.clearRect(0,0,w,h);
		g.setColor(Color.yellow);
		g.drawString("Loading image...",10,20);
		g.setColor(backColor);
		
		if(th==null)
			th=new Thread(this);
		th.start();
	}
	public void run()
	{
		Random rand=new Random();
		int[]	x=new int[max],
				y=new int[max],
				m=new int[max],
				d=new int[max],
				s=new int[max];
		boolean[] b=new boolean[max];
		Image[] img={getImage(getCodeBase(),fileSakuraBig),
					 getImage(getCodeBase(),fileSakuraSmall),
					 getImage(getCodeBase(),fileBack)};
		Dimension sSize = new Dimension(20,15);
		if(isAsyncLoad)
		{
			loadImages(img);
			sSize.width=img[0].getWidth(this);
			sSize.height=img[0].getHeight(this);
		}
		for(int i=0;i<max;i++)
		{
			x[i]=(int)(rand.nextFloat()*(w-20));
			y[i]=(int)(-rand.nextFloat()*h-30);
			m[i]=(int)(rand.nextFloat()*2*a-a);
			d[i]=(i<max/2)?1:0;
			b[i]=(int)(rand.nextFloat())==0;
			s[i]=(int)(rand.nextFloat()*3+5);
		}

		while(th!=null)
		{
			if(img[2]==null)
				g.fillRect(0,0,w,h);
			else
				g.drawImage(img[2],0,0,this);
			for(int i=0;i<max;i++)
			{
				if(m[i]==a || m[i]==-a)
					b[i]=!b[i];
				m[i]+=b[i]?1:-1;
				
				if(isPress && d[i]==0 &&
					(iCatch==i || iCatch<0 && abs(mx-x[i]-sSize.width/2)<sSize.width/2
					&& abs(my-y[i]-sSize.width/2)<sSize.height/2))
				{
					x[i]=mx-sSize.width/2;
					y[i]=my-sSize.height/2;
					m[i]=0;
					iCatch=i;
				}else
				{
					x[i]+=m[i];
					if(y[i]<h)
						y[i]+=s[i];
					else
					{
						x[i]=(int)(rand.nextFloat()*(w-20));
						y[i]=-(int)(rand.nextFloat()*5)-img[d[i]].getHeight(this);
					}
				}
				g.drawImage(img[d[i]],x[i],y[i],this);
			}
			repaint();
			try
			{
				Thread.sleep(wait);
			}catch(InterruptedException e){}
		}
	}

	// 高速化のため自作abs
	private static final int abs(int i)
	{
		return i > 0 ? i : -i;
	}
	public void stop()
	{
		if(th!=null)
		{
			th.stop();
			th=null;
		}
	}
	public void update(Graphics g)
	{
		paint(g);
	}
	public void paint(Graphics g)
	{
		g.drawImage(off,0,0,this);
	}
	
	protected void loadImages(Image[] img)
	{
		MediaTracker mt=new MediaTracker(this);
		for(int i=0;i<img.length;i++)
			mt.addImage(img[i],i);
		try
		{
			mt.waitForAll();
		}catch(Exception e){}
	}
	private static Color stringToColor(String paramValue)
	{//"rrggbb" 形式の文字列をColorオブジェクトに変換
		int red;
		int green;
		int blue;

		try
		{
			red = (Integer.decode("0x" + paramValue.substring(0,2))).intValue();
			green = (Integer.decode("0x" + paramValue.substring(2,4))).intValue();
			blue = (Integer.decode("0x" + paramValue.substring(4,6))).intValue();
			return new Color(red,green,blue);
		}catch(Exception e)
		{
			return null;
		}
	}
	public void mouseMoved(MouseEvent e){}
	public void mouseDragged(MouseEvent e)
	{//マウスカーソルがドラッグされた
		mx=e.getX();
		my=e.getY();
	}
	public void mouseExited(MouseEvent e){}
	public void mouseReleased(MouseEvent e)
	{
		isPress=false;
		iCatch=-1;
	}
	public void mousePressed(MouseEvent e)
	{
		if(e.getModifiers()==16)	//左クリック
		{
			isPress=true;
			mouseDragged(e);
		}
	}
	public void mouseEntered(MouseEvent e){}
	public void mouseClicked(MouseEvent e){}
}

