import java.awt.Graphics;
import java.awt.Polygon;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Image;
import java.awt.Event;
import java.net.URL;
import java.net.MalformedURLException;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class special_scroller extends java.applet.Applet
	{
		//***************//
		// declarations: //
		//***************//
	
		Image		OffScreenImage; // reduce flicker
		Graphics	OffScreen;		// reduce flicker

		//hold strings ... for use when turning over
		Image       Image1;
		Image		Image2;
		Image		Image3;
		Graphics	Temp;

		Color		BackColor;		// background color
		Color		ForeColor;		// foreground color
		Font		UsedFont;		// font to be used
		Font		UsedFontBold;	// same as UsedFont, but bold
		Font		SmallFont;		// small font
		Font		BigFont;		// big font

		int			CurrentImage = 1;// holds current image number
		
		String      ErrorMsg="";	// contains ErrorMessage, if an error occurs
		String		s1;

		boolean		OverLeft = false;
		boolean		OverRight = false;

		String[]	RawItems;
		String[]	Items;
		String[]	Items1;
		String[]	Items2;

		boolean		Items1Exist = false;
		boolean		Items2Exist = false;

		int l1 = 5;
		int t1 = 5;
		int r1 = 50;
		int b1 = 30;

		//*************//
        // functions:  //
		//*************//
	    
		//******************************//
		// gets the specified parameter // 
	    // and decodes it to a Color    //
		//******************************//
		Color DecodeColor(String param)
			{
				String pString = getParameter(param);
				Color Result = new Color(Integer.parseInt(pString.substring(0,2), 16),
										 Integer.parseInt(pString.substring(2,4), 16),
										 Integer.parseInt(pString.substring(4,6), 16));
				return Result;
			}

		//**************************************//
		// checks, if string contains substring //
		//**************************************//
		boolean SubStringExists(String MainString, String SubString)
			{
				int index = MainString.indexOf(SubString);
				boolean Result;
				if ((index >= 0) & (index < MainString.length())) Result = true;
					else
						Result = false;
				return Result;
			}

		//*****************************//
		// get the specified parameter //
		// and decodes it to a Font    //
		//*****************************//
		Font DecodeFont(String param)
			{
				int    FontStyle;
				int    FontSize;
				String FontName;
				Font   Result;

				String pString = getParameter(param);
				if (pString == null) Result = new Font("Arial", Font.PLAIN, 8);
					else
						{
							int ende = pString.indexOf(",");
							FontSize = Integer.parseInt(pString.substring(0, ende));
							int ende1 = pString.indexOf(",", ende+1);
							FontName = pString.substring(ende+2, ende1);
							pString = pString.toUpperCase();
							FontStyle = Font.PLAIN;
							if (SubStringExists(pString, "ITALIC"))
								FontStyle += Font.ITALIC;
							if (SubStringExists(pString, "BOLD"))
								FontStyle += Font.BOLD;
							Result = new Font(FontName, FontStyle, FontSize);
						}
				return Result;
			}
		
		//****************************//
		// gets specified parameter	  //
		// and converts it to integer //
		//****************************//
		int DecodeInteger(String param)
			{
				String pString = getParameter(param);
				return Integer.parseInt(pString);
			}

		//**************************//
		// checks, if param exists  //
		//**************************//
		boolean ParamExists(String param)
			{
				String pString = getParameter(param);
				boolean Result;
				if (pString == null) Result = false;
					else
						Result = true;
				return Result;
			}

		//***********************//
		// resizes Items[]-array // 
		//***********************//
		String[] CreateItemArray(int count)
			{
				String ItemArray[] = new String[count];
				for (int i = 0; i <= ItemArray.length; i++)
					{
						ItemArray[0] = "";
					}
				return ItemArray;
			}

		//******************************//
		// identify various font tokens //
		//******************************//
		int FoundIdent(String Line)
			{
				int found = -1;
				int index = -1;
				index = Line.indexOf("<r>");
				if (index != -1) found = 3;
				index = Line.indexOf("<fBIG>");
				if (index != -1) found = 1;
				index = Line.indexOf("<fSMALL>");
				if (index != -1) found = 2;
				index = Line.indexOf("<b>");
				if (index != -1) found = 4;
				return found;
			}

		//****************************//
		// extract string from tokens //
		//****************************//
		String ExtractString(String str, int Token)
			{
				switch (Token)
					{
						case 1:
							str = str.substring(6);
							break;
						case 2:
							str = str.substring(8);
							break;
						case 3:
							str = str.substring(3);
							break;
						case 4:
							{
								int i1 = str.indexOf("<b>")+3;
								int i2 = str.indexOf("</b>", i1);
								str = str.substring(i1, i2);
								break;
							}
						case 10:
							{
								int i1 = str.indexOf("</b>")+4;
								str = str.substring(i1, str.length());
								break;
							}
					}
				return str;
			}

		//**********************************//
		// division returning rounded value //
		//**********************************//
		int div(float x, float y)
			{
				return Math.round(x/y);
			}

		//*****************************//
		// ligthens or darkens a color //
		// by the given parameter      //
		//*****************************//
		Color ModifyColor(Color color, int amount)
			{
				int r = color.getRed();
				int g = color.getGreen();
				int b = color.getBlue();
				r += amount;
				if (r > 255) r = 255;
					else
						if (r < 0) r = 0;
				g += amount;
				if (g > 255) g = 255;
					else
						if (g < 0) g = 0;
				b += amount;
				if (b > 255) b = 255;
					else
						if (b < 0) b = 0;
				Color Result = new Color(r, g, b);
				return Result;
			}

		//********************//
        // applet functions:  //
		//********************//

		public void init()
			{
				if (ParamExists("file1"))
					{
						//initialize input stream:
						InputStream File = null;
						BufferedReader in = null;
						try
							{
								URL FileURL = new URL(getDocumentBase(), getParameter("file1"));
								//open a buffered reader
								in = new BufferedReader(new InputStreamReader(FileURL.openStream()));
								s1 = in.readLine();
								int ItemCount = Integer.parseInt(s1);
        						Items = CreateItemArray(ItemCount);
								//now read all the items
								for (int i=0;i<ItemCount;i++)
									{
										Items[i] = in.readLine();
									}
								try
									{
										in.close();
									} catch (IOException e) {}
							} catch (Exception e) 
								{
									ErrorMsg = e.toString();
								}
					}
				if (ParamExists("file2"))
					{
						Items1Exist = true;
						InputStream File = null;
						BufferedReader in = null;
						try
							{
								URL FileURL = new URL(getDocumentBase(), getParameter("file2"));
								//open a buffered reader
								in = new BufferedReader(new InputStreamReader(FileURL.openStream()));
								s1 = in.readLine();
								int ItemCount = Integer.parseInt(s1);
        						Items1 = CreateItemArray(ItemCount);
								//now read all the items
								for (int i=0;i<ItemCount;i++)
									{
										Items1[i] = in.readLine();
									}
								try
									{
										in.close();
									} catch (IOException e) {}
							} catch (Exception e) 
								{
									ErrorMsg = e.toString();
								}
					}
						else
							{}
				if (ParamExists("file3"))
					{
						Items2Exist = true;
						InputStream File = null;
						BufferedReader in = null;
						try
							{
								URL FileURL = new URL(getDocumentBase(), getParameter("file3"));
								//open a buffered reader
								in = new BufferedReader(new InputStreamReader(FileURL.openStream()));
								s1 = in.readLine();
								int ItemCount = Integer.parseInt(s1);
        						Items2 = CreateItemArray(ItemCount);
								//now read all the items
								for (int i=0;i<ItemCount;i++)
									{
										Items2[i] = in.readLine();
									}
								try
									{
										in.close();
									} catch (IOException e) {}
							} catch (Exception e) 
								{
									ErrorMsg = e.toString();
								}
					}
						else
							{}
				//get colors:
				if (ParamExists("background"))
					BackColor = DecodeColor("background");
						else
							BackColor = Color.white;
				if (ParamExists("foreground"))
					ForeColor = DecodeColor("foreground");
						else
							ForeColor = Color.black;
				//get font and its style:
				UsedFont = DecodeFont("font");
				SmallFont = DecodeFont("smallfont");
				BigFont = DecodeFont("bigfont");
				UsedFontBold = DecodeFont("fontbold");
				//initialize OffScreen Images:
				int w = getSize().width;
				int h = getSize().height;
				OffScreenImage = createImage(w, h);
				OffScreen = OffScreenImage.getGraphics();
				OffScreen.setFont(UsedFont);
				//init FontMetrics':
				FontMetrics Normal	   = getFontMetrics(UsedFont);
				FontMetrics Big		   = getFontMetrics(BigFont);
				FontMetrics Small      = getFontMetrics(SmallFont);
				FontMetrics NormalBold = getFontMetrics(UsedFontBold);
				//initialize other images:
				Image1 = createImage(w, h);
				Temp = Image1.getGraphics();
				Temp.setColor(BackColor);
				Temp.fillRect(0, 0, w, h);
				Temp.setColor(ForeColor);
				setBackground(BackColor);
				int top = 5;
				String s = "";
				int fi = -1;
				int dh = 0;
				int str_w = 0;
				for (int i=0;i<Items.length;i++)
					{
						s = Items[i];
						fi = FoundIdent(s);
						switch (fi)
							{
								case -1: //normal font, left aligned
									s = ExtractString(s, fi);
									Temp.setFont(UsedFont);
									dh = Normal.getHeight();
									str_w = Normal.stringWidth(s);
									top += dh;
									Temp.drawString(s, 2, top);
									break;
								case 1: //big font
									s = ExtractString(s, fi);
									Temp.setFont(BigFont);
									dh = Big.getHeight();
									str_w = Big.stringWidth(s);
									top += dh;
									if (FoundIdent(s) == 3)
										{
											Temp.drawString(s, w-5-str_w, top);
										}
											else
												{
													Temp.drawString(s, div(w, 2)-div(str_w, 2), top);
												}
									break;
								case 2: //small font
									s = ExtractString(s, fi);
									Temp.setFont(SmallFont);
									dh = Small.getHeight();
									str_w = Small.stringWidth(s);
									top += dh;
									if (FoundIdent(s) == 3)
										{
											Temp.drawString(s, w-5-str_w, top);
										}
											else
												{
													Temp.drawString(s, div(w, 2)-div(str_w, 2), top);
												}
									break;
								case 3: //normal font bold, right aligned
									s = ExtractString(s, fi);
									Temp.setFont(UsedFontBold);
									dh = NormalBold.getHeight();
									str_w = NormalBold.stringWidth(s);
									top += dh;
									Temp.drawString(s, w-5-str_w, top);
									break;
								case 4: //normal font, left aligned, bold:
									String s1 = ExtractString(s, fi);
									dh = NormalBold.getHeight();
									str_w = NormalBold.stringWidth(s1);
									String s2 = ExtractString(s, 10);
									int str_w1 = Normal.stringWidth(s2);
									top += dh;
									Temp.setFont(UsedFontBold);
									Temp.drawString(s1, 2, top);
									Temp.setFont(UsedFont);
									Temp.drawString(s2, 2+str_w, top);
									break;
							}
					}
				//initialize other images:
				Image2 = createImage(w, h);
				Temp = Image2.getGraphics();
				Temp.setColor(BackColor);
				Temp.fillRect(0, 0, w, h);
				Temp.setColor(ForeColor);
				setBackground(BackColor);
				top  = 5;
				s = "";
				fi = -1;
				dh = 0;
				str_w = 0;
				for (int i=0;i<Items1.length;i++)
					{
						s = Items1[i];
						fi = FoundIdent(s);
						switch (fi)
							{
								case -1: //normal font, left aligned
									s = ExtractString(s, fi);
									Temp.setFont(UsedFont);
									dh = Normal.getHeight();
									str_w = Normal.stringWidth(s);
									top += dh;
									Temp.drawString(s, 2, top);
									break;
								case 1: //big font
									s = ExtractString(s, fi);
									Temp.setFont(BigFont);
									dh = Big.getHeight();
									str_w = Big.stringWidth(s);
									top += dh;
									if (FoundIdent(s) == 3)
										{
											Temp.drawString(s, w-5-str_w, top);
										}
											else
												{
													Temp.drawString(s, div(w, 2)-div(str_w, 2), top);
												}
									break;
								case 2: //small font
									s = ExtractString(s, fi);
									Temp.setFont(SmallFont);
									dh = Small.getHeight();
									str_w = Small.stringWidth(s);
									top += dh;
									if (FoundIdent(s) == 3)
										{
											Temp.drawString(s, w-5-str_w, top);
										}
											else
												{
													Temp.drawString(s, div(w, 2)-div(str_w, 2), top);
												}
									break;
								case 3: //normal font bold, right aligned
									s = ExtractString(s, fi);
									Temp.setFont(UsedFontBold);
									dh = NormalBold.getHeight();
									str_w = NormalBold.stringWidth(s);
									top += dh;
									Temp.drawString(s, w-5-str_w, top);
									break;
								case 4: //normal font, left aligned, bold:
									String s1 = ExtractString(s, fi);
									dh = NormalBold.getHeight();
									str_w = NormalBold.stringWidth(s1);
									String s2 = ExtractString(s, 10);
									int str_w1 = Normal.stringWidth(s2);
									top += dh;
									Temp.setFont(UsedFontBold);
									Temp.drawString(s1, 2, top);
									Temp.setFont(UsedFont);
									Temp.drawString(s2, 2+str_w, top);
									break;
							}
					}
				//initialize other images:
				if (Items2Exist)
				{
				Image3 = createImage(w, h);
				Temp = Image3.getGraphics();
				Temp.setColor(BackColor);
				Temp.fillRect(0, 0, w, h);
				Temp.setColor(ForeColor);
				setBackground(BackColor);
				top  = 5;
				s = "";
				fi = -1;
				dh = 0;
				str_w = 0;
				for (int i=0;i<Items2.length;i++)
					{
						s = Items2[i];
						fi = FoundIdent(s);
						switch (fi)
							{
								case -1: //normal font, left aligned
									s = ExtractString(s, fi);
									Temp.setFont(UsedFont);
									dh = Normal.getHeight();
									str_w = Normal.stringWidth(s);
									top += dh;
									Temp.drawString(s, 2, top);
									break;
								case 1: //big font
									s = ExtractString(s, fi);
									Temp.setFont(BigFont);
									dh = Big.getHeight();
									str_w = Big.stringWidth(s);
									top += dh;
									if (FoundIdent(s) == 3)
										{
											Temp.drawString(s, w-5-str_w, top);
										}
											else
												{
													Temp.drawString(s, div(w, 2)-div(str_w, 2), top);
												}
									break;
								case 2: //small font
									s = ExtractString(s, fi);
									Temp.setFont(SmallFont);
									dh = Small.getHeight();
									str_w = Small.stringWidth(s);
									top += dh;
									if (FoundIdent(s) == 3)
										{
											Temp.drawString(s, w-5-str_w, top);
										}
											else
												{
													Temp.drawString(s, div(w, 2)-div(str_w, 2), top);
												}
									break;
								case 3: //normal font bold, right aligned
									s = ExtractString(s, fi);
									Temp.setFont(UsedFontBold);
									dh = NormalBold.getHeight();
									str_w = NormalBold.stringWidth(s);
									top += dh;
									Temp.drawString(s, w-5-str_w, top);
									break;
								case 4: //normal font, left aligned, bold:
									String s1 = ExtractString(s, fi);
									dh = NormalBold.getHeight();
									str_w = NormalBold.stringWidth(s1);
									String s2 = ExtractString(s, 10);
									int str_w1 = Normal.stringWidth(s2);
									top += dh;
									Temp.setFont(UsedFontBold);
									Temp.drawString(s1, 2, top);
									Temp.setFont(UsedFont);
									Temp.drawString(s2, 2+str_w, top);
									break;
							}
					}
				}
			}

		public void update(Graphics g)
			{
				paint(g);
			}

		public void destroy()
			{
				OffScreen.dispose();
			}

		public boolean mouseMove(Event event, int i, int j)
			{
				if (((i >= l1) && (i <= r1)) && ((j >= t1) && (j <= b1)))
					{
						if (OverLeft != true)
							{
								OverLeft = true;
								repaint();
							}
					}
						else
							{
								if (OverLeft)
									{
										OverLeft = false;
										repaint();
									}
							}
				int w = getSize().width-1;
				if (((i <= w-l1) && (i >= w-r1)) && ((j >= t1) && (j <= b1)))
					{
						if (OverRight != true)
							{
								OverRight = true;
								repaint();
							}
					}
						else
							{
								if (OverRight)
									{
										OverRight = false;
										repaint();
									}
							}
				return true;
			}

		public boolean mouseExit(Event event, int i, int j)
			{
				if (OverRight)
					{
						OverRight = false;
						repaint();
					}
				if (OverLeft)
					{
						OverLeft = false;
						repaint();
					}
				return true;
			}

		public boolean mouseDown(Event event, int i, int j)
			{
				if (OverLeft)
					{
						CurrentImage--;
						if (CurrentImage == 0)
							{
								if (Items2Exist)
									CurrentImage = 3;
										else
											CurrentImage = 2;
							}
					}
				if (OverRight)
					{
						CurrentImage++;
						if ((Items2Exist == false) && (CurrentImage == 3))
							CurrentImage = 1;
								else
									{
										if (CurrentImage == 4)
											CurrentImage = 1;
									}
					}
				repaint();
				return true;
			}

		public void paint(Graphics canvas)
			{
				//fill rectangel with background color:
				OffScreen.setColor(BackColor);
				OffScreen.fillRect(0, 0, getSize().width, getSize().height);
				OffScreen.setColor(ForeColor);
				setBackground(BackColor);
				//draw on OffScreenImage:
				switch (CurrentImage)
					{
						case 1:
							OffScreen.drawImage(Image1, 0, 0, this);
							break;
						case 2:
							OffScreen.drawImage(Image2, 0, 0, this);
							break;
						case 3:
							OffScreen.drawImage(Image3, 0, 0, this);
							break;
					}
				//draw buttons:
				//left button:
				OffScreen.setColor(ModifyColor(BackColor, -20));
				OffScreen.fillRect(l1, t1, r1-l1+1, b1-t1+1);
				OffScreen.setColor(ModifyColor(BackColor, -40));
				OffScreen.fillRect(l1+1, t1+1, r1-l1-1, b1-t1-1);
				OffScreen.setColor(ModifyColor(BackColor, -60));
				OffScreen.fillRect(l1+2, t1+2, r1-l1-3, b1-t1-3);
				OffScreen.setColor(ModifyColor(ForeColor, 150));
				{
				int h = b1-t1-6;
				int w = r1-l1-6;
				int b = div (h, 2);
				int px[] = {div(w,2)+l1-b, div(w,2)+l1+b, div(w,2)+l1+b};
				int py[] = {div(h,2)+t1+3, div(h,2)+t1+3+b, div(h,2)+t1+3-b};
				int points = px.length;
				Polygon poly = new Polygon(px, py, points);
				OffScreen.fillPolygon(poly);
				}
				//right button:
				{
				int wi = getSize().width-1;
				OffScreen.setColor(ModifyColor(BackColor, -20));
				OffScreen.fillRect(wi-r1, t1, r1-l1+1, b1-t1+1);
				OffScreen.setColor(ModifyColor(BackColor, -40));
				OffScreen.fillRect(wi-r1+1, t1+1, r1-l1-1, b1-t1-1);
				OffScreen.setColor(ModifyColor(BackColor, -60));
				OffScreen.fillRect(wi-r1+2, t1+2, r1-l1-3, b1-t1-3);
				OffScreen.setColor(ModifyColor(ForeColor, 150));
				int h = b1-t1-6;
				int w = r1-l1-6;
				int b = div (h, 2);
				int px[] = {wi-div(w,2)-l1+b, wi-div(w,2)-l1-b, wi-div(w,2)-l1-b};
				int py[] = {div(h,2)+t1+3, div(h,2)+t1+3+b, div(h,2)+t1+3-b};
				int points = px.length;
				Polygon poly = new Polygon(px, py, points);
				OffScreen.fillPolygon(poly);
				}
				//draw activated button:
				if (OverLeft)
					{
						 OffScreen.setColor(ModifyColor(BackColor, -40));
						 OffScreen.fillRect(l1, t1, r1-l1+1, b1-t1+1);
						 OffScreen.setColor(ModifyColor(BackColor, -100));
						 OffScreen.fillRect(l1+1, t1+1, r1-l1-1, b1-t1-1);
						 OffScreen.setColor(ModifyColor(BackColor, -140));
						 OffScreen.fillRect(l1+2, t1+2, r1-l1-3, b1-t1-3);
						 OffScreen.setColor(ForeColor);
						 int h = b1-t1-6;
						 int w = r1-l1-6;
						 int b = div (h, 2);
						 int px[] = {div(w,2)+l1-b, div(w,2)+l1+b, div(w,2)+l1+b};
						 int py[] = {div(h,2)+t1+3, div(h,2)+t1+3+b, div(h,2)+t1+3-b};
						 int points = px.length;
						 Polygon poly = new Polygon(px, py, points);
						 OffScreen.fillPolygon(poly);
					}
						else
							{
							}
				if (OverRight)
					{
						int wi = getSize().width-1;
						OffScreen.setColor(ModifyColor(BackColor, -40));
						OffScreen.fillRect(wi-r1, t1, r1-l1+1, b1-t1+1);
						OffScreen.setColor(ModifyColor(BackColor, -100));
						OffScreen.fillRect(wi-r1+1, t1+1, r1-l1-1, b1-t1-1);
						OffScreen.setColor(ModifyColor(BackColor, -140));
						OffScreen.fillRect(wi-r1+2, t1+2, r1-l1-3, b1-t1-3);
						OffScreen.setColor(ForeColor);
						int h = b1-t1-6;
						int w = r1-l1-6;
						int b = div (h, 2);
						int px[] = {wi-div(w,2)-l1+b, wi-div(w,2)-l1-b, wi-div(w,2)-l1-b};
						int py[] = {div(h,2)+t1+3, div(h,2)+t1+3+b, div(h,2)+t1+3-b};
						int points = px.length;
						Polygon poly = new Polygon(px, py, points);
						OffScreen.fillPolygon(poly);
					}
				//copy OffScreenImage to Screen:
	    		canvas.drawImage(OffScreenImage, 0, 0, this);
			}

		public String getAppletInfo()
			{
				return "Title: Menucard-Applet \nAuthor: Klaus Burgstaller \nThis applet was especially created for \nthe Schärdinger Wurstkuchl \nlast modified on 29.12.2001 \ncopyright (c) by Klaus Burgstaller. \nwww.crosswinds.net/~burgstaller";
			}

		public String[][] getParameterInfo()
			{
				String[][] info =	{
										{"file1-3", "path string", "Specifies file containing data to display as relative path. \nThis parameter has no default value. The component doesn't work otherwise!"},
										{"foreground", "hex color", "Foreground color in hex format: RRGGBB"},
										{"background", "hex color", "Works the same way for the back ground color"},
										{"fonts", "font size, font name, font style", "contains description about the font style: \nfirst parameter is font size, second font name, \nadditional font stylings can be given: BOLD, ITALIC, PLAIN. \nYou may write the font stylings upper od lower case. \nDefault = Arial, plain, size:12 ."},
									};
				return info;
			}
	}