package personnage;

import java.util.ArrayList;

import main.Jeu;

import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Point;
import org.newdawn.slick.geom.Rectangle;

import world.SaveAndLoadMap;

public class Zombie
{
	public int x, y;
	int vy = 0;
	int speed, jump;
	ArrayList <Rectangle> boxs;
	boolean jumping = false;
	int vie = 20;
	int direction = (int) (Math.random()*2)%2;
	Path path;
	int[][] map;
	boolean noPath = false;
	int counterPath = 30;
	int forcedJump = 5;
	ArrayList<Image> spritegauche;
	ArrayList<Image> spritedroite;
	int counterRight = 0, counterLeft = 0;
	int right = 0, left = 0;
	public Zombie() throws SlickException
	{
		boxs = new ArrayList<Rectangle>();
		spritegauche = new ArrayList<Image>();
		spritedroite = new ArrayList<Image>();
		
		boxs = SaveAndLoadMap.getBoxs();
		do
		{
			this.x = (int) (Math.random()*700);
			this.y = (int) (Math.random()*600);
		}while(intersect() || Math.abs(Jeu.zomb.getPerso().x + 10 - x) <= 100 && Math.abs(Jeu.zomb.getPerso().y + 15 - y) <= 100);
		
		map = SaveAndLoadMap.map.clone();
		
		speed = 2;
		jump = -12;
		
		spritegauche.add(new Image("res/Personnages/Zombie/gauche1.png"));
		spritegauche.add(new Image("res/Personnages/Zombie/gauche2.png"));
		spritegauche.add(new Image("res/Personnages/Zombie/gauche3.png"));
		
		spritedroite.add(new Image("res/Personnages/Zombie/droite1.png"));
		spritedroite.add(new Image("res/Personnages/Zombie/droite2.png"));
		spritedroite.add(new Image("res/Personnages/Zombie/droite3.png"));
	}
	public Zombie(int x, int y) throws SlickException
	{
		boxs = new ArrayList<Rectangle>();
		boxs = SaveAndLoadMap.getBoxs();
		spritegauche = new ArrayList<Image>();
		spritedroite = new ArrayList<Image>();
		this.x = x;
		this.y = y;
		map = SaveAndLoadMap.map.clone();
		speed = 3;
		jump = -12;
		spritegauche.add(new Image("res/Personnages/Zombie/gauche1.png"));
		spritegauche.add(new Image("res/Personnages/Zombie/gauche2.png"));
		spritegauche.add(new Image("res/Personnages/Zombie/gauche3.png"));
		
		spritedroite.add(new Image("res/Personnages/Zombie/droite1.png"));
		spritedroite.add(new Image("res/Personnages/Zombie/droite2.png"));
		spritedroite.add(new Image("res/Personnages/Zombie/droite3.png"));
		
	}
	public boolean isBlocked(int x, int y)
	{
		return !(isEmpty(x, y));
	}
	public boolean isEmpty(int x, int y)
	{
		return map[y][x] == 0;
	}
	public void initPathFinding()
	{
		Personnage enemy = Jeu.zomb.getPerso();
		int zombiex =  Math.min(24, Math.max(0, (x+10)/32));
		int zombiey =  Math.min(19, Math.max(0, (y+10)/32));
		int enemyx = Math.min(24, Math.max(0, (enemy.x+10)/32));
		int enemyy =  Math.min(19, Math.max(0, (enemy.y+10)/32));
		ArrayList<Point> totreat = new ArrayList<Point>();
		ArrayList<Point> treating = new ArrayList<Point>();
		treating.add(new Point(enemyx, enemyy));
		int init = 200;
		int i = init;
		for(int u = 0 ; u < 20 ; u++)
			for(int v = 0 ; v < 25 ; v++)
				if(map[u][v] >= 5)
					map[u][v] = 0;

		map[enemyy][enemyx] = init;
		//PSEUDO CODE
		// ON REMPLIE DE PERSO A ZOMBIE JUSQU'A ARRIVER A LA CASE ZOMBIE
		// ON TRACE LE CHEMIN DANS L'AUTRE SENS DEPUIS ZOMBIE

		for(int u = 19 ; u > 3 ; u--)
			for(int v = 0 ; v < 25 ; v++)
				if(isEmpty(v,u) && isEmpty(v, u-1) && isEmpty(v, u-2) && isEmpty(v, u-3))
					map[u-3][v] = 1;
		int boucleinfini = 200;
		while(isEmpty(zombiex, zombiey))
		{
			if(boucleinfini-- <= 0)
			{
				noPath = true;
				break;
			}
			totreat.clear();
			for(Point p : treating)
			{
				int x = (int) p.getX();
				int y = (int) p.getY();
				if(isEmpty(Math.max(0, x-1), y))
				{
					totreat.add(new Point(Math.max(0, x-1), y));
					map[y][x-1] = i-1;
				}
				if(isEmpty(Math.min(24, x+1), y))
				{
					totreat.add(new Point(Math.min(24, x+1), y));
					map[y][x+1] = i-1;
				}
				if(isEmpty(x, Math.max(0, y-1)))
				{
					totreat.add(new Point(x, Math.max(0, y-1)));
					map[y-1][x] = i-1;
				}
				if(isEmpty(x, Math.min(19, y+1)))
				{
					totreat.add(new Point(x, Math.min(19, y+1)));
					map[y+1][x] = i-1;
				}
			}
			treating.clear();
			for(Point p : totreat)
			{
				treating.add(p);
			}
			i--;
		}
		path = new Path(zombiex, zombiey);
		int nb = map[zombiey][zombiex];
		boucleinfini = 200;
		while(nb != init && !noPath)
		{
			if(boucleinfini-- <= 0)
			{
				noPath = true;
				break;
			}
			int x = (int) path.endPoint().getX();
			int y = (int) path.endPoint().getY();
			nb = map[y][x];
			if(map[y][Math.min(24, x+1)] == nb+1)
			{
				path.addPoint(Math.min(24, x+1), y);
				continue;
			}
			if(map[y][Math.max(0,x-1)] == nb+1)
			{
				path.addPoint(Math.max(0,x-1), y);
				continue;
			} 
			if(map[Math.max(0, y-1)][x] == nb+1)
			{
				path.addPoint(x, Math.max(0, y-1));
				continue;
			}
			if(map[Math.min(19, y+1)][x] == nb+1)
			{
				path.addPoint(x, Math.min(19, y+1));
				continue;
			}
//			else
//			{
//				System.out.println(nb);
//				for(int u = 0 ; u < 20 ; System.out.println(""), u++)
//					for(int v = 0 ; v < 25 ; System.out.print(map[u][v] + ((map[u][v]>=100) ? " " : "   ")), v++);
//				break;
//			}
		}
	}
	private boolean intersect()
	{
		Rectangle rect = new Rectangle(x+6,y+3,16,29);
		for(int i = 0; i < boxs.size();i++)
			if(boxs.get(i).intersects(rect))
				return true;
		return false;
	}
	public void draw(Graphics g)
	{
		if(direction == 1)
		{
			g.drawImage(spritedroite.get(right), x, y+2);
		}
		else
		{
			g.drawImage(spritegauche.get(left), x, y+2);
	 	}
		if(Jeu.debug)
		{
			path.draw(g);
			Rectangle rect = new Rectangle(x+3,y+3,19,29);
			g.draw(rect);
		}
	}
	
