
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

record ShipData (int size, String name){}

public class Ship {
	static List<List<ShipData>> semeterList = Arrays.asList(Arrays.asList(
																	new ShipData(2, "PRG 1"),
																	new ShipData(2, "GDI"),
																	new ShipData(2, "MAT 1"),
																	new ShipData(2, "THI"),
																	new ShipData(4, "STP"),
																	new ShipData(6, "ENG")),
															Arrays.asList(
																	new ShipData(2, "PRG 2"),
																	new ShipData(2, "DBS 1"),
																	new ShipData(2, "MAT 2"),
																	new ShipData(2, "STA"),
																	new ShipData(2, "AUD")),
															Arrays.asList(
																	new ShipData(2, "PRG 3"),
																	new ShipData(2, "DBS 2"),
																	new ShipData(2, "MAT 3"),
																	new ShipData(2, "BSN 1"),
																	new ShipData(4, "PRP"),
																	new ShipData(6, "BWL")),
															Arrays.asList(
																	new ShipData(2, "WEB"),
																	new ShipData(2, "SE 1"),
																	new ShipData(2, "CG 1"),
																	new ShipData(2, "BSN 2"),
																	new ShipData(4, "SEM"),
																	new ShipData(6, "E BWL")),
															Arrays.asList(
																	new ShipData(2, "WPF 1"),
																	new ShipData(2, "SE 2"),
																	new ShipData(2, "CG 2"),
																	new ShipData(2, "PXP 1"),
																	new ShipData(6, "EF 1")),
															Arrays.asList(
																	new ShipData(2, "WPF 2"),
																	new ShipData(1, "PXP 2"),
																	new ShipData(8, "BAA"))
	);

	private int size;
	private boolean horizontal;
	private Point position;
	private String name;
	private int hitsOnMe;
	private boolean sunk;
	private boolean isPlaced;

	public Ship (int size, String name) {
		this.size = size;
		this.name = name;
		this.horizontal = false; //true = von Punkt aus nach rechts; false = von Punkt aus nach unten
		this.position = null;
		this.hitsOnMe = 0;
		this.sunk = false;
		this.isPlaced = false;
	}
	
	public boolean setPosition(Point pos, List<Ship> shipsList, int boardSize) {
	    // ueberpruefe boundaries
	    if (pos.getX() < 0 || pos.getY() < 0 || pos.getX() >= boardSize || pos.getY() >= boardSize) {
	        return false;
	    }

	    // bestimme die Endposition anhand der Ausrichtung
	    int endX = pos.getX();
	    int endY = pos.getY();

	    if (this.horizontal) { // rechts links
	        endX = pos.getX() + this.size - 1;
	        if (endX >= boardSize) {
	            return false;
	        }
	    } else { // oben unten
	        endY = pos.getY() + this.size - 1;
	        if (endY >= boardSize) {
	            return false;
	        }
	    }

	    // Liste an Punkten die das Schiff einnehmen wuerde
	    List<Point> shipPoints = new ArrayList<>();
	    for (int i = 0; i < this.size; i++) {
	        int x = this.horizontal ? pos.getX() + i : pos.getX(); //falls horizontal dann pos.x + i ansonsten pos.x
	        int y = this.horizontal ? pos.getY() : pos.getY() + i;
	        shipPoints.add(new Point(x, y));
	    }

	    // ueberlappen mit anderen Schiffen pruefen
	    for (Ship otherShip : shipsList) {
	        // eigenes Schiff ueberspringen
	        if (otherShip == this) {
	            continue;
	        }
	        // ueberspringe falls noch nicht gesetzt
	        if (otherShip.position == null) {
	            continue;
	        }
	        // Punkte die das andere Schiff besetzt
	        List<Point> otherShipPoints = otherShip.getOccupiedPoints();
	        // ueberlappen checken
	        for (Point p : shipPoints) {
	        	for (Point otherPoint : otherShipPoints) {
	        		if (otherPoint.neighbours(p)) return false;
	        	}
	        }
	    }

	    // kein ueberlappen also setze das Schiff
	    this.position = pos;
	    return true;
	}

	public List<Point> getOccupiedPoints() {
	    List<Point> points = new ArrayList<>();
	    if (this.position == null) {
	        return points;
	    }
	    for (int i = 0; i < this.size; i++) {
	        int x = this.horizontal ? this.position.getX() + i : this.position.getX();
	        int y = this.horizontal ? this.position.getY() : this.position.getY() + i;
	        points.add(new Point(x, y));
	    }
	    return points;
	}

	public Point getPosition() {
		return position;
	}

	public boolean isShipOnPos(Point pos){
		if(this.position == null){
			return false;
		}
		if ((this.horizontal && pos.getY() == this.position.getY() && pos.getX() >= this.position.getX() && pos.getX() < this.position.getX() + size) ||
			(!(this.horizontal) && pos.getX() == this.position.getX() && pos.getY() >= this.position.getY() && pos.getY() < this.position.getY() + size)) {
			return true;
		}
		return false;
	}

	public HitResponseType shootOnShip(Point pos) {
		if (this.isShipOnPos(pos)) {
			hitsOnMe++;
			if (hitsOnMe >= size) {
				this.sunk = true;
				return HitResponseType.SUNK;
			}  else {
				return HitResponseType.HIT;
			}
		} else {
			return HitResponseType.MISS;
		}
	}

	public boolean isSunk() {
		return sunk;
	}

	public void setHorizontal(boolean horizontal) {
		this.horizontal = horizontal;
	}

	public int getSize() {
		return size;
	}
	public String getName() {
		return name;
	}

	//potentiell falsch neu
	public boolean isPlaced(){
		return this.position != null;
	}
}
