from __future__ import annotations

import copy
import math
from typing import Optional, Tuple, Type, TYPE_CHECKING

from ai import BaseAI
from stats import Stats
from inventory import Inventory
from useable import BaseUseable

if TYPE_CHECKING:
	from floor_map import FloorMap

class Entity:
	ai: Optional[BaseAI] = None
	stats: Optional[Stats] = None
	inventory: Optional[Inventory] = None
	useable: Optional[BaseUseable] = None

	def __init__(
		self,
		x: int = 0,
		y: int = 0,
		char: str = "?",
		color: Tuple[int, int, int] = (255, 255, 255),
		*,
		name: str = "<Unnamed>",
		walkable: bool = True,
		floor_map: FloorMap = None,

		#monster-specific stuff
		ai_class: Type[BaseAI] = None,
		stats: Stats = None,

		#item-specific stuff
		inventory: Inventory = None,
		useable: BaseUseable = None,
	):
		self.x = x
		self.y = y
		self.char = char
		self.color = color
		self.name = name
		self.walkable = walkable
		self.floor_map = floor_map

		#monster-specific stuff
		if ai_class:
			self.ai = ai_class(self)

		if stats:
			self.stats = stats
			self.stats.entity = self

		#item-specific stuff
		if inventory:
			self.inventory = inventory

		if useable:
			self.useable = useable
			self.useable.entity = self

	#generic entity stuff
	def spawn(self, x: int, y: int, floor_map: FloorMap):
		clone = copy.deepcopy(self)
		clone.x = x
		clone.y = y
		clone.floor_map = floor_map
		clone.floor_map.entities.add(clone)
		return clone

	def set_pos(self, x: int, y: int) -> None:
		self.x = x
		self.y = y

	def get_distance_to(self, x: int, y: int) -> float:
		return math.sqrt((x - self.x) ** 2 + (y - self.y) ** 2)

	#monster-specific stuff
	def is_alive(self) -> bool:
		return bool(self.ai)

	#item-specific stuff
	def is_item(self) -> bool:
		return bool(self.useable)