// Alea - a simple RPG dice roller for mobile devices
// 2010-03-11 Felix Pleșoianu <felixp7@yahoo.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package ro.plesoianu;

import java.util.Random;
import javax.microedition.io.ConnectionNotFoundException;
import java.io.IOException;

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

public class Alea extends MIDlet
		implements CommandListener, ItemCommandListener {
	private MainScreen top;
	private TextBox results =
		new TextBox("Roll results", null, 1024, TextField.ANY);
	
	private Command results_cmd =
		new Command("Last roll", Command.SCREEN, 10);
	private Command about_cmd =
		new Command("About Alea", Command.HELP, 10);
	private Command exit_cmd =
		new Command("Exit", Command.EXIT, 10);
	private Command close_results_cmd =
		new Command("Back", Command.BACK, 10);

	private Form about;
	private StringItem author_link;
	private Command author_cmd;
	private StringItem license_link;
	private Command license_cmd;
	private StringItem images_link;
	private Command images_cmd;
	private Alert web_fail;
	private Command close_about_cmd;
		
	private int num_dice = 2;
	private int dice_type = 3;
	private int[] dice_types = {2, 3, 4, 6, 8, 10, 12, 20, 30, 100};
	
	private Random rng = new Random();
		
	public Alea() {
		top = new MainScreen(this);
		top.addCommand(results_cmd);
		top.addCommand(about_cmd);
		top.addCommand(exit_cmd);
		top.setCommandListener(this);

		results.addCommand(close_results_cmd);
		results.setCommandListener(this);
	}

	public void startApp() {
		Display.getDisplay(this).setCurrent(top);
	}
	public void pauseApp() { }
	public void destroyApp(boolean unconditional) { }
	
	public void commandAction(Command c, Displayable s) {
		if (c == exit_cmd) {
			notifyDestroyed();
		} else if (c == results_cmd) {
			Display.getDisplay(this).setCurrent(results);
		} else if (c == close_results_cmd) {
			Display.getDisplay(this).setCurrent(top);
		} else if (c == about_cmd) {
			initAboutScreen();
			Display.getDisplay(this).setCurrent(about);
		} else if (c == close_about_cmd) {
			Display.getDisplay(this).setCurrent(top);
		}
	}

	public void commandAction(Command c, Item i) {
		if (c == author_cmd) {
			try {
				platformRequest("http://felix.plesoianu.ro/");
			} catch (ConnectionNotFoundException e) {
				Display.getDisplay(this).setCurrent(web_fail);
			}
		} else if (c == license_cmd) {
			try {
				platformRequest("http://opensource.org/licenses/mit-license.php");
			} catch (ConnectionNotFoundException e) {
				Display.getDisplay(this).setCurrent(web_fail);
			}
		} else if (c == images_cmd) {
			try {
				platformRequest("http://en.wikipedia.org/wiki/File:DnD_Dice_Set.jpg");
			} catch (ConnectionNotFoundException e) {
				Display.getDisplay(this).setCurrent(web_fail);
			}
		}
	}
	
	private void initAboutScreen() {
		if (about != null) return;
		
		about = new Form("About Alea");
		author_link = new StringItem(
			"Author", "Felix Pleșoianu", Item.HYPERLINK);
		author_cmd = new Command(
			"Author's Website", Command.ITEM, 10);
		license_link = new StringItem(
			"License", "MIT (Open Source)", Item.HYPERLINK);
		license_cmd = new Command("License text", Command.ITEM, 10);
		images_link = new StringItem(
			"Dice images", "Public domain from Wikipedia",
			Item.HYPERLINK);
		images_cmd = new Command("Image source", Command.ITEM, 10);
		web_fail = new Alert(
			"Failure", "Can't open webpage", null, AlertType.ERROR);
		close_about_cmd = new Command("Back", Command.BACK, 10);
		
		about.append("Alea, a simple RPG dice roller");
		author_link.setDefaultCommand(author_cmd);
		author_link.setItemCommandListener(this);
		about.append(author_link);
		license_link.setDefaultCommand(license_cmd);
		license_link.setItemCommandListener(this);
		about.append(license_link);
		images_link.setDefaultCommand(images_cmd);
		images_link.setItemCommandListener(this);
		about.append(images_link);
		about.append("Did I mention 'Alea' means 'dice' in Latin?");
		about.addCommand(close_about_cmd);
		about.setCommandListener(this);
	}

	public int getNumDice() { return num_dice; }
	public int getNumFaces() { return dice_types[dice_type]; }
	public int getDiceType() { return dice_type; }
	public void moreDice() { if (num_dice < 20) num_dice++; }
	public void fewerDice() { if (num_dice > 1) num_dice--; }
	
	public void nextType() {
		if (++dice_type >= dice_types.length) dice_type = 0;
	}
	
	public void prevType() {
		if (--dice_type < 0) dice_type = dice_types.length - 1;
	}
	
	public void roll(int times) {
		if (times <= 0) return;
		
		StringBuffer buf = new StringBuffer();
		for (int i = 0; i < times; i++) {
			int sum = 0;
			for (int j = 0; j < num_dice; j++) {
				int roll = rng.nextInt(
					dice_types[dice_type]) + 1;
				buf.append(roll);
				buf.append(" ");
				sum += roll;
			}
			buf.append(" = ");
			buf.append(sum);
			buf.append("\n");
		}
		
		results.setString(buf.toString());
		Display.getDisplay(this).setCurrent(results);
	}
}