	public void iAConne()
	{
		if(Jeu.zomb.getPerso().x < x-2)
			move(0);
		if(Jeu.zomb.getPerso().x > x+2)
			move(1);
		if(Jeu.zomb.getPerso().y < y)
		{
			jump();
		}
	}
	public void iAIntelligente()
	{
		Point toGoTo = null;
		
		try
		{
			toGoTo = path.getPath().get(1);
		}
		catch(Exception e)
		{
			this.noPath = true;
			return;
		}
		if(toGoTo.getY()*32 < y)
		{
			jump();
		}
		if(toGoTo.getX()*32 + 5 > x)
		{
			move(1);
		}
		if(toGoTo.getX()*32 + 5 < x)
		{
			move(0);
		}
	}
	public void update()
	{

		y += vy++;
		if(intersect())
		{
			if(vy > 0)
			{
				y = (y/32)*32 - 1;
				jumping = false;
			}
			if(vy < 0)
				y = (y/32 + 1)*32 - 1;
			vy = 0;
		}
		if(noPath)
		{
			iAConne();
		}
		else
		{
			initPathFinding();
			iAIntelligente();
		}
	}
	public void testBalle(Balles b)
	{
		b.test(this);
	}
	public boolean testMort()
	{
		if(y > 640)
			return true;
		if(vie <= 0)
			return true;
		return false;
	}
	public void move(int direction)
	{
		if(direction == 1)
		{
			x+=speed;
			if(intersect())
				x -= speed;
			this.direction = 1;
			counterRight+=2;
		}
		else
		{
			x-=speed;
			if(intersect())
				x+=speed;
			counterLeft +=2;
			this.direction = 0;
		}
		if(counterRight > 15)
		{
			if(right != 2)
				right++;
			else
				right = 0;
			counterRight = 0;
		}
		if(counterLeft > 15)
		{
			if(left != 2)
				left++;
			else
				left= 0;
			counterLeft = 0;
		}
	}
	public void jump()
	{
		if(jumping == false)
		{
			vy = jump;
			jumping = true;
		}		
	}
}
