package de.heatup.objects;

import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;

import de.heatup.mapengine.CollisionHandler;
import de.heatup.ui.Main;
import de.heatup.ui.PanelBuilder;

//TODO: Magische Nummern entfernen

public class Opponent extends Player {

	private static final long serialVersionUID = 1L;
	// Nötig sobald der Schritt in die gewollte Richtung erfolgt ist
	private boolean redecide = true; 
	private Random rand = new Random();
	private int testX;
	private int testY;
	// Notwendig um Blockade zu erkennen
	private int previ;
	private char prevd;
	private int prevX;
	private int prevY;
	private boolean blocked = false;
	private boolean move = false;
	private int blockedCounter = 0;
	private char charDir;
	// Direkten Pfad zum Spieler nutzen
	private char newd;
	// Variablen zur Animation
	private int tickCounter = 0;
	private int ticker = 0;

	public Opponent() {
		CollisionHandler.addMovingObject(this);
	}
	
	@Override protected void loadBufferedImage() {
		try {
			super.bf1 = ImageIO.read(this.getClass().getClassLoader().getResourceAsStream("de/heatup/resources/images/opponent_f1.png"));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	@Override public void tick() {

		if ( ! this.loaded ) {
			loadBufferedImage_to(2,'w');
			loadBufferedImage_to(3,'x');
			loadBufferedImage_to(4,'y');
			loadBufferedImage_to(5,'z');
			System.out.println("Loaded..");
			this.loaded = true;
		}

		
		// Part for Animation
		this.tickCounter++;
		if ( (this.tickCounter%10) == 0 ) {
			this.tickCounter = 0;
			if ( ticker == 0 ) {
//				super.setImgChar('w');
//				super.loadBufferedImage();
				setImage(this.bf2);
				ticker = 1;
			} else if ( ticker == 1 ) {
//				super.setImgChar('x');
//				super.loadBufferedImage();
				setImage(this.bf3);
				ticker = 2;
			} else if ( ticker == 2 ) {
//				super.setImgChar('y');
//				super.loadBufferedImage();
				setImage(this.bf4);
				ticker = 3;
			} else if ( ticker == 3 ) {
//				super.setImgChar('z');
//				super.loadBufferedImage();
				setImage(this.bf5);
				ticker = 0;
			}
		}
		
		if ( redecide ) {	
			while ( true ) {
				
				// Blockade Erkennung 
				if ( this.prevX == this.getGridLocation().x & this.prevY == this.getGridLocation().y ) {
					this.blockedCounter++;
				} else {
					this.blockedCounter = 0;
				}
				this.blocked = (this.blockedCounter >= 30) ? true : false;
				this.prevX = this.getGridLocation().x;
				this.prevY = this.getGridLocation().y;
				
				if ( direction == 'x' ) {
					if ( CollisionHandler.checkCollision(this, 'd') ) {
						this.move = false;
					}
					if ( CollisionHandler.checkCollision(this, 'u') ) {
						this.move = false;
					}
				}

				if ( direction == 'y' ) {
					if ( CollisionHandler.checkCollision(this, 'l') ) {
						this.move = false;
					}
					if ( CollisionHandler.checkCollision(this, 'r') ) {
						this.move = false;
					}
				}

				/*
				 * Spieler identifizieren und auf "direkte Sicht" prüfen 
				 */
				int playerX = Main.getPlayer().getGridLocation().x;
				int playerY = Main.getPlayer().getGridLocation().y;
				char playerDirection = '0';
				int stepLength = 0;
				// Richtung bestimmen wenn sich Spieler und Gegner auf einer Achse befinden
				if ( this.getGridLocation().x == playerX) {
					//Auf Y-Achse in Richtung Spieler bewegen
					playerDirection = (this.getGridLocation().y > playerY ) ? 'u' : 'd';
					stepLength = Math.abs(this.getGridLocation().y - playerY);
					this.newd = 'y';
					i = (playerDirection == 'u') ? -1 : 1;					
				} else if ( this.getGridLocation().y == playerY) {
					// Auf X-Achse in Richtung Spieler bewegen
					playerDirection = (this.getGridLocation().x > playerX ) ? 'l' : 'r';
					stepLength = Math.abs(this.getGridLocation().x - playerX);
					this.newd = 'x';
					i = (playerDirection == 'l') ? -1 : 1;
				}
				
				// Sichtprüfung durchführen
				if ( stepLength != 0 && playerDirection != '0' && CollisionHandler.checkCollision(this.getGridLocation(), playerDirection, stepLength) ) {
					//Logger.write("Direct path to player, distance: " + stepLength );
					direction = this.newd;
					charDir = playerDirection;
					this.move = true;
				}
								
				// Umentscheiden oder weiter in die vorgegeben Richtung
				if ( ! this.move ) {
					//Logger.write("Redeciding...");
					this.direction = (rand.nextInt(10) <= 4) ? 'x' : 'y';
					this.i = (rand.nextInt(10) <= 4) ? 1 : -1;
					// Sicher stellen das man nicht in die Richtung geht aus der man gekommen ist.
					if ( redecide && this.direction == this.prevd && this.i != this.previ ) {
						this.i *= -1;
					}
				} else {
					//Logger.write("Moving...");					
				}
				this.move = true;

				// Blockade auflösen, gehe doch in die Richtung aus man gekommen ist
				if ( this.blocked ) {
					//Logger.write("Warning: Block detected!");
					this.i *= -1;
					this.move = false;
					this.blocked = false;
					this.blockedCounter = 0;
				}
				
				// Neue Koordinaten bestimmen
				if (direction == 'x') {
					testX=this.getGridLocation().x + i;
					testY=this.getGridLocation().y;
				} else if (direction == 'y') {
					testY=this.getGridLocation().y + i;
					testX=this.getGridLocation().x;				
				}
				
				if ( direction == 'x' && i == -1 ) {
					charDir = 'l';
				} else if ( direction == 'x' && i == 1 ) {
					charDir = 'r';
				} else if ( direction == 'y' && i == -1 ) {
					charDir = 'u';
				} else if ( direction == 'y' && i == 1 ) {
					charDir = 'd';
				}				
				
				if (CollisionHandler.checkCollision(this, charDir)) {
					this.setGridLocation(testX, testY);
					this.prevd = direction;
					this.previ = i;
					redecide = false;
					animate = true;
					break;
				}	
			}
		}
	
		if ( animate ) {
			int newx = this.getX();
			int newy = this.getY();
	
			// Speed Multiplikator
			for (int s = 0; s < this.speedMultiplicator; s++) {
				if (direction == 'x' && i == -1) {
					newx = newx - 1;
				} else if (direction == 'x' && i == 1) {
					newx = newx + 1;
				} else if (direction == 'y' && i == -1) {
					newy = newy - 1;
				} else if (direction == 'y' && i == 1) {
					newy = newy + 1;
				}
				
				this.setAutoBounds(newx, newy);
				stepCounter--;
				if ( stepCounter <= 0 ) {
					animate = false;
					break;
				}
				
			}
			if (stepCounter <= 0) {
				stepCounter = 25;
				redecide = true;
				animate = false;
			} else { 
				animate = true; 
			}
		}
	}
}
