# -*- coding: utf-8 -*-
"""
Bindings de bajo nivel para bass.dll.

Configura argtypes y restype para todas las funciones exportadas
por bass.dll. Permite acceso directo a la API nativa de BASS.

Uso:
	from basskit.dlls.bass import bass
	version = bass.BASS_GetVersion()
"""

import ctypes
from typing import Optional

from ..cargador import cargar_bass
from ..tipos import QWORD
from ..estructuras.bass import (
	BASS_DEVICEINFO,
	BASS_INFO,
	BASS_RECORDINFO,
	BASS_SAMPLE,
	BASS_CHANNELINFO,
	BASS_3DVECTOR,
	BASS_PLUGININFO,
)
from ..callbacks.bass import (
	STREAMPROC,
	DOWNLOADPROC,
	SYNCPROC,
	DSPPROC,
	RECORDPROC,
	BASS_FILEPROCS,
)


# ─── Carga de la DLL ─────────────────────────────────────────────────
_bass: Optional[ctypes.WinDLL] = None


def _obtener_bass() -> ctypes.WinDLL:
	"""Obtiene la instancia cargada de bass.dll (con caché)."""
	global _bass
	if _bass is None:
		_bass = cargar_bass()
		_configurar_funciones(_bass)
	return _bass


def _configurar_funciones(dll: ctypes.WinDLL) -> None:
	"""Configura argtypes y restype de todas las funciones de bass.dll."""

	# ─── Configuración y versión ──────────────────────────────────
	dll.BASS_SetConfig.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
	dll.BASS_SetConfig.restype = ctypes.c_int

	dll.BASS_GetConfig.argtypes = [ctypes.c_ulong]
	dll.BASS_GetConfig.restype = ctypes.c_ulong

	dll.BASS_SetConfigPtr.argtypes = [ctypes.c_ulong, ctypes.c_void_p]
	dll.BASS_SetConfigPtr.restype = ctypes.c_int

	dll.BASS_GetConfigPtr.argtypes = [ctypes.c_ulong]
	dll.BASS_GetConfigPtr.restype = ctypes.c_void_p

	dll.BASS_GetVersion.argtypes = []
	dll.BASS_GetVersion.restype = ctypes.c_ulong

	dll.BASS_ErrorGetCode.argtypes = []
	dll.BASS_ErrorGetCode.restype = ctypes.c_int

	# ─── Dispositivos ────────────────────────────────────────────
	dll.BASS_GetDeviceInfo.argtypes = [ctypes.c_ulong, ctypes.POINTER(BASS_DEVICEINFO)]
	dll.BASS_GetDeviceInfo.restype = ctypes.c_int

	dll.BASS_Init.argtypes = [ctypes.c_int, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_void_p]
	dll.BASS_Init.restype = ctypes.c_int

	dll.BASS_SetDevice.argtypes = [ctypes.c_ulong]
	dll.BASS_SetDevice.restype = ctypes.c_int

	dll.BASS_GetDevice.argtypes = []
	dll.BASS_GetDevice.restype = ctypes.c_ulong

	dll.BASS_Free.argtypes = []
	dll.BASS_Free.restype = ctypes.c_int

	dll.BASS_GetInfo.argtypes = [ctypes.POINTER(BASS_INFO)]
	dll.BASS_GetInfo.restype = ctypes.c_int

	# ─── Control general ─────────────────────────────────────────
	dll.BASS_Update.argtypes = [ctypes.c_ulong]
	dll.BASS_Update.restype = ctypes.c_int

	dll.BASS_GetCPU.argtypes = []
	dll.BASS_GetCPU.restype = ctypes.c_float

	dll.BASS_Start.argtypes = []
	dll.BASS_Start.restype = ctypes.c_int

	dll.BASS_Stop.argtypes = []
	dll.BASS_Stop.restype = ctypes.c_int

	dll.BASS_Pause.argtypes = []
	dll.BASS_Pause.restype = ctypes.c_int

	try:
		dll.BASS_IsStarted.argtypes = []
		dll.BASS_IsStarted.restype = ctypes.c_ulong
	except AttributeError:
		pass

	dll.BASS_SetVolume.argtypes = [ctypes.c_float]
	dll.BASS_SetVolume.restype = ctypes.c_int

	dll.BASS_GetVolume.argtypes = []
	dll.BASS_GetVolume.restype = ctypes.c_float

	# ─── Plugins ─────────────────────────────────────────────────
	dll.BASS_PluginLoad.argtypes = [ctypes.c_char_p, ctypes.c_ulong]
	dll.BASS_PluginLoad.restype = ctypes.c_ulong

	dll.BASS_PluginFree.argtypes = [ctypes.c_ulong]
	dll.BASS_PluginFree.restype = ctypes.c_int

	dll.BASS_PluginGetInfo.argtypes = [ctypes.c_ulong]
	dll.BASS_PluginGetInfo.restype = ctypes.POINTER(BASS_PLUGININFO)

	try:
		dll.BASS_PluginEnable.argtypes = [ctypes.c_ulong, ctypes.c_int]
		dll.BASS_PluginEnable.restype = ctypes.c_int
	except AttributeError:
		pass  # No disponible en todas las versiones

	# ─── 3D ──────────────────────────────────────────────────────
	dll.BASS_Set3DFactors.argtypes = [ctypes.c_float, ctypes.c_float, ctypes.c_float]
	dll.BASS_Set3DFactors.restype = ctypes.c_int

	dll.BASS_Get3DFactors.argtypes = [
		ctypes.POINTER(ctypes.c_float),
		ctypes.POINTER(ctypes.c_float),
		ctypes.POINTER(ctypes.c_float),
	]
	dll.BASS_Get3DFactors.restype = ctypes.c_int

	dll.BASS_Set3DPosition.argtypes = [
		ctypes.POINTER(BASS_3DVECTOR),
		ctypes.POINTER(BASS_3DVECTOR),
		ctypes.POINTER(BASS_3DVECTOR),
		ctypes.POINTER(BASS_3DVECTOR),
	]
	dll.BASS_Set3DPosition.restype = ctypes.c_int

	dll.BASS_Get3DPosition.argtypes = [
		ctypes.POINTER(BASS_3DVECTOR),
		ctypes.POINTER(BASS_3DVECTOR),
		ctypes.POINTER(BASS_3DVECTOR),
		ctypes.POINTER(BASS_3DVECTOR),
	]
	dll.BASS_Get3DPosition.restype = ctypes.c_int

	dll.BASS_Apply3D.argtypes = []
	dll.BASS_Apply3D.restype = None

	# ─── Muestras ────────────────────────────────────────────────
	dll.BASS_SampleLoad.argtypes = [ctypes.c_int, ctypes.c_void_p, QWORD, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong]
	dll.BASS_SampleLoad.restype = ctypes.c_ulong

	dll.BASS_SampleCreate.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong]
	dll.BASS_SampleCreate.restype = ctypes.c_ulong

	dll.BASS_SampleFree.argtypes = [ctypes.c_ulong]
	dll.BASS_SampleFree.restype = ctypes.c_int

	dll.BASS_SampleSetData.argtypes = [ctypes.c_ulong, ctypes.c_void_p]
	dll.BASS_SampleSetData.restype = ctypes.c_int

	dll.BASS_SampleGetData.argtypes = [ctypes.c_ulong, ctypes.c_void_p]
	dll.BASS_SampleGetData.restype = ctypes.c_int

	dll.BASS_SampleGetInfo.argtypes = [ctypes.c_ulong, ctypes.POINTER(BASS_SAMPLE)]
	dll.BASS_SampleGetInfo.restype = ctypes.c_int

	dll.BASS_SampleSetInfo.argtypes = [ctypes.c_ulong, ctypes.POINTER(BASS_SAMPLE)]
	dll.BASS_SampleSetInfo.restype = ctypes.c_int

	dll.BASS_SampleGetChannel.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
	dll.BASS_SampleGetChannel.restype = ctypes.c_ulong

	dll.BASS_SampleGetChannels.argtypes = [ctypes.c_ulong, ctypes.POINTER(ctypes.c_ulong)]
	dll.BASS_SampleGetChannels.restype = ctypes.c_ulong

	dll.BASS_SampleStop.argtypes = [ctypes.c_ulong]
	dll.BASS_SampleStop.restype = ctypes.c_int

	# ─── Streams ─────────────────────────────────────────────────
	dll.BASS_StreamCreate.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, STREAMPROC, ctypes.c_void_p]
	dll.BASS_StreamCreate.restype = ctypes.c_ulong

	dll.BASS_StreamCreateFile.argtypes = [ctypes.c_int, ctypes.c_void_p, QWORD, QWORD, ctypes.c_ulong]
	dll.BASS_StreamCreateFile.restype = ctypes.c_ulong

	dll.BASS_StreamCreateURL.argtypes = [ctypes.c_char_p, ctypes.c_ulong, ctypes.c_ulong, DOWNLOADPROC, ctypes.c_void_p]
	dll.BASS_StreamCreateURL.restype = ctypes.c_ulong

	dll.BASS_StreamCreateFileUser.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(BASS_FILEPROCS), ctypes.c_void_p]
	dll.BASS_StreamCreateFileUser.restype = ctypes.c_ulong

	dll.BASS_StreamFree.argtypes = [ctypes.c_ulong]
	dll.BASS_StreamFree.restype = ctypes.c_int

	dll.BASS_StreamGetFilePosition.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
	dll.BASS_StreamGetFilePosition.restype = QWORD

	dll.BASS_StreamPutData.argtypes = [ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong]
	dll.BASS_StreamPutData.restype = ctypes.c_ulong

	dll.BASS_StreamPutFileData.argtypes = [ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong]
	dll.BASS_StreamPutFileData.restype = ctypes.c_ulong

	try:
		dll.BASS_StreamCancel.argtypes = [ctypes.c_ulong]
		dll.BASS_StreamCancel.restype = ctypes.c_int
	except AttributeError:
		pass

	# ─── Música MOD ──────────────────────────────────────────────
	dll.BASS_MusicLoad.argtypes = [ctypes.c_int, ctypes.c_void_p, QWORD, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong]
	dll.BASS_MusicLoad.restype = ctypes.c_ulong

	dll.BASS_MusicFree.argtypes = [ctypes.c_ulong]
	dll.BASS_MusicFree.restype = ctypes.c_int

	# ─── Grabación ───────────────────────────────────────────────
	dll.BASS_RecordGetDeviceInfo.argtypes = [ctypes.c_ulong, ctypes.POINTER(BASS_DEVICEINFO)]
	dll.BASS_RecordGetDeviceInfo.restype = ctypes.c_int

	dll.BASS_RecordInit.argtypes = [ctypes.c_int]
	dll.BASS_RecordInit.restype = ctypes.c_int

	dll.BASS_RecordSetDevice.argtypes = [ctypes.c_ulong]
	dll.BASS_RecordSetDevice.restype = ctypes.c_int

	dll.BASS_RecordGetDevice.argtypes = []
	dll.BASS_RecordGetDevice.restype = ctypes.c_ulong

	dll.BASS_RecordFree.argtypes = []
	dll.BASS_RecordFree.restype = ctypes.c_int

	dll.BASS_RecordGetInfo.argtypes = [ctypes.POINTER(BASS_RECORDINFO)]
	dll.BASS_RecordGetInfo.restype = ctypes.c_int

	dll.BASS_RecordGetInputName.argtypes = [ctypes.c_int]
	dll.BASS_RecordGetInputName.restype = ctypes.c_char_p

	dll.BASS_RecordSetInput.argtypes = [ctypes.c_int, ctypes.c_ulong, ctypes.c_float]
	dll.BASS_RecordSetInput.restype = ctypes.c_int

	dll.BASS_RecordGetInput.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_float)]
	dll.BASS_RecordGetInput.restype = ctypes.c_ulong

	dll.BASS_RecordStart.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_void_p, ctypes.c_void_p]
	dll.BASS_RecordStart.restype = ctypes.c_ulong

	# ─── Canales ─────────────────────────────────────────────────
	dll.BASS_ChannelBytes2Seconds.argtypes = [ctypes.c_ulong, QWORD]
	dll.BASS_ChannelBytes2Seconds.restype = ctypes.c_double

	dll.BASS_ChannelSeconds2Bytes.argtypes = [ctypes.c_ulong, ctypes.c_double]
	dll.BASS_ChannelSeconds2Bytes.restype = QWORD

	dll.BASS_ChannelGetDevice.argtypes = [ctypes.c_ulong]
	dll.BASS_ChannelGetDevice.restype = ctypes.c_ulong

	dll.BASS_ChannelSetDevice.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
	dll.BASS_ChannelSetDevice.restype = ctypes.c_int

	dll.BASS_ChannelIsActive.argtypes = [ctypes.c_ulong]
	dll.BASS_ChannelIsActive.restype = ctypes.c_ulong

	dll.BASS_ChannelGetInfo.argtypes = [ctypes.c_ulong, ctypes.POINTER(BASS_CHANNELINFO)]
	dll.BASS_ChannelGetInfo.restype = ctypes.c_int

	dll.BASS_ChannelGetTags.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
	dll.BASS_ChannelGetTags.restype = ctypes.c_void_p

	dll.BASS_ChannelFlags.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong]
	dll.BASS_ChannelFlags.restype = ctypes.c_ulong

	dll.BASS_ChannelUpdate.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
	dll.BASS_ChannelUpdate.restype = ctypes.c_int

	dll.BASS_ChannelLock.argtypes = [ctypes.c_ulong, ctypes.c_int]
	dll.BASS_ChannelLock.restype = ctypes.c_int

	dll.BASS_ChannelFree.argtypes = [ctypes.c_ulong]
	dll.BASS_ChannelFree.restype = ctypes.c_int

	dll.BASS_ChannelPlay.argtypes = [ctypes.c_ulong, ctypes.c_int]
	dll.BASS_ChannelPlay.restype = ctypes.c_int

	dll.BASS_ChannelStop.argtypes = [ctypes.c_ulong]
	dll.BASS_ChannelStop.restype = ctypes.c_int

	dll.BASS_ChannelPause.argtypes = [ctypes.c_ulong]
	dll.BASS_ChannelPause.restype = ctypes.c_int

	try:
		dll.BASS_ChannelStart.argtypes = [ctypes.c_ulong]
		dll.BASS_ChannelStart.restype = ctypes.c_int
	except AttributeError:
		pass

	dll.BASS_ChannelSetAttribute.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.c_float]
	dll.BASS_ChannelSetAttribute.restype = ctypes.c_int

	dll.BASS_ChannelGetAttribute.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(ctypes.c_float)]
	dll.BASS_ChannelGetAttribute.restype = ctypes.c_int

	dll.BASS_ChannelSetAttributeEx.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong]
	dll.BASS_ChannelSetAttributeEx.restype = ctypes.c_int

	dll.BASS_ChannelGetAttributeEx.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong]
	dll.BASS_ChannelGetAttributeEx.restype = ctypes.c_ulong

	dll.BASS_ChannelSlideAttribute.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.c_float, ctypes.c_ulong]
	dll.BASS_ChannelSlideAttribute.restype = ctypes.c_int

	dll.BASS_ChannelIsSliding.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
	dll.BASS_ChannelIsSliding.restype = ctypes.c_int

	dll.BASS_ChannelSet3DAttributes.argtypes = [
		ctypes.c_ulong, ctypes.c_int, ctypes.c_float, ctypes.c_float,
		ctypes.c_int, ctypes.c_int, ctypes.c_float,
	]
	dll.BASS_ChannelSet3DAttributes.restype = ctypes.c_int

	dll.BASS_ChannelGet3DAttributes.argtypes = [
		ctypes.c_ulong,
		ctypes.POINTER(ctypes.c_ulong),
		ctypes.POINTER(ctypes.c_float),
		ctypes.POINTER(ctypes.c_float),
		ctypes.POINTER(ctypes.c_ulong),
		ctypes.POINTER(ctypes.c_ulong),
		ctypes.POINTER(ctypes.c_float),
	]
	dll.BASS_ChannelGet3DAttributes.restype = ctypes.c_int

	dll.BASS_ChannelSet3DPosition.argtypes = [
		ctypes.c_ulong,
		ctypes.POINTER(BASS_3DVECTOR),
		ctypes.POINTER(BASS_3DVECTOR),
		ctypes.POINTER(BASS_3DVECTOR),
	]
	dll.BASS_ChannelSet3DPosition.restype = ctypes.c_int

	dll.BASS_ChannelGet3DPosition.argtypes = [
		ctypes.c_ulong,
		ctypes.POINTER(BASS_3DVECTOR),
		ctypes.POINTER(BASS_3DVECTOR),
		ctypes.POINTER(BASS_3DVECTOR),
	]
	dll.BASS_ChannelGet3DPosition.restype = ctypes.c_int

	dll.BASS_ChannelGetLength.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
	dll.BASS_ChannelGetLength.restype = QWORD

	dll.BASS_ChannelSetPosition.argtypes = [ctypes.c_ulong, QWORD, ctypes.c_ulong]
	dll.BASS_ChannelSetPosition.restype = ctypes.c_int

	dll.BASS_ChannelGetPosition.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
	dll.BASS_ChannelGetPosition.restype = QWORD

	dll.BASS_ChannelGetLevel.argtypes = [ctypes.c_ulong]
	dll.BASS_ChannelGetLevel.restype = ctypes.c_ulong

	dll.BASS_ChannelGetLevelEx.argtypes = [ctypes.c_ulong, ctypes.POINTER(ctypes.c_float), ctypes.c_float, ctypes.c_ulong]
	dll.BASS_ChannelGetLevelEx.restype = ctypes.c_int

	dll.BASS_ChannelGetData.argtypes = [ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong]
	dll.BASS_ChannelGetData.restype = ctypes.c_ulong

	dll.BASS_ChannelSetSync.argtypes = [ctypes.c_ulong, ctypes.c_ulong, QWORD, SYNCPROC, ctypes.c_void_p]
	dll.BASS_ChannelSetSync.restype = ctypes.c_ulong

	dll.BASS_ChannelRemoveSync.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
	dll.BASS_ChannelRemoveSync.restype = ctypes.c_int

	dll.BASS_ChannelSetDSP.argtypes = [ctypes.c_ulong, DSPPROC, ctypes.c_void_p, ctypes.c_int]
	dll.BASS_ChannelSetDSP.restype = ctypes.c_ulong

	dll.BASS_ChannelRemoveDSP.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
	dll.BASS_ChannelRemoveDSP.restype = ctypes.c_int

	dll.BASS_ChannelSetLink.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
	dll.BASS_ChannelSetLink.restype = ctypes.c_int

	dll.BASS_ChannelRemoveLink.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
	dll.BASS_ChannelRemoveLink.restype = ctypes.c_int

	dll.BASS_ChannelSetFX.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.c_int]
	dll.BASS_ChannelSetFX.restype = ctypes.c_ulong

	dll.BASS_ChannelRemoveFX.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
	dll.BASS_ChannelRemoveFX.restype = ctypes.c_int

	try:
		dll.BASS_ChannelRef.argtypes = [ctypes.c_ulong, ctypes.c_int]
		dll.BASS_ChannelRef.restype = ctypes.c_int
	except AttributeError:
		pass

	# ─── Efectos ─────────────────────────────────────────────────
	dll.BASS_FXSetParameters.argtypes = [ctypes.c_ulong, ctypes.c_void_p]
	dll.BASS_FXSetParameters.restype = ctypes.c_int

	dll.BASS_FXGetParameters.argtypes = [ctypes.c_ulong, ctypes.c_void_p]
	dll.BASS_FXGetParameters.restype = ctypes.c_int

	dll.BASS_FXReset.argtypes = [ctypes.c_ulong]
	dll.BASS_FXReset.restype = ctypes.c_int

	try:
		dll.BASS_FXFree.argtypes = [ctypes.c_ulong]
		dll.BASS_FXFree.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_FXSetPriority.argtypes = [ctypes.c_ulong, ctypes.c_int]
		dll.BASS_FXSetPriority.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_FXSetBypass.argtypes = [ctypes.c_ulong, ctypes.c_int]
		dll.BASS_FXSetBypass.restype = ctypes.c_int
	except AttributeError:
		pass

	# ─── Funciones v0.3.0: Slide, Link, Lock ────────────────────
	try:
		dll.BASS_ChannelSlideAttribute.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.c_float, ctypes.c_ulong]
		dll.BASS_ChannelSlideAttribute.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_ChannelIsSliding.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
		dll.BASS_ChannelIsSliding.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_ChannelSetLink.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
		dll.BASS_ChannelSetLink.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_ChannelRemoveLink.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
		dll.BASS_ChannelRemoveLink.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_ChannelLock.argtypes = [ctypes.c_ulong, ctypes.c_int]
		dll.BASS_ChannelLock.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_ChannelGetDevice.argtypes = [ctypes.c_ulong]
		dll.BASS_ChannelGetDevice.restype = ctypes.c_ulong
	except AttributeError:
		pass

	try:
		dll.BASS_ChannelSetDevice.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
		dll.BASS_ChannelSetDevice.restype = ctypes.c_int
	except AttributeError:
		pass

	# ─── Funciones v0.3.0: 3D ───────────────────────────────────
	try:
		dll.BASS_ChannelGet3DAttributes.argtypes = [ctypes.c_ulong, ctypes.POINTER(ctypes.c_ulong), ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_ulong), ctypes.POINTER(ctypes.c_ulong), ctypes.POINTER(ctypes.c_float)]
		dll.BASS_ChannelGet3DAttributes.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_ChannelSet3DAttributes.argtypes = [ctypes.c_ulong, ctypes.c_int, ctypes.c_float, ctypes.c_float, ctypes.c_int, ctypes.c_int, ctypes.c_float]
		dll.BASS_ChannelSet3DAttributes.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_ChannelGet3DPosition.argtypes = [ctypes.c_ulong, ctypes.POINTER(BASS_3DVECTOR), ctypes.POINTER(BASS_3DVECTOR), ctypes.POINTER(BASS_3DVECTOR)]
		dll.BASS_ChannelGet3DPosition.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_ChannelSet3DPosition.argtypes = [ctypes.c_ulong, ctypes.POINTER(BASS_3DVECTOR), ctypes.POINTER(BASS_3DVECTOR), ctypes.POINTER(BASS_3DVECTOR)]
		dll.BASS_ChannelSet3DPosition.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_Set3DFactors.argtypes = [ctypes.c_float, ctypes.c_float, ctypes.c_float]
		dll.BASS_Set3DFactors.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_Get3DFactors.argtypes = [ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float)]
		dll.BASS_Get3DFactors.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_Set3DPosition.argtypes = [ctypes.POINTER(BASS_3DVECTOR), ctypes.POINTER(BASS_3DVECTOR), ctypes.POINTER(BASS_3DVECTOR), ctypes.POINTER(BASS_3DVECTOR)]
		dll.BASS_Set3DPosition.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_Get3DPosition.argtypes = [ctypes.POINTER(BASS_3DVECTOR), ctypes.POINTER(BASS_3DVECTOR), ctypes.POINTER(BASS_3DVECTOR), ctypes.POINTER(BASS_3DVECTOR)]
		dll.BASS_Get3DPosition.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_Apply3D.argtypes = []
		dll.BASS_Apply3D.restype = None
	except AttributeError:
		pass

	# ─── Funciones v0.3.0: Samples ──────────────────────────────
	try:
		dll.BASS_SampleCreate.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong]
		dll.BASS_SampleCreate.restype = ctypes.c_ulong
	except AttributeError:
		pass

	try:
		dll.BASS_SampleSetData.argtypes = [ctypes.c_ulong, ctypes.c_void_p]
		dll.BASS_SampleSetData.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_SampleGetData.argtypes = [ctypes.c_ulong, ctypes.c_void_p]
		dll.BASS_SampleGetData.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_SampleGetChannel.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
		dll.BASS_SampleGetChannel.restype = ctypes.c_ulong
	except AttributeError:
		pass

	try:
		dll.BASS_SampleGetChannels.argtypes = [ctypes.c_ulong, ctypes.POINTER(ctypes.c_ulong)]
		dll.BASS_SampleGetChannels.restype = ctypes.c_ulong
	except AttributeError:
		pass

	try:
		dll.BASS_SampleStop.argtypes = [ctypes.c_ulong]
		dll.BASS_SampleStop.restype = ctypes.c_int
	except AttributeError:
		pass

	# ─── Funciones v0.3.0: Stream push ──────────────────────────
	try:
		dll.BASS_StreamPutData.argtypes = [ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong]
		dll.BASS_StreamPutData.restype = ctypes.c_ulong
	except AttributeError:
		pass

	try:
		dll.BASS_StreamPutFileData.argtypes = [ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong]
		dll.BASS_StreamPutFileData.restype = ctypes.c_ulong
	except AttributeError:
		pass

	# ─── Funciones v0.3.0: FX management ────────────────────────
	try:
		dll.BASS_FXFree.argtypes = [ctypes.c_ulong]
		dll.BASS_FXFree.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_FXReset.argtypes = [ctypes.c_ulong]
		dll.BASS_FXReset.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		dll.BASS_ChannelSetDSPEx.argtypes = [ctypes.c_ulong, DSPPROC, ctypes.c_void_p, ctypes.c_int, QWORD, QWORD]
		dll.BASS_ChannelSetDSPEx.restype = ctypes.c_ulong
	except AttributeError:
		pass

	try:
		dll.BASS_ChannelGetLevelEx.argtypes = [ctypes.c_ulong, ctypes.POINTER(ctypes.c_float), ctypes.c_float, ctypes.c_ulong]
		dll.BASS_ChannelGetLevelEx.restype = ctypes.c_int
	except AttributeError:
		pass


class BassAPI:
	"""
	Proxy de acceso a las funciones de bass.dll.

	Permite acceder a todas las funciones nativas mediante atributos.
	La DLL se carga de forma perezosa en el primer acceso.

	Ejemplo:
		from basskit.dlls.bass import bass
		version = bass.BASS_GetVersion()
	"""

	def __getattr__(self, nombre: str):
		"""Delega el acceso de atributos a la DLL cargada."""
		dll = _obtener_bass()
		return getattr(dll, nombre)


# Instancia singleton para uso directo
bass = BassAPI()
