class BaseAction:
	def __init__(self, entity):
		self.entity = entity

	def apply(self) -> None:
		raise NotImplementedError()

class QuitAction(BaseAction):
	def __init__(self): #override the base __init__
		pass

	def apply(self) -> None:
		raise SystemExit()


class WaitAction(BaseAction):
	def apply(self) -> None:
		pass


class DirectionAction(BaseAction):
	def __init__(self, entity, xdir: int, ydir: int):
		super().__init__(entity)
		self.xdir = xdir
		self.ydir = ydir

	def apply(self) -> None:
		raise NotImplementedError()


class MovementAction(DirectionAction):
	def apply(self) -> None:
		dest_x = self.entity.x + self.xdir
		dest_y = self.entity.y + self.ydir

		#bounds and collision checks
		if not self.entity.floor_map.in_bounds(dest_x, dest_y):
			return
		if not self.entity.floor_map.tiles["walkable"][dest_x, dest_y]:
			return
		if self.entity.floor_map.get_entity_at(dest_x, dest_y, unwalkable_only=True) is not None:
			return

		self.entity.set_pos(dest_x, dest_y)

class MeleeAction(DirectionAction):
	def apply(self) -> None:
		dest_x = self.entity.x + self.xdir
		dest_y = self.entity.y + self.ydir

		target = self.entity.floor_map.get_entity_at(dest_x, dest_y)

		if not target:
			return

		print(f"You kicked the {target.name}, which was funny")

class BumpAction(DirectionAction): #bad name, deal with it
	def apply(self) -> None:
		dest_x = self.entity.x + self.xdir
		dest_y = self.entity.y + self.ydir

		if self.entity.floor_map.get_entity_at(dest_x, dest_y):
			return MeleeAction(self.entity, self.xdir, self.ydir).apply()
		else:
			return MovementAction(self.entity, self.xdir, self.ydir).apply()