 /**
  *  Level contains the Level load and paint for the Epsilon game.
  *  Epsilon is a simple space-shooter-vertical-scroller game.
  *
  *  Epsilon is available for non-commercial use only!
  *  You can learn from this sources and you can modify them
  *  for learning purposes.
  * 
  *  @author      Ziga Hajdukovic
  *  @version     1.0
  *
  */

import java.io.*;

import javax.microedition.lcdui.Graphics;

class Level
{

	public static final byte MAX_LEVELS = 1;

	public static final byte LEVEL_WIDTH = 16;
	public static final byte LEVEL_HEIGHT = 64;
	
	public static final byte TILE_SIZE = 16;
	public static final byte TILES_PER_IMAGE_LINE = 5;

	// space background position and scroll speed
	public static int space_scroll_y;
	public static int space_scroll_vy = -1;

	// tiled background position and scroll speed
	public static int tiles_scroll_y;
	public static int tiles_scroll_vy = -2;
	public static int tiles_scroll_x;

	public static byte levelno;

	public static byte[] tileMap;

	//  a translation table for level tile text representation
	//  to tile index in the tile image 
	public static char[] tileTextToImageIndex = 
	{
		'J', 'L','^','<','>',
		'\\','/','v','O','G',
	};
	
	public static final byte SPRITE_ID_PLAYER = 0;	// 'P'
	public static final byte SPRITE_ID_ENEMY1 = 1;	// 'A'
	public static final byte SPRITE_ID_ENEMY2 = 2;	// 'V'
	public static final byte SPRITE_ID_ENEMY3 = 3;	// 'O'
	public static final byte SPRITE_ID_BOSS1 = 4;	// 'B'
//	public static final byte SPRITE_ID_EXPLOSION = 5;
//	public static final byte SPRITE_ID_FIRE1 = 6;
//	public static final byte SPRITE_ID_FIRE2 = 7;
//	public static final byte SPRITE_ID_FIRE3 = 8;

	//  a translation table for level sprite text representation
	//  to sprite id
	public static char[] spriteTextToSpriteId = 
	{
		'P','A','V','O','B',
	};

	public static byte getTileIndex(char t)
	{
		byte idx = 0;
		// find tile index
		while ( idx < tileTextToImageIndex.length && tileTextToImageIndex[idx] != t )
			idx++;
		
		// handle unexisting or empty tiles
		if (idx > tileTextToImageIndex.length)
			idx = -1;
		
		return idx;
	}
	
	public static byte getSpriteId(char t)
	{
		byte idx = 0;
		// find sprite id
		while ( idx < spriteTextToSpriteId.length && spriteTextToSpriteId[idx] != t )
			idx++;
		
		// handle unexisting sprites
		if (idx > spriteTextToSpriteId.length)
			idx = -1;
		
		return idx;
	}

	public static void loadLevel(byte level_no)
	{
		levelno = level_no;

		// intialize the scrolling background
		space_scroll_y = 0;
		space_scroll_vy = 1;

		InputStream inputstream = null;
		DataInputStream datainputstream = null;
	
		tileMap = new byte[LEVEL_HEIGHT * LEVEL_WIDTH];
		int map_row = 0;
		int tile_map_col = 0;
		int sprite_map_col = 0;
		try
		{
			inputstream = new Object().getClass().getResourceAsStream( "/stage"+ level_no +".txt" );
			datainputstream = new DataInputStream(inputstream);
	
			char ch;
            boolean eof = false;
            while(!eof)
            {
            	// read level text file lines
            	try
            	{
        			// load a row of tiles
            		tile_map_col = 0;
            		ch = ' ';
            		while (ch != ';')
            		{
            			ch = (char) datainputstream.readByte();
            			System.out.print(ch);
            			
            			if (ch != ';')
            			{
                			tileMap[ map_row * LEVEL_WIDTH + tile_map_col ] = getTileIndex(ch);

                			tile_map_col++;
            			}
            			else
            			{
            				break;
            			}
            		}
            		// load a row of sprites
            		sprite_map_col = 0;
            		ch = ' ';
            		while (ch != ';')
            		{
            			ch = (char) datainputstream.readByte();
            			System.out.print(ch);
            			
            			if (ch != ';')
            			{
            				switch (getSpriteId(ch)) {
							case SPRITE_ID_PLAYER:

								// initialize player sprite
								GameCanvas.player = new GameSprite(
										GameCanvas.SPRITE_IMAGE_PLAYER,
										GameCanvas.MAX_ENERGY_PLAYER);
								GameCanvas.player.x = GameCanvas.canvasWidth / 2 - GameCanvas.player.w/2;
								GameCanvas.player.y = GameCanvas.canvasHeight - GameCanvas.player.h - GameCanvas.player.h/2;
								GameCanvas.player.frameId = GameCanvas.SPRITE_FRAME_PLAYER_CENTER;

								break;
							case SPRITE_ID_ENEMY1:
								break;
							case SPRITE_ID_ENEMY2:
								break;
							case SPRITE_ID_ENEMY3:
								break;
							case SPRITE_ID_BOSS1:
								break;
							}
            				
                    		sprite_map_col++;
            			}
            			else
            			{
            			
                			System.out.println();

                			// read 0x0D and 0x0A  (CR, LF)
                			ch = (char) datainputstream.readByte();
                			ch = (char) datainputstream.readByte();

            				break;
            			}
            		}

            		// go to next line of text
            		map_row++;
            	}
            	catch (EOFException eofex)
            	{
            		eof = true;
            	}
            }
			inputstream.close();
			inputstream = null;
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
		}
	}

