import numpy as np

from matplotlib.patches import Rectangle

from nabirds import utils
from .base import BasePart

class LocationPart(BasePart):
	DEFAULT_RATIO = np.sqrt(49 / 400) # 0.35

	def __init__(self, image, annotation, rescale_size=None):
		super(LocationPart, self).__init__()

		annotation = self.rescale(image, annotation, rescale_size)
		# here x,y are the center of the part
		self._id, self.x, self.y, self.is_visible = annotation
		self._ratio = LocationPart.DEFAULT_RATIO

	def as_annotation(self):
		return np.array([self._id, self.x, self.y, self.is_visible])

	def crop(self, image, ratio=None, padding_mode="edge", *args, **kwargs):
		ratio = ratio or self._ratio
		_h, _w, c = utils.dimensions(image)
		w, h = int(_w * ratio), int(_h * ratio)
		return super(LocationPart, self).crop(image, w, h,
				padding_mode, is_location=True)

	def reveal(self, im, ratio=None, *args, **kwargs):
		_h, _w, c = utils.dimensions(im)
		w, h = int(_w * ratio), int(_h * ratio)
		x,y = self.xy
		x, y = max(x - w // 2, 0), max(y - h // 2, 0)
		return x, y, im[y:y+h, x:x+w]

	def plot(self, im, ax, ratio, fill=False, linestyle="--", **kwargs):
		if not self.is_visible: return
		x, y = self.xy
		_h, _w, c = utils.dimensions(im)
		w, h = int(_w * ratio), int(_h * ratio)
		ax.add_patch(Rectangle(
			(x-w//2, y-h//2), w, h,
			fill=fill, linestyle=linestyle,
			**kwargs
		))

		ax.scatter(*self.middle, marker="x", color="white", alpha=0.8)


	@property
	def middle(self):
		return np.array([self.x, self.y])

class BBoxPart(BasePart):

	def __init__(self, image, annotation, rescale_size=None):
		super(BBoxPart, self).__init__()

		annotation = self.rescale(image, annotation, rescale_size)
		# here x,y are top left corner of the part
		self._id, self.x, self.y, self.w, self.h = annotation
		self.is_visible = True

	@property
	def as_annotation(self):
		return np.array([self._id, self.x, self.y, self.w, self.h])

	def rescale(self, image, annotation, rescale_size):
		if rescale_size is not None and rescale_size > 0:
			annotation = super(BBoxPart, self).rescale(image, annotation, rescale_size)
			h, w, c = utils.dimensions(image)
			scale = np.array([w, h]) / rescale_size
			wh = annotation[3:5]
			wh = wh * scale
			annotation[3:5] = wh

		return annotation

	@property
	def middle(self):
		return np.array([self.x + self.w // 2, self.y + self.h // 2])

	def crop(self, image, padding_mode="edge", *args, **kwargs):
		return super(BBoxPart, self).crop(image, self.w, self.h,
			padding_mode, is_location=False)

	def reveal(self, im, ratio, *args, **kwargs):
		_h, _w, c = utils.dimensions(im)
		x,y = self.xy
		return x, y, im[y:y+self.h, x:x+self.w]



	def plot(self, im, ax, ratio, fill=False, linestyle="--", **kwargs):
		ax.add_patch(Rectangle(
			(self.x, self.y), self.w, self.h,
			fill=fill, linestyle=linestyle,
			**kwargs
		))

		ax.scatter(*self.middle, marker="x", color="white", alpha=0.8)

