import java.applet.Applet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

public class Tetravex extends Applet implements Runnable,MouseListener,MouseMotionListener{
	private Dimension d;
	private Image offscreen;
	private Graphics grf;
	private MediaTracker mt;
	private Field field;
	private Color bgcolor;
	private Color mojicolor;
	private Color holecolor;
	private Color panerucolor;
	private Color linecolor;
	private Color gameclearcolor;
	private Font titleFont;
	private Font otherFont;
	private Image [] masu;
	private Image nextbutton;
	private Image startbutton;
	private Image restartbutton;
	private Image giveupbutton;
	private Image sankakubutton;
	private Image sankaku2button;
	private Thread thread;
	private Thread thread2;
	public boolean start;
	private boolean push;
	private boolean push2;
	private int total_time;
	private boolean paneru_push;
	private int mouse_x;
	private int mouse_y;
	private int retu;
	private int h_retu;
	private int stage_width;
	private String stage_mode;
	private String h_stage_mode;
	public Tetravex(){
		super();
		addMouseListener(this);
		addMouseMotionListener(this);
		start = false;
		push = false;
		push2 = false;
		paneru_push = false;
		retu = 2;
		h_retu = 2;
		stage_mode = "R";
		h_stage_mode = "R";
	}
	public void init(){
		d = getSize();
		offscreen = createImage(d.width,d.height);
		grf = offscreen.getGraphics();
		mt = new MediaTracker(this);

		if(stage_mode.equals("R")){
			stageReset();
		}else{
			if(field.gameClear()){
				stage_width++;
				total_time = total_time + field.getTime();
			}
		}
		stage_mode = h_stage_mode;
		if(stage_mode.equals("R")){
			retu = h_retu;
		}else{
			retu = stage_width;
		}
		field = new Field(this,retu);
		if(stage_mode.equals("F")){
			field.setTime(total_time);
		}
		masu = new Image[10];
		for(int i = 0;i < 10;i++){
			masu[i] = getImage(getCodeBase(),"masu_0"+i+".gif");
			mt.addImage(masu[i],0);
		}
		nextbutton = getImage(getCodeBase(),"nextbutton.png");
		mt.addImage(nextbutton,0);
		startbutton = getImage(getCodeBase(),"startbutton.png");
		mt.addImage(startbutton,0);
		restartbutton = getImage(getCodeBase(),"restartbutton.png");
		mt.addImage(restartbutton,0);
		giveupbutton = getImage(getCodeBase(),"giveupbutton.png");
		mt.addImage(giveupbutton,0);
		sankakubutton = getImage(getCodeBase(),"sankaku1.jpg");
		mt.addImage(sankakubutton,0);
		sankaku2button = getImage(getCodeBase(),"sankaku2.jpg");
		mt.addImage(sankaku2button,0);
		bgcolor = new Color(104,255,180);
		mojicolor = Color.black;
		linecolor = Color.black;
		holecolor = new Color(192,192,192);
		panerucolor = Color.white;
		gameclearcolor = Color.red;
		titleFont = new Font("Monospaced",Font.BOLD,24);
		otherFont = new Font("Monospaced",Font.BOLD,14);
	}
	public void paint(Graphics g){
		update(g);
	}
	public void update(Graphics g){
		if(!mt.checkID(0)){
			g.clearRect(0,0,d.width,d.height);
			g.setColor(Color.black);
			g.drawString("Please wait....",d.width / 4,d.height / 2);
			return;
		}
		grf.setColor(bgcolor);
		grf.fillRect(0,0,d.width,d.height);
		grf.setColor(mojicolor);
		grf.setFont(titleFont);
		grf.drawString("数字あわせゲーム",72,40);
		grf.setFont(otherFont);
		for(int i = 0;i < retu;i++){
			for(int j = 0;j < retu;j++){
				if(field.getP_hole(i,j).getField_Paneru() != null){
					grf.setColor(panerucolor);
					grf.fillRect(6+j*50,60+i*50,48,48);
					drawPanel(grf,field.getP_hole(i,j).getField_Paneru(),6+j*50,60+i*50);
				}else{
					grf.setColor(holecolor);
					grf.fillRect(6+j*50,60+i*50,48,48);
				}	
			}
		}
		for(int i = 0;i < 4;i++){
			for(int j = 0;j < 2;j++){
				if(field.getR_hole(i,j).getField_Paneru()!=null){
					grf.setColor(panerucolor);
					grf.fillRect(228+j*50,60+i*50,48,48);
					drawPanel(grf,field.getR_hole(i,j).getField_Paneru(),228+j*50,60+i*50);
				}else{
					grf.setColor(holecolor);
					grf.fillRect(228+j*50,60+i*50,48,48);
				}
			}
		}
		for(int i = 0;i < 2;i++){
			for(int j = 0;j < 4;j++){
				if(field.getU_hole(i,j).getField_Paneru()!= null){
					grf.setColor(panerucolor);
					grf.fillRect(6+j*50,282+i*50,48,48);
					drawPanel(grf,field.getU_hole(i,j).getField_Paneru(),6+j*50,282+i*50);
				}else{
					grf.setColor(holecolor);
					grf.fillRect(6+j*50,282+i*50,48,48);
				}
			}
		}
		if(paneru_push){
			Field_Paneru f_p = field.getMove_Field_Paneru().getf_p();
			grf.setColor(panerucolor);
			int x = f_p.getIndex_x();
			int y = f_p.getIndex_y();
			grf.fillRect(x,y,48,48);
			drawPanel(grf,f_p,x,y);
		}
		grf.setColor(mojicolor);
		double time = (double)(field.getTime());
		time = time / 100;
		if(!field.gameOver(stage_mode)){
			grf.drawString("Time:"+time,228,378);
		}
		grf.drawString("Stage Mode",6,410);
		if(push2){
			grf.drawImage(sankakubutton,96,394,this);
		}else{
			grf.drawImage(sankaku2button,96,394,this);
		}
		grf.drawString(h_stage_mode,116,410);
		if(h_stage_mode.equals("R")){
			grf.drawString("盤面",130,410);
			if(push){
				grf.drawImage(sankakubutton,170,394,this);
			}else{
				grf.drawImage(sankaku2button,170,394,this);
			}
			grf.drawString(""+h_retu+"×"+h_retu,191,410);
		}

		if(!start){
			grf.drawImage(startbutton,245,387,this);
		}else{
			if(stage_mode.equals("F")){
				grf.drawImage(giveupbutton,245,387,this);
			}else{
				grf.drawImage(restartbutton,245,387,this);
			}
		}
		
		grf.setFont(titleFont);
		grf.setColor(gameclearcolor);
		if(field.gameClear()){
			if(stage_mode.equals("R")){
				grf.drawString("GAMECLEAR!",80,180);
				grf.drawString("得点:" + field.getTokuten(retu),80,220);
				grf.drawString("ランク:"+field.getRank(retu),80,260);

			}else{
				double t_time = (double)(total_time);
				t_time = t_time / 100;
				t_time = time - t_time;
				grf.drawString("This stage time:"+t_time,30,230);
				if(stage_width == 4){
					grf.drawString("ALLSTAGECLEAR!",70,180);
					t_time = t_time * 100 + (double)(total_time);
					t_time = t_time / 100;
					int h_time = (int)(t_time);
					grf.drawString("Total      time:"+t_time,30,280);
					field.setTime(h_time);
					grf.drawString("得点:" + field.getTokuten(5),80,220);
					grf.drawString("ランク:"+field.getRank(5),80,260);
				}else{
					grf.drawString("GO NEXT STAGE!",70,180);
					grf.drawImage(nextbutton,245,387,this);
				}
			}
		}
		if(field.gameOver(stage_mode)){
			grf.drawString("GAMEOVER!",85,180);
			grf.drawString("得点:" + 0,80,220);
			grf.drawString("ランク:"+"F",80,260);
		}
		g.drawImage(offscreen,0,0,this);
	}
	public void drawPanel(Graphics grf2,Field_Paneru f_hole,int x,int y){
		int up = f_hole.getPaneru().getUp();
		int down = f_hole.getPaneru().getDown();
		int left = f_hole.getPaneru().getLeft();
		int right = f_hole.getPaneru().getRight();
		grf2.setColor(linecolor);
		grf2.drawImage(masu[up],x+16,y,this);
		grf2.drawImage(masu[down],x+16,y+32,this);
		grf2.drawImage(masu[left],x,y+16,this);
		grf2.drawImage(masu[right],x+32,y+16,this);
		grf2.drawLine(x,y,x+47,y+47);
		grf2.drawLine(x,y+47,x+47,y);
	}
	public void paneru_push_syori(Field_Hole f_h,int ix,int iy){
		paneru_push = true;
		f_h.setField_Paneru(null);
		mouse_x = ix;
		mouse_y = iy;
		repaint();
	}
	public void setMouse_x(int mouse_x){
		this.mouse_x = mouse_x;
	}
	public void setMouse_y(int mouse_y){
		this.mouse_y = mouse_y;
	}
	public void start(){
		if(thread == null){
			thread = new Thread(this);
			thread.start();
		}
	}
	public void timerThreadStop(){
		if(thread2 != null){
			thread2.stop();
			thread2 = null;
		}
	}
	public void stop(){
		if(thread != null){
			thread.stop();
			thread = null;
		}
	}
	public void run(){
		try{
			mt.waitForID(0);
		}catch(InterruptedException e){
			return;
		}
		repaint();
	}
	public void timeThreadStart(){
		TimerCount tc = new TimerCount(this,field,stage_mode);
		thread2 = new Thread(tc);
		thread2.start();
	}
	public void stageReset(){
		stage_width = 2;
		total_time = 0;
	}
	public void mouseClicked(MouseEvent arg0) {
		int ix = arg0.getX();
		int iy = arg0.getY();
		if(ix >= 245 && ix < 315 && iy >= 387 && iy < 417){
			if(start && stage_mode.equals("F")){
				field.setTime(720000);
				start = false;
				stageReset();
			}else{
				start = true;
				init();
				timeThreadStart();
				repaint();
			}
		}
		repaint();
	}
	public void mousePressed(MouseEvent arg0) {
		int ix = arg0.getX();
		int iy = arg0.getY();
		if(ix >= 170 && ix < 186 && iy >= 394 && iy < 410){
			if(h_stage_mode.equals("R")){
				push = true;
				repaint();
			}
		}
		if(ix >= 96 && ix < 112 && iy >= 394 && iy < 410){
				push2 = true;
				repaint();
		}
		if(start){
			for(int i = 0;i < retu;i++){
				for(int j = 0;j < retu;j++){
					if(ix >= 6+j*50 && ix < 54+j*50 && iy >= 60+i*50 && iy < 108+i*50){
						Field_Paneru f_p = field.getP_hole(i,j).getField_Paneru();
						if(f_p !=null){
							field.setMove_Field_Paneru(new Move_Field_Paneru(field,f_p,i*retu+j));
							paneru_push_syori(field.getP_hole(i,j),ix,iy);
						}
					}
				}
			}
			for(int i = 0;i < 4;i++){
				for(int j = 0;j < 2;j++){
					if(ix >= 228 + j*50 && ix < 276+j*50 && iy >= 60+i*50 && iy < 108+i*50){
						Field_Paneru f_p = field.getR_hole(i,j).getField_Paneru();
						if(f_p!=null){
							field.setMove_Field_Paneru(new Move_Field_Paneru(field,f_p,i*2+j+retu*retu));
							paneru_push_syori(field.getR_hole(i,j),ix,iy);
						}
					}
				}
			}
			for(int i = 0;i < 2;i++){
				for(int j = 0;j < 4;j++){
					if(ix >= 6+j*50 && ix < 54+j*50 && iy >= 282+i*50 && iy < 330+i*50){
						Field_Paneru f_p = field.getU_hole(i,j).getField_Paneru();
						if(field.getU_hole(i,j).getField_Paneru()!=null){
							field.setMove_Field_Paneru(new Move_Field_Paneru(field,f_p,i*4+j+8+retu*retu));
							paneru_push_syori(field.getU_hole(i,j),ix,iy);
						}
					}
				}
			}
		}
	}
	public void mouseReleased(MouseEvent arg0) {
		int ix = arg0.getX();
		int iy = arg0.getY();
		if(push){
			push = false;
			if(ix >= 170 && ix < 186 && iy >= 394 && iy < 410){
				if(h_retu == 4){
					h_retu = 2;
				}else{
					h_retu = h_retu + 1;
				}
			}
		}
		if(push2){
			push2 = false;
			if(ix >= 96 && ix < 112 && iy >= 394 && iy < 410){
				if(h_stage_mode.equals("F")){
					h_stage_mode = "R";				
				}else{
					h_stage_mode = "F";
				}
			}
		}
		if(start){
			if(paneru_push){
				boolean flg = false;
				for(int i = 0;i < retu;i++){
					for(int j = 0;j < retu;j++){
						if(ix >= 6+j*50 && ix < 54+j*50 && iy >= 60+i*50 && iy < 108+i*50){
							flg = true;
							if(!field.existCheck(i,j,"P")){
								if(field.upCheck(i,j)&&field.downCheck(i,j)&&field.leftCheck(i,j)&&field.rightCheck(i,j)){
									Field_Paneru f_p = field.getMove_Field_Paneru().getf_p();
									f_p.setIndex_x(6+j*50);
									f_p.setIndex_y(60+i*50);
									field.getP_hole(i,j).setField_Paneru(f_p);
								}else{
									field.set_reverse();
								}
							}else{
								field.set_reverse();
							}
						}
					}
				}
				for(int i = 0;i < 4;i++){
					for(int j = 0;j < 2;j++){
						if(ix >= 228 + j*50 && ix < 276+j*50 && iy >= 60+i*50 && iy < 108+i*50){
							flg = true;
							if(!field.existCheck(i,j,"R")){
								Field_Paneru f_p = field.getMove_Field_Paneru().getf_p();
								f_p.setIndex_x(228+j*50);
								f_p.setIndex_y(60+i*50);
								field.getR_hole(i,j).setField_Paneru(f_p);
							}else{
								field.set_reverse();
							}
						}
					}
				}
				for(int i = 0;i < 2;i++){
					for(int j = 0;j < 4;j++){
						if(ix >= 6+j*50 && ix < 54+j*50 && iy >= 282+i*50 && iy < 330+i*50){
							flg = true;
							if(!field.existCheck(i,j,"U")){
								Field_Paneru f_p = field.getMove_Field_Paneru().getf_p();
								f_p.setIndex_x(6+j*50);
								f_p.setIndex_y(282+i*50);
								field.getU_hole(i,j).setField_Paneru(f_p);
							}else{
								field.set_reverse();
							}
						}
					}
				}
				if(!flg){
					field.set_reverse();
				}
				paneru_push = false;
			}
		}
		repaint();
	}
	public void mouseEntered(MouseEvent arg0) {
	}
	public void mouseExited(MouseEvent arg0) {
	}
	public void mouseDragged(MouseEvent arg0) {
		int ix = arg0.getX();
		int iy = arg0.getY();
		if(start){
			if(paneru_push){
				field.moveIndex(ix,iy,mouse_x,mouse_y);
				repaint();
			}
		}
	}
	public void mouseMoved(MouseEvent arg0) {
	}
}
