package position;

/**
 * A position csomagban hozzuk létre a nyilvános Position osztályt. Az osztály
 * objektumai a koordináta-rendszer pozícióit fogják ábrázolni.
 */
public class Position {

	/**
	 * Az osztályban legyen két nyilvános, int típusú, nem módosítható (final)
	 * adattag: a vízszintes (h) és a függőleges (v) koordináta.
	 */
	public final int h;
	public final int v;

	/**
	 * Egy konstruktort, amely inicializálja az adattagokat. Paraméterül várja
	 * a:
	 * @param h vízszintes és
	 * @param v függőleges koordinátákat
	 */
	public Position(int h, int v) {
		this.h = h;
		this.v = v;
	}

	/**
	 * Az Object-ből örökölt toString metódust.
	 * @return Ennek az eredménye legyen (h,v) ahol h a vízszintes, v a
	 * függőleges koordináta.
	 */
	@Override
	public String toString() {
		return "(" + h + "," + v + ")";
	}

	/**
	 * Ha az irány UP_LEFT, akkor az új pozícióban eggyel nagyobb lesz a
	 * függőleges és eggyel kisebb a vízszintes koordináta. Ha az irány
	 * DOWN_RIGHT, akkor az új pozícióban a függőleges koordináta eggyel kisebb,
	 * a vízszintes koordináta eggyel nagyobb lesz, és így tovább a maradék két
	 * esetre.
	 * @param dir paraméterül vár egy Direction értéket
	 * @return visszaadja az aktuális pozíció szomszédos pozícióját
	 */
	public Position next(Direction dir) {
		switch (dir) {
			case DOWN_LEFT:
				return new Position(h - 1, v - 1);
			case DOWN_RIGHT:
				return new Position(h + 1, v - 1);
			case UP_LEFT:
				return new Position(h - 1, v + 1);
			case UP_RIGHT:
				return new Position(h + 1, v + 1);
		}
		//3ICE: Default
		return null;
	}

	/**
	 * Az Object-ből örökölt equals metódus.
	 * @param o a paraméterül kapott Object referencia Position objektumra mutat
	 * (instanceof segít eldönteni)
	 * @return csak akkor ad vissza logikai igaz értéket, ha ennek a Position
	 * objektumnak a koordinátái megegyeznek annak a Position objektumnak a
	 * koordinátáival, amelyre meghívták az equals-t.
	 * @note Biztonság kedvéért használjuk az Override annotációt.
	 */
	@Override
	public boolean equals(Object o) {
		return o != null && o instanceof Position && ((Position) o).h == h && ((Position) o).v == v;
	}

	/**
	 * Egy distance metódus.
	 * @param q paraméterül vár egy másik pozíciót
	 * @return visszaadja egy kételemű, egészekből álló tömbben a vízszintes és
	 * függőleges távolságot, melyet az aktuális pozíciótól a paraméterül kapott
	 * pozícióig meg kell tenni.
	 */
	public int[] distance(Position q) {
		return new int[]{q.h - h, q.v - v};
	}

	/**
	 * Egy osztályszintű isDiagonal metódus. Ehhez számoljuk ki a pozíciók közti
	 * távolságot (distance). A két pozíció egy átlón helyezkedik el, ha a
	 * függőleges és a vízszintes távolság megegyezik, vagy a kettő összege 0.
	 * @param p paraméterül vár két pozíciót
	 * @param q paraméterül vár két pozíciót
	 * @return csak akkor ad vissza igaz értéket, ha a két pozíció egy átlón
	 * helyezkedik el
	 */
	public static boolean isDiagonal(Position p, Position q) {
		return (Math.abs(p.v - q.v) == Math.abs(p.h - q.h));
	}

	/**
	 * Az Object-ből örökölt hashCode-t.
	 * @return A visszaadott egész szám értéke legyen 100 * v + h, ahol v a
	 * függőleges, h a vízszintes koordináta.
	 * @note Biztonság kedvéért használjuk az Override annotációt.
	 */
	@Override
	public int hashCode() {
		return 100 * v + h;
	}

	/**
	 * @return horizontal / vízszintes
	 */
	public int getH() {
		return h;
	}

	/**
	 * @return vertical / függőleges
	 */
	public int getV() {
		return v;
	}
}