class MainScreen extends Canvas {
	private Alea roller;
	
	private Image[] dice_img = new Image[10];
	
	public MainScreen(Alea a) {
		roller = a;
		setTitle("Alea: simple RPG dice roller");

		try {
			dice_img[0] = null;
			dice_img[1] = null;
			dice_img[2] = Image.createImage("/4-sided.jpg");
			dice_img[3] = Image.createImage("/6-sided.jpg");
			dice_img[4] = Image.createImage("/8-sided.jpg");
			dice_img[5] = Image.createImage("/10-sided.jpg");
			dice_img[6] = Image.createImage("/12-sided.jpg");
			dice_img[7] = Image.createImage("/20-sided.jpg");
			dice_img[8] = Image.createImage("/30-sided.jpg");
			dice_img[9] = Image.createImage("/percentile.jpg");
		} catch (IOException e) {
			//
		}
	}
	
	protected void paint(Graphics g) {
		int centerx = getWidth() / 2;
				
		g.setColor(0xffffff);
		g.fillRect(0, 0, getWidth(), getHeight());
		
		Image img = dice_img[roller.getDiceType()];
		if (img != null) {
			g.drawImage(img, centerx, getHeight() / 2,
				Graphics.HCENTER|Graphics.VCENTER);
		}

		g.setColor(0x000000);
		g.setFont(Font.getFont(
			Font.FACE_PROPORTIONAL,
			Font.STYLE_BOLD,
			Font.SIZE_LARGE));
		g.drawString(
			String.valueOf(roller.getNumDice())
			+ "d"
			+ String.valueOf(roller.getNumFaces()),
			centerx, 0,
			Graphics.TOP|Graphics.HCENTER);
		g.setFont(Font.getFont(
			Font.FACE_PROPORTIONAL,
			Font.STYLE_BOLD,
			Font.SIZE_SMALL));
		g.drawString(
			"Arrows select dice number/type",
			centerx, getHeight() - g.getFont().getHeight(),
			Graphics.BOTTOM|Graphics.HCENTER);
		g.drawString(
			"Action or digits roll dice",
			centerx, getHeight(),
			Graphics.BOTTOM|Graphics.HCENTER);

	}
	
	protected void keyPressed(int keyCode) {
		switch (keyCode) {
			case KEY_NUM1: roller.roll(1); return;
			case KEY_NUM2: roller.roll(2); return;
			case KEY_NUM3: roller.roll(3); return;
			case KEY_NUM4: roller.roll(4); return;
			case KEY_NUM5: roller.roll(5); return;
			case KEY_NUM6: roller.roll(6); return;
			case KEY_NUM7: roller.roll(7); return;
			case KEY_NUM8: roller.roll(8); return;
			case KEY_NUM9: roller.roll(9); return;
			case KEY_NUM0: roller.roll(10); return;
		}

		switch (getGameAction(keyCode)) {
			case UP: roller.moreDice(); repaint(); return;
			case DOWN: roller.fewerDice(); repaint(); return;
			case LEFT: roller.prevType(); repaint(); return;
			case RIGHT: roller.nextType(); repaint(); return;
			case FIRE: roller.roll(1); return;
		}
	}
}

