package com.rs.game.route;

/**
 * Class, controlling the exit point of a route.
 */
public abstract class RouteStrategy {

	public static final int BLOCK_FLAG_NORTH = 0x1;
	public static final int BLOCK_FLAG_EAST = 0x2;
	public static final int BLOCK_FLAG_SOUTH = 0x4;
	public static final int BLOCK_FLAG_WEST = 0x8;

	/**
	 * Whether we can exit at specific x and y.
	 */
	public abstract boolean canExit(int currentX, int currentY, int sizeXY, int[][] clip, int clipBaseX, int clipBaseY);

	/**
	 * Get's approximated destination position X.
	 */
	public abstract int getApproxDestinationX();

	/**
	 * Get's approximated destination position Y.
	 */
	public abstract int getApproxDestinationY();

	/**
	 * Get's approximated destination size X.
	 */
	public abstract int getApproxDestinationSizeX();

	/**
	 * Get's approximated destination size Y.
	 */
	public abstract int getApproxDestinationSizeY();

	/**
	 * Whether this strategy equals to other object.
	 */
	public abstract boolean equals(Object other);

	/**
	 * Check's if we can interact wall decoration from current position.
	 */
	protected static boolean checkWallDecorationInteract(int[][] clip, int currentX, int currentY, int sizeXY, int targetX, int targetY, int targetType, int targetRotation) {
		// TODO, include additional checks for size's bigger than 1.
		if (currentX == targetX && currentY == targetY)
			return true;
		if (targetType == 6 || targetType == 7) {
			if (targetType == 7)
				targetRotation = targetRotation + 2 & 0x3;
			if (targetRotation == 0) {
				if (currentX == (targetX + 1) && currentY == targetY && (clip[currentX][currentY] & Flags.WALLOBJ_WEST) == 0)
					return true;
				if (currentX == targetX && currentY == (targetY - 1) && (clip[currentX][currentY] & Flags.WALLOBJ_NORTH) == 0)
					return true;
			} else if (targetRotation == 1) {
				if (currentX == (targetX - 1) && currentY == targetY && (clip[currentX][currentY] & Flags.WALLOBJ_EAST) == 0)
					return true;
				if (currentX == targetX && currentY == (targetY - 1) && (clip[currentX][currentY] & Flags.WALLOBJ_NORTH) == 0)
					return true;
			} else if (targetRotation == 2) {
				if (currentX == (targetX - 1) && currentY == targetY && (clip[currentX][currentY] & Flags.WALLOBJ_EAST) == 0)
					return true;
				if (currentX == targetX && currentY == (targetY + 1) && (clip[currentX][currentY] & Flags.WALLOBJ_SOUTH) == 0)
					return true;
			} else if (targetRotation == 3) {
				if (currentX == (targetX + 1) && currentY == targetY && (clip[currentX][currentY] & Flags.WALLOBJ_WEST) == 0)
					return true;
				if (currentX == targetX && currentY == (targetY + 1) && (clip[currentX][currentY] & Flags.WALLOBJ_SOUTH) == 0)
					return true;
			}
		} else if (targetType == 8) {
			if (currentX == targetX && currentY == (targetY + 1) && (clip[currentX][currentY] & Flags.WALLOBJ_SOUTH) == 0)
				return true;
			if (currentX == targetX && currentY == (targetY - 1) && (clip[currentX][currentY] & Flags.WALLOBJ_NORTH) == 0)
				return true;
			if (currentX == (targetX - 1) && currentY == targetY && (clip[currentX][currentY] & Flags.WALLOBJ_EAST) == 0)
				return true;
			if (currentX == (targetX + 1) && currentY == targetY && (clip[currentX][currentY] & Flags.WALLOBJ_WEST) == 0)
				return true;
		}
		return false;
	}

