package lab.game;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javafx.geometry.Dimension2D;
import javafx.geometry.Point2D;
import javafx.geometry.Rectangle2D;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import lab.Config;

public class Monster extends WorldEntity implements Collisionable {

	private static Logger log = LogManager.getLogger(Monster.class);

	private static final Random RANDOM = new Random();

	private Image image;
	private Point2D speed;
	private List<DeadListener> deadListeners = new ArrayList<>();

	public Monster(Level level) {
		super(level, new Point2D(0, 0), 100);
		image = new Image(getClass().getResourceAsStream("red-monster.gif"));
		position = new Point2D(level.getWidth() * Config.getInstance().getMonsterMinXPopsition()
				+ RANDOM.nextDouble(level.getWidth() - image.getWidth()), RANDOM.nextDouble(level.getHeight()));
		speed = new Point2D(0, RANDOM.nextDouble(Config.getInstance().getMonsterMinSpeed(),
				Config.getInstance().getMonsterMaxSpeed()));
	}

	public Monster(Level level, Point2D position) {
		super(level, position);
		image = new Image(getClass().getResourceAsStream("spike.gif"));
	}

	public void drawInternal(GraphicsContext gc) {
		gc.drawImage(image, position.getX(), position.getY());
	}

	public void changeDirection() {
		speed = speed.multiply(-1);
		log.debug("Monster chaned direction.");
	}

	public void simulate(double delay) {
		position = position.add(speed.multiply(delay / 1_000_000_000));
		position = new Point2D(position.getX(), position.getY() % level.getHeight());
		if (position.getY() + image.getHeight() < 0) {
			position = new Point2D(position.getX(), level.getHeight());
		}
	}

	@Override
	public Rectangle2D getBoundingBox() {
		return new Rectangle2D(position.getX(), position.getY(), image.getWidth(), image.getHeight());
	}

	@Override
	public boolean intersect(Rectangle2D another) {
		return getBoundingBox().intersects(another);
	}

	@Override
	public void hitBy(Collisionable another) {
		log.trace("Moster hitted by {}.", another);
		if (another instanceof Player) {
			level.remove(this);
			level.add(new Obstacle(level, getPosition(), new Dimension2D(Config.getInstance().getObstacleWidth(),
					Config.getInstance().getObstacleHeight())));
			fireMonsterDead();
		}

	}

	public boolean addDeadListener(DeadListener e) {
		return deadListeners.add(e);
	}

	public boolean removeDeadListener(DeadListener o) {
		return deadListeners.remove(o);
	}

	public void fireMonsterDead() {
		for (DeadListener deadListener : deadListeners) {
			deadListener.monsterDead(this);
		}
	}
}