package net.robertboehm.ld22;

import org.newdawn.slick.geom.Shape;

public class CollisionEntity implements ICollidable {
	
	public static final float STEPSIZE = 0.25f;
	
	protected Shape shape;
	protected IEnvironment collisionEnvironment;
	protected float velocityX = 0;
	protected float velocityY = 0;
	
	public CollisionEntity(Shape shape, IEnvironment collisionEnvironment) {
		this.shape = shape;
		this.collisionEnvironment = collisionEnvironment;
	}
	
	public void setCollisionEnvironment(IEnvironment collisionEnvironment) {
		this.collisionEnvironment = collisionEnvironment;
	}
	
	public float getX() {
		return this.shape.getX();
	}
	
	public float getY() {
		return this.shape.getY();
	}
	
	public void setX(float x) {
		this.shape.setX(x);
	}
	
	public void setY(float y) {
		this.shape.setY(y);
	}
	
	public void forceX(float x) {
		this.velocityX += x;
	}
	
	public void forceY(float y) {
		this.velocityY += y;
	}

	public void multiplyX(float factor) {
		this.velocityX *= factor;
	}

	public void multiplyY(float factor) {
		this.velocityY *= factor;
	}

	public void resetVelocity() {
		this.velocityX = 0;
		this.velocityY = 0;
	}
	
	public void setPosition(float x, float y) {
		this.setX(x);
		this.setY(y);
	}

	public void addX(float x) {
		float oldX = this.getX();
		this.setX(oldX + x);
		if(collisionEnvironment.intersects(shape)) {
			this.velocityX = 0;
			if(x <= 1) {
				this.setX(oldX);
			} else {
				for(float xo = oldX + STEPSIZE; xo < oldX + x; xo += STEPSIZE) {
					this.setX(xo);
					if(collisionEnvironment.intersects(shape)) {
						this.setX(xo - STEPSIZE);
						break;
					}
				}
			}
		}
	}
	
	public void addY(float y) {
		float oldY = this.getY();
		this.setY(oldY + y);
		if(collisionEnvironment.intersects(shape)) {
			this.velocityY = 0;
			this.setY(oldY);
			/*if(y < 0) {
				if(y >= -STEPSIZE) {
					this.setY(oldY);
				} else {
					for(float yo = oldY + STEPSIZE; yo < oldY + y; yo += STEPSIZE) {
						this.setY(yo);
						if(collisionEnvironment.intersects(shape)) {
							this.setY(yo - STEPSIZE);
							break;
						}
					}
				}
			} else if(y > 0) {
				if(y <= STEPSIZE) {
					this.setY(oldY);
				} else {
					for(float yo = oldY + STEPSIZE; yo < oldY + y; yo += STEPSIZE) {
						this.setY(yo);
						if(collisionEnvironment.intersects(shape)) {
							this.setY(yo - STEPSIZE);
							break;
						}
					}
				}
			}*/
		}
	}

	public Shape getShape() {
		return this.shape;
	}

	public boolean isStanding() {
		float oldY = getY();
		setY(oldY + 1);
		float myY = getY();
		boolean isStanding = collisionEnvironment.intersects(shape);
		if(getY() == myY) {
			setY(oldY);
		}
		return isStanding;
	}
	
	@Override
	public boolean intersects(Shape other) {
		return other.intersects(shape);
	}

	public void update(float elapsed) {
		velocityY += collisionEnvironment.getGravity() * elapsed;
		this.addX(velocityX * elapsed);
		this.addY(velocityY * elapsed);
		
		double friction = Math.pow(collisionEnvironment.getFriction(), elapsed);
		velocityX = (float) (velocityX * friction);
		velocityY = (float) (velocityY * friction);
	}

}
