# -*- coding: utf-8 -*-
"""
API de alto nivel - Mezclador de canales.

Usa BASSmix para combinar multiples fuentes de audio.
"""

import ctypes
from typing import Optional

from ..dlls.bassmix import bassmix
from ..dlls.bass import bass
from ..constantes.bassmix import BASS_MIXER_NONSTOP, BASS_MIXER_BUFFER
from ..constantes.bass import BASS_STREAM_DECODE, BASS_ATTRIB_VOL, BASS_POS_BYTE
from ..excepciones import ErrorBassNativo


class Mezclador:
	"""
	Mezclador de audio de alto nivel.

	Combina multiples canales de audio en una sola salida.
	Requiere que BASS este inicializado.

	Ejemplo:
		from basskit.alto_nivel.mezclador import Mezclador
		mezclador = Mezclador()
		mezclador.crear(44100, 2)
		mezclador.agregar_canal(stream1_handle)
		mezclador.agregar_canal(stream2_handle)
		mezclador.reproducir()
	"""

	def __init__(self) -> None:
		self._handle: int = 0
		self._canales: list[int] = []

	def crear(
		self,
		frecuencia: int = 44100,
		canales: int = 2,
		flags: int = 0,
	) -> None:
		"""
		Crea el stream mezclador.

		Parametros:
			frecuencia: Frecuencia de muestreo de salida.
			canales: Numero de canales de salida.
			flags: Flags adicionales (BASS_MIXER_xxx).
		"""
		self.cerrar()
		flags_final = flags | BASS_MIXER_NONSTOP
		handle = bassmix.BASS_Mixer_StreamCreate(frecuencia, canales, flags_final)
		if handle == 0:
			codigo = bass.BASS_ErrorGetCode()
			raise ErrorBassNativo(codigo, "BASS_Mixer_StreamCreate")
		self._handle = handle

	def agregar_canal(self, canal: int, flags: int = 0) -> None:
		"""
		Agrega un canal fuente al mezclador.

		Parametros:
			canal: Handle del canal a agregar (debe ser DECODE).
			flags: Flags del canal en el mixer (BASS_MIXER_xxx).
		"""
		if self._handle == 0:
			raise RuntimeError("Mezclador no creado. Llame a crear() primero.")
		flags_final = flags | BASS_MIXER_BUFFER
		resultado = bassmix.BASS_Mixer_StreamAddChannel(self._handle, canal, flags_final)
		if resultado == 0:
			codigo = bass.BASS_ErrorGetCode()
			raise ErrorBassNativo(codigo, "BASS_Mixer_StreamAddChannel")
		self._canales.append(canal)

	def quitar_canal(self, canal: int) -> None:
		"""Quita un canal del mezclador."""
		bassmix.BASS_Mixer_ChannelRemove(canal)
		if canal in self._canales:
			self._canales.remove(canal)

	def reproducir(self, reiniciar: bool = False) -> None:
		"""Inicia la reproduccion del mezclador."""
		if self._handle == 0:
			return
		resultado = bass.BASS_ChannelPlay(self._handle, 1 if reiniciar else 0)
		if resultado == 0:
			codigo = bass.BASS_ErrorGetCode()
			raise ErrorBassNativo(codigo, "BASS_ChannelPlay")

	def pausar(self) -> None:
		"""Pausa la reproduccion."""
		if self._handle:
			bass.BASS_ChannelPause(self._handle)

	def detener(self) -> None:
		"""Detiene la reproduccion."""
		if self._handle:
			bass.BASS_ChannelStop(self._handle)

	@property
	def volumen(self) -> float:
		"""Volumen del mezclador (0.0 a 1.0)."""
		if not self._handle:
			return 0.0
		val = ctypes.c_float(0.0)
		bass.BASS_ChannelGetAttribute(self._handle, BASS_ATTRIB_VOL, ctypes.byref(val))
		return val.value

	@volumen.setter
	def volumen(self, valor: float) -> None:
		if self._handle:
			bass.BASS_ChannelSetAttribute(self._handle, BASS_ATTRIB_VOL, valor)

	@property
	def num_canales(self) -> int:
		"""Numero de canales activos en el mezclador."""
		return len(self._canales)

	def cerrar(self) -> None:
		"""Cierra el mezclador y libera recursos."""
		if self._handle != 0:
			bass.BASS_StreamFree(self._handle)
			self._handle = 0
			self._canales.clear()

	def __del__(self) -> None:
		self.cerrar()

	def __repr__(self) -> str:
		return f"<Mezclador handle={self._handle} canales={len(self._canales)}>"