	/**
	 * Check's if we can interact wall object from current position.
	 */
	protected static boolean checkWallInteract(int[][] clips, int currentX, int currentY, int sizeXY, int targetX, int targetY, int targetType, int targetRotation) {
		// TODO refactor
		if (sizeXY == 1) {
			if (currentX == targetX && currentY == targetY)
				return true; // we are inside the object
		} else if (targetX >= currentX && targetX <= currentX + sizeXY - 1 && targetY <= targetY + sizeXY - 1)
			return true; // we are inside the object bounds , though no y check?
		if (sizeXY == 1) {
			if (targetType == 0) {
				if (targetRotation == 0) {
					if (targetX - 1 == currentX && currentY == targetY)
						return true;
					if (currentX == targetX && targetY + 1 == currentY && (clips[currentX][currentY] & 0x2c0120) == 0)
						return true;
					if (targetX == currentX && currentY == targetY - 1 && (clips[currentX][currentY] & 0x2c0102) == 0)
						return true;
				} else if (targetRotation == 1) {
					if (currentX == targetX && targetY + 1 == currentY)
						return true;
					if (currentX == targetX - 1 && targetY == currentY && (clips[currentX][currentY] & 0x2c0108) == 0)
						return true;
					if (targetX + 1 == currentX && currentY == targetY && (clips[currentX][currentY] & 0x2c0180) == 0)
						return true;
				} else if (targetRotation == 2) {
					if (targetX + 1 == currentX && currentY == targetY)
						return true;
					if (targetX == currentX && currentY == targetY + 1 && (clips[currentX][currentY] & 0x2c0120) == 0)
						return true;
					if (targetX == currentX && currentY == targetY - 1 && (clips[currentX][currentY] & 0x2c0102) == 0)
						return true;
				} else if (targetRotation == 3) {
					if (currentX == targetX && targetY - 1 == currentY)
						return true;
					if (targetX - 1 == currentX && currentY == targetY && (clips[currentX][currentY] & 0x2c0108) == 0)
						return true;
					if (targetX + 1 == currentX && targetY == currentY && (clips[currentX][currentY] & 0x2c0180) == 0)
						return true;
				}
			}
			if (targetType == 2) {
				if (targetRotation == 0) {
					if (currentX == targetX - 1 && currentY == targetY)
						return true;
					if (targetX == currentX && targetY + 1 == currentY)
						return true;
					if (currentX == targetX + 1 && targetY == currentY && (clips[currentX][currentY] & 0x2c0180) == 0)
						return true;
					if (targetX == currentX && targetY - 1 == currentY && (clips[currentX][currentY] & 0x2c0102) == 0)
						return true;
				} else if (targetRotation == 1) {
					if (targetX - 1 == currentX && targetY == currentY && (clips[currentX][currentY] & 0x2c0108) == 0)
						return true;
					if (targetX == currentX && targetY + 1 == currentY)
						return true;
					if (targetX + 1 == currentX && currentY == targetY)
						return true;
					if (targetX == currentX && currentY == targetY - 1 && (clips[currentX][currentY] & 0x2c0102) == 0)
						return true;
				} else if (targetRotation == 2) {
					if (targetX - 1 == currentX && currentY == targetY && (clips[currentX][currentY] & 0x2c0108) == 0)
						return true;
					if (currentX == targetX && currentY == targetY + 1 && (clips[currentX][currentY] & 0x2c0120) == 0)
						return true;
					if (currentX == targetX + 1 && targetY == currentY)
						return true;
					if (currentX == targetX && targetY - 1 == currentY)
						return true;
				} else if (targetRotation == 3) {
					if (targetX - 1 == currentX && currentY == targetY)
						return true;
					if (targetX == currentX && targetY + 1 == currentY && (clips[currentX][currentY] & 0x2c0120) == 0)
						return true;
					if (currentX == targetX + 1 && targetY == currentY && (clips[currentX][currentY] & 0x2c0180) == 0)
						return true;
					if (currentX == targetX && targetY - 1 == currentY)
						return true;
				}
			}
			if (targetType == 9) {
				if (targetX == currentX && targetY + 1 == currentY && (clips[currentX][currentY] & 0x20) == 0)
					return true;
				if (currentX == targetX && targetY - 1 == currentY && (clips[currentX][currentY] & 0x2) == 0)
					return true;
				if (currentX == targetX - 1 && currentY == targetY && (clips[currentX][currentY] & 0x8) == 0)
					return true;
				if (currentX == targetX + 1 && currentY == targetY && (clips[currentX][currentY] & 0x80) == 0)
					return true;
			}
		} else {
			int i_66_ = currentX + sizeXY - 1;
			int i_67_ = sizeXY + currentY - 1;
			if (targetType == 0) {
				if (targetRotation == 0) {
					if (targetX - sizeXY == currentX && targetY >= currentY && targetY <= i_67_)
						return true;
					if (targetX >= currentX && targetX <= i_66_ && currentY == targetY + 1 && (clips[targetX][currentY] & 0x2c0120) == 0)
						return true;
					if (targetX >= currentX && targetX <= i_66_ && targetY - sizeXY == currentY && (clips[targetX][i_67_] & 0x2c0102) == 0)
						return true;
				} else if (targetRotation == 1) {
					if (targetX >= currentX && targetX <= i_66_ && targetY + 1 == currentY)
						return true;
					if (currentX == targetX - sizeXY && targetY >= currentY && targetY <= i_67_ && (clips[i_66_][targetY] & 0x2c0108) == 0)
						return true;
					if (targetX + 1 == currentX && targetY >= currentY && targetY <= i_67_ && (clips[currentX][targetY] & 0x2c0180) == 0)
						return true;
				} else if (targetRotation == 2) {
					if (targetX + 1 == currentX && targetY >= currentY && targetY <= i_67_)
						return true;
					if (targetX >= currentX && targetX <= i_66_ && currentY == targetY + 1 && (clips[targetX][currentY] & 0x2c0120) == 0)
						return true;
					if (targetX >= currentX && targetX <= i_66_ && currentY == targetY - sizeXY && (clips[targetX][i_67_] & 0x2c0102) == 0)
						return true;
				} else if (targetRotation == 3) {
					if (targetX >= currentX && targetX <= i_66_ && targetY - sizeXY == currentY)
						return true;
					if (currentX == targetX - sizeXY && targetY >= currentY && targetY <= i_67_ && (clips[i_66_][targetY] & 0x2c0108) == 0)
						return true;
					if (targetX + 1 == currentX && targetY >= currentY && targetY <= i_67_ && (clips[currentX][targetY] & 0x2c0180) == 0)
						return true;
				}
			}
			if (targetType == 2) {
				if (targetRotation == 0) {
					if (targetX - sizeXY == currentX && targetY >= currentY && targetY <= i_67_)
						return true;
					if (targetX >= currentX && targetX <= i_66_ && targetY + 1 == currentY)
						return true;
					if (targetX + 1 == currentX && targetY >= currentY && targetY <= i_67_ && (clips[currentX][targetY] & 0x2c0180) == 0)
						return true;
					if (targetX >= currentX && targetX <= i_66_ && targetY - sizeXY == currentY && (clips[targetX][i_67_] & 0x2c0102) == 0)
						return true;
				} else if (targetRotation == 1) {
					if (currentX == targetX - sizeXY && targetY >= currentY && targetY <= i_67_ && (clips[i_66_][targetY] & 0x2c0108) == 0)
						return true;
					if (targetX >= currentX && targetX <= i_66_ && currentY == targetY + 1)
						return true;
					if (targetX + 1 == currentX && targetY >= currentY && targetY <= i_67_)
						return true;
					if (targetX >= currentX && targetX <= i_66_ && currentY == targetY - sizeXY && (clips[targetX][i_67_] & 0x2c0102) == 0)
						return true;
				} else if (targetRotation == 2) {
					if (currentX == targetX - sizeXY && targetY >= currentY && targetY <= i_67_ && (clips[i_66_][targetY] & 0x2c0108) == 0)
						return true;
					if (targetX >= currentX && targetX <= i_66_ && targetY + 1 == currentY && (clips[targetX][currentY] & 0x2c0120) == 0)
						return true;
					if (targetX + 1 == currentX && targetY >= currentY && targetY <= i_67_)
						return true;
					if (targetX >= currentX && targetX <= i_66_ && currentY == targetY - sizeXY)
						return true;
				} else if (targetRotation == 3) {
					if (targetX - sizeXY == currentX && targetY >= currentY && targetY <= i_67_)
						return true;
					if (targetX >= currentX && targetX <= i_66_ && currentY == targetY + 1 && (clips[targetX][currentY] & 0x2c0120) == 0)
						return true;
					if (targetX + 1 == currentX && targetY >= currentY && targetY <= i_67_ && (clips[currentX][targetY] & 0x2c0180) == 0)
						return true;
					if (targetX >= currentX && targetX <= i_66_ && currentY == targetY - sizeXY)
						return true;
				}
			}
			if (targetType == 9) {
				if (targetX >= currentX && targetX <= i_66_ && targetY + 1 == currentY && (clips[targetX][currentY] & 0x2c0120) == 0)
					return true;
				if (targetX >= currentX && targetX <= i_66_ && targetY - sizeXY == currentY && (clips[targetX][i_67_] & 0x2c0102) == 0)
					return true;
				if (targetX - sizeXY == currentX && targetY >= currentY && targetY <= i_67_ && (clips[i_66_][targetY] & 0x2c0108) == 0)
					return true;
				if (currentX == targetX + 1 && targetY >= currentY && targetY <= i_67_ && (clips[currentX][targetY] & 0x2c0180) == 0)
					return true;
			}
		}
		return false;
	}

