package gamepack.data.drawable;


import gamepack.data.Point;
import gamepack.utility.Direction;
import gamepack.utility.ProjectMethods;

import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.geom.Rectangle;

public class Tile implements DrawableObject
{
	private int			value;
	private int			powerOfTwo;
	
	protected Rectangle	rectangle;
	protected Color rectangleColor;
	
	private Direction	tileDirection;	//Give in which direction the tile goes
	private Tile		arrivedTile;	//If the tile has an arrived Tile
	private Point		arrivedPoint;	//If the tile has an arrived Point
	
	private int prevValue;
	private Point prevPosition;
	private Tile mergedTile;
	
	
	public Tile(int x, int y, int value)
	{
		this.rectangle = new Rectangle(x, y, 50, 50);
		this.value = value;
		powerOfTwo = ProjectMethods.powerOfTwo(value);
		tileDirection = Direction.None;
		refreshColor();
	}
	
	public Tile(Tile t)
	{
		this.value = t.value;
		this.powerOfTwo = t.powerOfTwo;

		this.rectangle = new Rectangle(t.getX(), t.getY(), t.rectangle.getWidth(), t.rectangle.getHeight());
		this.tileDirection = t.tileDirection;
		this.arrivedTile = t.arrivedTile;
		this.arrivedPoint = t.arrivedPoint;
		refreshColor();
	}
	
	//GET
	public int getValue()
	{
		return this.value;
	}
	
	public float getX()
	{
		return this.rectangle.getX();
	}
	
	public float getY()
	{
		return this.rectangle.getY();
	}
	
	private int getCenterX()
	{
		return (int) this.rectangle.getCenterX();
	}
	
	private int getCenterY()
	{
		return (int) this.rectangle.getCenterY();
	}

	public Tile getArrivedTile()
	{
		return this.arrivedTile;
	}
	
	public Point getArrivedPoint() {
	return arrivedPoint;
	}

	public int getArrivedPointX()
	{
		return arrivedPoint.getX();
	}
	
	public int getArrivedPointY()
	{
		return arrivedPoint.getY();
	}

	public Direction getDirection()
	{
		return this.tileDirection;
	}
	
	protected int getTextX()
	{
		return getCenterX();
	}
	
	protected int getTextY()
	{
		return getCenterY();
	}
	
	//SET
	public void setX(int x)
	{
		this.rectangle.setX(x);
	}
	
	public void setY(int y)
	{
		this.rectangle.setY(y);
	}

	public void setArrivedTile(Tile t)
	{
		this.arrivedTile = t;
	}
	
	public void setArrivedPoint(Point arrivedPoint)
	{
		this.arrivedPoint = arrivedPoint;
	}
	
	public void setDirection(Direction tileDirection)
	{
		this.tileDirection = tileDirection;
	}
	
	public void setSize(int size)
	{
		rectangle.setSize(size, size);
	}
	
	
	//OTHER
	
	//Double the value of the tile, increment the powerOfTwo and refresh the color
	public void doubleValue()
	{
		value = 2*value;
		powerOfTwo++;
		refreshColor();
	}
	
	//move the tile 
	public void move(float x, float y)
	{
		this.rectangle.setX(this.rectangle.getX() + x);
		this.rectangle.setY(this.rectangle.getY() + y);
	}
	
	//Test if two tiles have the same positions and value
	public boolean equals(Tile secondTile)
	{
		if (secondTile != null && getX() == secondTile.getX() && getY() == secondTile.getY() && value == secondTile.getValue()) 
			return true;
		return false;
	}
	
	//If the tile and his arrivedTile has the same coordinates, return true
	//then, double the value of the arrivedTile (use a method doubleValue())
	public Boolean refreshFusion()
	{
		if (this.equals(this.arrivedTile)) {
			this.arrivedTile.doubleValue();
			return true;
		}else{
			return false;
		}
	}
	
	//return true if the tile has arrived to his arrivedPoint 
	public boolean isArrived()
	{
		if(arrivedPoint != null)
			return getX() == arrivedPoint.getX() && getY() == arrivedPoint.getY();
		return true;
	}
	
	//avoid a bad positionning of the tile (it could be positionning after the arrived point due to
	//bad framerate)
	public void improvePosition()
	{
		if(tileDirection == Direction.Left)
		{
			if(getX() < getArrivedPointX())
				setX(getArrivedPointX());
		}
		else if(tileDirection == Direction.Right)
		{
			if(getX() > getArrivedPointX())
				setX(getArrivedPointX());
		}
		else if(tileDirection == Direction.Up)
		{
			if(getY() < getArrivedPointY())
				setY(getArrivedPointY());
		}
		else if(tileDirection == Direction.Down)
		{
			if(getY() > getArrivedPointY())
				setY(getArrivedPointY());
		}
	}
	
	//Draw the Tile
	public void beDrawn(Graphics gr)
	{
		//Couleur mise
		gr.setColor(rectangleColor);
		gr.fill(rectangle);
		
		gr.setColor(Color.white);
		gr.drawString("" + value, getTextX(), getTextY());
	}
	
	//refresh the color of the Tile
	private void refreshColor()
	{
		int rgb[] = ProjectMethods.getRGBColor(powerOfTwo);
		rectangleColor = new Color(rgb[0],rgb[1],rgb[2]);
	}

	public void setMergedPrev(Tile prevTile)
	{
		this.setPrev();
		mergedTile = prevTile;
	}
	
	public void setPrev()
	{
		prevPosition = new Point((int) rectangle.getX(), (int) rectangle.getY());
		prevValue = value;
		mergedTile = null;
	}
	
	public Tile getMergedTile()
	{
		return this.mergedTile;
	}
	
	public void undo()
	{
		this.setArrivedTile(null);
		this.setArrivedPoint(this.prevPosition);
		prevPosition = null;
		prevValue = 0;
		mergedTile = null;
	}
	
	public String toString()
	{
		return ""+value;
	}
}

@@ -3495,16 +3495,45 @@
 lue();%0D%0A
+%09%09%09this.arrivedTile = null;%0D%0A
 %09%09%09retur
@@ -5330,32 +5330,50 @@
 = null;%0D%0A%09%7D%0D%0A%09%0D%0A
+%09//draw the tile%0D%0A
 %09public String t

delete the arrivedTile in the Tile if there is a fusion