from typing import Any, Union

try:
	from typing import override
except ImportError:
	from typing_extensions import override  # noqa: F401

import tgt
import pyqtgraph as pg

from .markers import Marker, IntervalMarker
from .tiers import PointTier, IntervalTier, TextGrid, TextgridConverter


class PointTierTGTConvert(TextgridConverter[PointTier, tgt.core.PointTier]):
	@override
	def to_textgrid(self, to_convert: PointTier) -> tgt.core.PointTier:
		"""
		Converts a PointTier object to a tgt.core.PointTier object.

		Args:
			to_convert (PointTier): The PointTier instance to convert.

		Returns:
			tgt.core.PointTier: The equivalent tgt.core.PointTier with points copied over.
		"""

		tgt_tier = tgt.core.PointTier(
			to_convert.get_start_time(),
			to_convert.get_end_time(),
			to_convert.get_name(),
		)

		for point in to_convert.get_elements():
			tgt_point = tgt.core.Point(point, point.name)
			tgt_tier.add_point(tgt_point)

		return tgt_tier

	@override
	def from_textgrid(self, convert_from: tgt.core.PointTier) -> PointTier:
		"""
		Creates a PointTier object from a tgt.core.PointTier object.

		Args:
			convert_from (tgt.core.PointTier): The tgt.core.PointTier to convert.

		Returns:
			PointTier: A new PointTier instance containing markers from the tgt.core.PointTier.
		"""

		point_tier = PointTier(
			convert_from.name, convert_from.start_time, convert_from.end_time, self
		)

		for p in convert_from.points:
			point = Marker(p.time, p.text)
			point_tier.add_element(point)

		return point_tier


class IntervalTierTGTConvert(TextgridConverter[IntervalTier, tgt.core.IntervalTier]):
	@override
	def to_textgrid(self, to_convert: IntervalTier) -> tgt.core.IntervalTier:
		"""
		Converts an IntervalTier object to a tgt.core.IntervalTier object.

		Args:
			to_convert (IntervalTier): The IntervalTier instance to convert.

		Returns:
			tgt.core.IntervalTier: The equivalent tgt.core.IntervalTier with intervals copied over.
		"""

		tgt_tier = tgt.core.IntervalTier(
			to_convert.get_start_time(),
			to_convert.get_end_time(),
			to_convert.get_name(),
		)

		for interval in to_convert.get_elements():
			tgt_interval = tgt.core.Interval(
				interval.start_time, interval.end_time, interval.get_name()
			)
			tgt_tier.add_interval(tgt_interval)

		return tgt_tier

	@override
	def from_textgrid(self, convert_from: tgt.core.IntervalTier) -> IntervalTier:
		"""
		Creates an IntervalTier object from a tgt.core.IntervalTier object.

		Args:
			convert_from (tgt.core.IntervalTier): The tgt.core.IntervalTier to convert.

		Returns:
			IntervalTier: A new IntervalTier instance containing intervals from the tgt.core.IntervalTier.
		"""

		interval_tier = IntervalTier(
			convert_from.name, convert_from.start_time, convert_from.end_time, self
		)

		for el in convert_from.intervals:
			interval = IntervalMarker.new_interval(el.start_time, el.end_time, el.text)
			interval_tier.add_element(interval)

		return interval_tier


class TextgridTGTConvert(TextgridConverter[TextGrid, tgt.core.TextGrid]):
	valid_tier_types: dict[str, TextgridConverter[Union[IntervalTier, PointTier], Any]]
	linked_plot: Any

	def __init__(self, linked_plot: Union[pg.PlotItem, pg.ImageItem]):
		self.valid_tier_types = {}
		self.linked_plot = linked_plot

		self.valid_tier_types["IntervalTier"] = IntervalTierTGTConvert()
		self.valid_tier_types["TextTier"] = PointTierTGTConvert()

	@override
	def to_textgrid(self, textgrid: TextGrid) -> tgt.core.TextGrid:
		"""
		Converts a TextGrid object to a tgt.core.TextGrid object by converting each tier.

		Args:
			textgrid (TextGrid): The TextGrid instance to convert.

		Returns:
			tgt.core.TextGrid: The equivalent tgt.core.TextGrid with all tiers converted.
		"""

		tgt_textgrid = tgt.core.TextGrid()

		for tier in textgrid.get_tiers():
			tgt_tier = tier.to_textgrid()
			tgt_textgrid.add_tier(tgt_tier)

		return tgt_textgrid

	@override
	def from_textgrid(self, tg: tgt.core.TextGrid) -> TextGrid:
		"""
		Creates a TextGrid object from a tgt.core.TextGrid object, converting only valid tier types.

		Args:
			tg (tgt.core.TextGrid): The tgt.core.TextGrid to convert.

		Returns:
			TextGrid: A new TextGrid instance containing converted tiers of valid types.
		"""

		textgrid = TextGrid(self.linked_plot, self)

		for t in tg.tiers:
			if t.tier_type() not in self.valid_tier_types:
				continue

			tier_converter = self.valid_tier_types[t.tier_type()]
			tier = tier_converter.from_textgrid(t)
			textgrid.add_tier(tier)

		return textgrid