	/**
	 * Check's if we can interact filled rectangular (Might be ground object or npc or player etc) from current
	 * position.
	 */
	protected static boolean checkFilledRectangularInteract(int[][] clip, int currentX, int currentY, int sizeX, int sizeY, int targetX, int targetY, int targetSizeX, int targetSizeY, int accessBlockFlag) {
		// TODO refactor
		int srcEndX = currentX + sizeX;
		int srcEndY = currentY + sizeY;
		int destEndX = targetX + targetSizeX;
		int destEndY = targetY + targetSizeY;
		if (destEndX == currentX && (accessBlockFlag & 0x2) == 0) { // can we
			// enter
			// from east
			// ?
			int i_12_ = currentY > targetY ? currentY : targetY;
			for (int i_13_ = srcEndY < destEndY ? srcEndY : destEndY; i_12_ < i_13_; i_12_++) {
				if (((clip[destEndX - 1][i_12_]) & 0x8) == 0)
					return true;
			}
		} else if (srcEndX == targetX && (accessBlockFlag & 0x8) == 0) { // can
			// we
			// enter
			// from
			// west
			// ?
			int i_14_ = currentY > targetY ? currentY : targetY;
			for (int i_15_ = srcEndY < destEndY ? srcEndY : destEndY; i_14_ < i_15_; i_14_++) {
				if (((clip[targetX][i_14_]) & 0x80) == 0)
					return true;
			}
		} else if (currentY == destEndY && (accessBlockFlag & 0x1) == 0) { // can
			// we
			// enter
			// from
			// north?
			int i_16_ = currentX > targetX ? currentX : targetX;
			for (int i_17_ = srcEndX < destEndX ? srcEndX : destEndX; i_16_ < i_17_; i_16_++) {
				if (((clip[i_16_][destEndY - 1]) & 0x2) == 0)
					return true;
			}
		} else if (targetY == srcEndY && (accessBlockFlag & 0x4) == 0) { // can
			// we
			// enter
			// from
			// south?
			int i_18_ = currentX > targetX ? currentX : targetX;
			for (int i_19_ = srcEndX < destEndX ? srcEndX : destEndX; i_18_ < i_19_; i_18_++) {
				if (((clip[i_18_][targetY]) & 0x20) == 0)
					return true;
			}
		}
		return false;
	}

}
