import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import java.beans.*;
import java.io.*;
import java.net.URL;
import java.util.*;

import javax.swing.text.*;
import javax.swing.undo.*;
import javax.swing.event.*;
import java.applet.*;

class tacticsApp extends Applet implements MouseListener, MouseMotionListener,
 KeyListener, FocusListener, Runnable  {

	Thread viewerThread = null;
	MediaTracker mediaTracker;
	int MTID;

	int gameSpeed = 5000;

	Image	 offscreen;
	Graphics offGraphics;

	int Square_sizeX = 32;
	int Square_sizeY = 32;

	int maxGage = 100;
	boolean showHP = false;

	int updateX_lefttop = 0, updateY_lefttop = 0, updateX_rightbottm = 0, updateY_rightbottm = 0;

	int ctrNationality = 0;	// どの勢力を操作するか。
	boolean ctrWalking = true; //true == go, false == stop;
	int ctrDirection = 0;
	int ctrX = 0, ctrY = 0;
	static Image ctrImg[] = new Image[4];	// 兵士コントロール用カーソル画像。
	static Image ctrStopImg[] = new Image[4];	// 兵士コントロール用カーソル画像。兵士を止めるとき。

	board gameBoard;	// この盤上に兵士などのユニットが配置される。
	int board_sizeX = 16, board_sizeY = 16;	// ゲームボードの縦横の大きさ。

	public void init() {

		mediaTracker = new MediaTracker(this);
		MTID = 0;

		// カーソル画像の読み込み。
		ctrImg[0] = getImage(getCodeBase(), "up.gif");
		mediaTracker.addImage(ctrImg[0], MTID);
		ctrImg[1] = getImage(getCodeBase(), "right.gif");
		mediaTracker.addImage(ctrImg[1], MTID);
		ctrImg[2] = getImage(getCodeBase(), "down.gif");
		mediaTracker.addImage(ctrImg[2], MTID);
		ctrImg[3] = getImage(getCodeBase(), "left.gif");
		mediaTracker.addImage(ctrImg[3], MTID);

		// カーソルストップ画像の読み込み。
		ctrStopImg[0] = getImage(getCodeBase(), "stop_up.gif");
		mediaTracker.addImage(ctrStopImg[0], MTID);
		ctrStopImg[1] = getImage(getCodeBase(), "stop_right.gif");
		mediaTracker.addImage(ctrStopImg[1], MTID);
		ctrStopImg[2] = getImage(getCodeBase(), "stop_down.gif");
		mediaTracker.addImage(ctrStopImg[2], MTID);
		ctrStopImg[3] = getImage(getCodeBase(), "stop_left.gif");
		mediaTracker.addImage(ctrStopImg[3], MTID);

		try
		{
			//イメージの強制ロードを要求
			mediaTracker.waitForID(MTID);
		}
		catch (InterruptedException e)
		{
			return;
		}

		addMouseListener(this);
		addMouseMotionListener(this);
		addKeyListener(this);
		addFocusListener( this );

		// オフスクリーンの作成。
		offscreen = createImage(board_sizeX*Square_sizeX, board_sizeY*Square_sizeY);
		offGraphics  = offscreen.getGraphics();

		// ゲームボードの作成。
		gameBoard = new board(board_sizeX,board_sizeY);
		unit.setGameBoard(gameBoard);
		unit.setViewer(this);
		unit.setUGE( new UnitGraphicsEngineApp(this, mediaTracker) );

	        requestFocus();  // キーボードフォーカスを要求

		// ゲームボードへの兵士ユニットの配置。
		int nationarity;
		int direction;
		boolean auto;

		king blueKing = new king(7,15, 0, 0, null, false);
		king redKing = new king(8,0, 2, 1, blueKing, true);
		blueKing.setTarget(redKing);

		gameBoard.setUnit(7,15, blueKing);
		gameBoard.setUnit(8,0, redKing);

		// 勢力「1」の兵士を作成し、盤の(0-max,0)座標に配置。
		nationarity = 1;
		direction = 2; 	// 下を向く
		auto = true;

		gameBoard.setUnit(0,3, new cavalry(0,3, direction, nationarity, blueKing, auto) );
		gameBoard.setUnit(1,3, new cavalry(1,3, direction, nationarity, blueKing, auto) );
		gameBoard.setUnit(2,3, new cavalry(2,3, direction, nationarity, blueKing, auto) );
		gameBoard.setUnit(13,3, new cavalry(13,3, direction, nationarity, blueKing, auto) );
		gameBoard.setUnit(14,3, new cavalry(14,3, direction, nationarity, blueKing, auto) );
		gameBoard.setUnit(15,3, new cavalry(15,3, direction, nationarity, blueKing, auto) );
		for (int x=0, y=2; x<16; x++) {
			gameBoard.setUnit(x,y, new soldier(x,y, direction, nationarity, blueKing, auto) );
		}
		for (int x=4, y=1; x<12; x++) {
			gameBoard.setUnit(x,y, new archer(x,y, direction, nationarity, blueKing, auto) );
		}

		// 勢力「0」の兵士を作成し、盤の(15,y-max)座標に配置。
		nationarity = 0;
		direction = 0; 	// 上を向く
		auto = false;

		gameBoard.setUnit(0,12, new cavalry(0,12, direction, nationarity, redKing, auto) );
		gameBoard.setUnit(1,12, new cavalry(1,12, direction, nationarity, redKing, auto) );
		gameBoard.setUnit(2,12, new cavalry(2,12, direction, nationarity, redKing, auto) );
		gameBoard.setUnit(13,12, new cavalry(13,12, direction, nationarity, redKing, auto) );
		gameBoard.setUnit(14,12, new cavalry(14,12, direction, nationarity, redKing, auto) );
		gameBoard.setUnit(15,12, new cavalry(15,12, direction, nationarity, redKing, auto) );
		for (int x=0, y=13; x<16; x++) {
			gameBoard.setUnit(x,y, new soldier(x,y, direction, nationarity, redKing, auto) );
		}
		for (int x=4, y=14; x<12; x++) {
			gameBoard.setUnit(x,y, new archer(x,y, direction, nationarity, redKing, auto) );
		}

	}
	public void start() {
		if (viewerThread == null) {
			viewerThread = new Thread(this);
			viewerThread.start();
		}
	}
	public void run() {
		while (gameBoard != null) {

			// ゲーム速度に応じてウエイトをおく。
			try
			{
				viewerThread.sleep(gameBoard.getSpeed()/32);
									}
			catch (InterruptedException e)
			{
			}
			repaint();	//

		}
	}

		
	public void paint(Graphics g) {

		int size_x = gameBoard.getSizeX();
		int size_y = gameBoard.getSizeY();

		for (int y=0; y<size_y; y++)
		 for (int x=0; x<size_x; x++) {

			soldier sol = (soldier)gameBoard.getUnit(x,y);
			if (null != sol) {
				g.setColor( Color.white );
				g.fillRect( x*Square_sizeX,y*Square_sizeY, Square_sizeX,Square_sizeY);
				sol.show(g, x*Square_sizeX,y*Square_sizeY, (Component)this);

				if (showHP) {
					int gageHP = calcGage(sol.HP, sol.getMaxHP());

//					AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f );
//					( (Graphics2D)g ).setComposite( ac );
					g.setColor( Color.blue );
					g.fillRect( x*Square_sizeX,y*Square_sizeY+24, gageHP,4 );
				}
			}
			else {
				g.setColor( Color.white );
				g.fillRect( x*Square_sizeX,y*Square_sizeY, Square_sizeX,Square_sizeY);
			}

			if (ctrWalking)
				g.drawImage( ctrImg[ctrDirection], ctrX*Square_sizeX, ctrY*Square_sizeY, this);
			else
				g.drawImage( ctrStopImg[ctrDirection], ctrX*Square_sizeX, ctrY*Square_sizeY, this);
		}
	}

	public void update(Graphics g) {
		if (offscreen != null) {

			paint(offGraphics);
			g.drawImage(offscreen, 0,0, this);
		}
		else {
			paint(g);
		}
	}


	public void destroy() {
		unit.setGameBoard(null);

		for (int x = 0; x < board_sizeX; x++)
		 for (int y = 0; y < board_sizeY; y++)
			gameBoard.removeUnit(x, y);

		gameBoard.setSpeed(0);

		removeMouseListener(this);
		removeMouseMotionListener(this);
		removeKeyListener(this);
		removeFocusListener( this );

	}
	public int calcGage(int src, int max) {
		int retGage = src / (max / Square_sizeX);

		if ( 0 >= retGage && 0 < src)
			retGage = 1;
		if ( Square_sizeX < retGage)
			retGage = Square_sizeX;			
		return retGage;
	}

	public void mouseDragged(MouseEvent e) {
	}
	public void mouseMoved(MouseEvent e) {
		ctrX = e.getX()/Square_sizeX;
		ctrY = e.getY()/Square_sizeY;
		repaint();
	}

	public void mouseReleased(MouseEvent e) {
	}
	public void mousePressed(MouseEvent e) {
	}
	public void mouseClicked(MouseEvent e) {
		// マウスポインタの変更。
		ctrX = e.getX()/Square_sizeX;
		ctrY = e.getY()/Square_sizeY;

		soldier sol = (soldier)gameBoard.getUnit(ctrX, ctrY);

		if (null != sol)
			if (ctrNationality == sol.getNationality()) {
			 // 兵士の向きを変更。
				sol.setDirection( ctrDirection );
				sol.setWalking(ctrWalking);
			}

		repaint();
	}

	public void mouseEntered(MouseEvent e) {
	}
	public void mouseExited(MouseEvent e) {
	}

	public void keyTyped(KeyEvent e) {
	}
	public void keyPressed(KeyEvent e) {
		if (e.getKeyCode() == e.VK_SPACE) {
			showHP = !showHP;
			repaint();
		}

		if (e.getKeyCode() == e.VK_UP) {
			ctrDirection = 0;
			repaint();
		}
		if (e.getKeyCode() == e.VK_RIGHT) {
			ctrDirection = 1;
			repaint();
		}
		if (e.getKeyCode() == e.VK_DOWN) {
			ctrDirection = 2;
			repaint();
		}
		if (e.getKeyCode() == e.VK_LEFT) {
			ctrDirection = 3;
			repaint();
		}

		if (e.getKeyCode() == e.VK_SHIFT) {
			ctrWalking = !ctrWalking;
			repaint();
		}

		if (e.getKeyCode() == e.VK_ENTER) {
			if (0 == gameBoard.getSpeed())
				gameBoard.setSpeed(gameSpeed);	// ゲーム速度を設定しゲームをスタート。
			else
				gameBoard.setSpeed(0);	// ゲーム速度を0にしゲームを中断。
		}
	}
	public void keyReleased(KeyEvent e) {
	}

	public void focusGained( FocusEvent evt ) {
	}
	public void focusLost( FocusEvent evt ) {
	}

}