	public static void paintTiles(Graphics g)
	{
		// clip window coordinates
		int cx, cy, cw, ch;
		// image draw coordinates
		int dx, dy;
		
		int x;
		int y = 0;

		while (y <= GameCanvas.canvasHeight)
		{
			x = 0;
			while (x <= GameCanvas.canvasWidth)
			{
				// get the tileMap index of the tile, located at tx, ty
				int tx = tiles_scroll_x + x;
				int ty = tiles_scroll_y + y;
				int tile_idx = ty / TILE_SIZE * LEVEL_WIDTH + tx / TILE_SIZE;

				// get tile index in image from tileMap
				byte tile_image_idx = tileMap[tile_idx];
				
				if ( tile_image_idx >= 0)
				{
					// get tile level coordinates from tile index
					int tile_idx_x = (tile_idx % LEVEL_WIDTH) * TILE_SIZE;
					int tile_idx_y = (tile_idx / LEVEL_WIDTH) * TILE_SIZE;

					// translate to screen coordinates
					tile_idx_x -= tiles_scroll_x;
					tile_idx_y -= tiles_scroll_y;
					
					int tile_col = tile_image_idx % TILES_PER_IMAGE_LINE;
					int tile_row = tile_image_idx / TILES_PER_IMAGE_LINE;
					
					cx = tile_idx_x;
					cy = tile_idx_y;
					cw = TILE_SIZE;
					ch = TILE_SIZE;

					//  check clip window coordinates, if out of screen
					if (cx < 0)
					{
						cw += cx;
						cx = 0;
					}
					if (cy < 0)
					{
						ch += cy;
						cy = 0;
					}

					//  check clip window size, if out of screen
					if (cx + cw > GameCanvas.canvasWidth)
						cw -= (cx + cw) - GameCanvas.canvasWidth; 
					if (cy + ch > GameCanvas.canvasHeight)
						ch -= (cy + ch) - GameCanvas.canvasHeight; 
					
					dx = tile_idx_x - tile_col * TILE_SIZE;
					dy = tile_idx_y - tile_row * TILE_SIZE;
					
					g.setClip(cx, cy, cw, ch);
					g.drawImage(GameCanvas.tileImage, dx, dy, Graphics.TOP | Graphics.LEFT);
				}

				x += TILE_SIZE;
			}
		
			y += TILE_SIZE;
		}
		g.setClip(0, 0, GameCanvas.canvasWidth, GameCanvas.canvasHeight);
	}

	public static void paintSpaceBackground(Graphics g)
	{
		// fill the vast space
		g.setColor(0x000000);
		g.fillRect(0, 0, GameCanvas.canvasWidth, GameCanvas.canvasHeight);
		
		// init scrolling background image tiling
		int x = 0;
		int y = space_scroll_y % GameCanvas.imgBackground.getHeight() - GameCanvas.imgBackground.getHeight();

		// image is wide enough, so we only need to tile it in the vertical (y) direction
		while (y < GameCanvas.canvasHeight)
		{
			g.drawImage(GameCanvas.imgBackground, x, y, Graphics.TOP | Graphics.LEFT);
		
			y += GameCanvas.imgBackground.getHeight();
		}
	}

}

