import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

class ScottCanvas extends Canvas {
	int x, yLine;
	int bottom_x;
	int textLines;
	int myWidth;
	int myHeight;
	int spaceWidth;
	int wWidth;	/* 'w' is a good letter for guessing with */
	int lineHeight;
	String[] textLine;
	Font myFont;
	Display display;
	ScottFree myOwner;
	boolean splitScreen;
	int scrollLine;

	public int Characters() {
		return textLines * (myWidth/wWidth);
	}
	public int Lines() {
		return textLines;
	}
	void TryFont(int size) {
		myFont = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN, size);
		spaceWidth = myFont.stringWidth(" ");
		wWidth = myFont.stringWidth("w");
		myWidth = getWidth();
		myHeight = getHeight();
		lineHeight =  myFont.getHeight() + 1;
		textLines = myHeight / lineHeight;
	}
	public ScottCanvas(ScottFree owner) {
		super();

		myOwner = owner;
		/* Try and pick a font. It might also make sense if we
		   considered going to the original split screen format
		   on big displays. Someone buy me a phone with a big
		   screen if they want that implementing ;) */
		/* PS: Joke - implement it yourself */
		TryFont(Font.SIZE_SMALL);
		if(Characters() > 480)
			TryFont(Font.SIZE_MEDIUM);
		if(Characters() < 800 || Lines() < 12)
			TryFont(Font.SIZE_SMALL);
		textLine = new String[textLines];
		/* System.out.println("Lines "+textLines); */
		ClearScreen();
	}
	protected void paint (Graphics g) {
		/* Should check for changes ?? */
		g.setColor(255,255,255);
		g.fillRect(0, 0, myWidth, myHeight);
		g.setColor(0, 0, 0);
		g.setFont(myFont);
		for(int i = 0; i < textLines; i++) {
			g.drawString(textLine[i], 0, i * lineHeight,
				Graphics.LEFT|Graphics.TOP);
		}
		/* System.out.println("Painted"); */
	}
	/*
 	 *	Scroll the dumb terminal
	 */
	void ScrollUp() {
		if(yLine < textLines - 1) {
			yLine++;
			x = 0;
			return;
		}
		/* We supress repeated newtextLines due to screen size */
		if(x != 0) {
			for(int i = scrollLine + 1; i < textLines; i++)
				textLine[i-1] = textLine[i];
			textLine[textLines-1] = "";
			x = 0;
			/* System.out.println("Scrolled");*/ 
		}
	}
	/*
 	 *	Add a single word to the display, scroll if necessary.
	 */
	void AddWord(String s) {
		int pad = 0;

		/* Eliminate multiple spacers given screen size */
		if(s.length() == 0)
			return;

		/* How long is it, including a space if needed */
		int wordsize = myFont.stringWidth(s);
		if(x != 0)
			pad = spaceWidth;
		/* If it doesn't fit we scroll */
		if(wordsize < myWidth && wordsize + pad + x >= myWidth) {
			ScrollUp();
		}
		/* Add the text */
		if(x != 0)
			textLine[yLine] = textLine[yLine] + " " + s;
		else
			textLine[yLine] = s;
		x += wordsize + spaceWidth;
	}
	/*
	 *	Wipe the terminal window.
	 */
	public void ClearScreen() {
		int bottom = scrollLine - 1;

		if(splitScreen == false)
			bottom = textLines;
		
		for(int i = 0; i < bottom; i++) {
			textLine[i] = "";
		}
		x = 0;
	}
	/*
 	 *	Run dumb terminal emulation and format up the new text
	 *	including word breaking.
	 */
	public void AddString(String s) {
		while (true) {
			/*
 			 *	Scroll leading newlines
			 */
			if(s.length() > 0 && s.charAt(0) == '\n') {
				ScrollUp();
				s = s.substring(1);
				continue;
			}
			/*
 			 *	Look for formatting
			 */
			int p = s.indexOf(' ');
			int nl = s.indexOf('\n');
			/*
			 *	Who is first ?
			 */
			if(nl != -1 && (p == -1 || p > nl))
				p = nl;
			/*
 			 *	End word
			 */
			if(p == -1) {
				AddWord(s); 
				return;
			}
			/*
			 *	Split a word, process and loop
			 */
			String word = s.substring(0, p);
			AddWord(word);
			if(s.charAt(p) == '\n')
				ScrollUp();
			s = s.substring(p+1, s.length());
		}
	}
	/*
	 *	Mode management
	 */
	public void SplitScreen() {
		splitScreen = true;
		SwitchToBottomScreen();
	}
	public void SwitchToTopScreen() {
		if(splitScreen) {
			/* Clear screen may corrupt so save first */
			bottom_x = x;
			ClearScreen();
			yLine = 0;
		}
		else AddString("\n");
	}
	public void SwitchToBottomScreen() {
		if(splitScreen) {
			scrollLine = yLine + 1;
			x = bottom_x;
			yLine = textLines - 1;
		}
	}
	/*
 	 *	Display ourself
	 */
	public void SetCurrent() {
		display.setCurrent(this);
	}
	/*
	 *	Make sure the user view is currnet
	 */
	public void Refresh() {
		repaint();
	}
	/*
	 *	Allow our owner to inform us of the display
	 *	we are to use.
	 */
	public void SetDisplay(Display d) {
		display = d;
	}
	/*
	 *	Input operators. Pass keys upstream
	 */

	public void keyPressed(int keyCode) {
		if(myOwner == null)
			return;
		keyCode = getGameAction(keyCode);
		switch(keyCode) {
		case LEFT:
			myOwner.PerformCommand("WEST");
			return;
		case RIGHT:
			myOwner.PerformCommand("EAST");
			return;
		case UP:
			myOwner.PerformCommand("NORTH");
			return;
		case DOWN:
			myOwner.PerformCommand("SOUTH");
			return;
		}
	}
}
