# -*- coding: utf-8 -*-
"""Bindings de bajo nivel para bassmidi.dll. Reproduccion MIDI con soundfonts SF2."""

import ctypes
from typing import Optional
from ..cargador import cargar_addon
from ..tipos import QWORD
from ..callbacks.bass import DOWNLOADPROC, BASS_FILEPROCS
from ..estructuras.addons import (
	HSOUNDFONT, BASS_MIDI_FONT, BASS_MIDI_FONTEX, BASS_MIDI_FONTEX2,
	BASS_MIDI_FONTINFO, BASS_MIDI_MARK, BASS_MIDI_EVENT, BASS_MIDI_DEVICEINFO,
)
from ..callbacks.addons import MIDIINPROC, MIDIFILTERPROC

_dll: Optional[ctypes.WinDLL] = None

def _obtener() -> ctypes.WinDLL:
	global _dll
	if _dll is None:
		_dll = cargar_addon("bassmidi")
		if _dll is None:
			raise OSError("bassmidi.dll no disponible")
		_configurar(_dll)
	return _dll

def _configurar(d: ctypes.WinDLL) -> None:
	d.BASS_MIDI_GetVersion.argtypes = []
	d.BASS_MIDI_GetVersion.restype = ctypes.c_ulong

	d.BASS_MIDI_StreamCreate.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong]
	d.BASS_MIDI_StreamCreate.restype = ctypes.c_ulong

	d.BASS_MIDI_StreamCreateFile.argtypes = [ctypes.c_int, ctypes.c_void_p, QWORD, QWORD, ctypes.c_ulong, ctypes.c_ulong]
	d.BASS_MIDI_StreamCreateFile.restype = ctypes.c_ulong

	d.BASS_MIDI_StreamCreateURL.argtypes = [ctypes.c_char_p, ctypes.c_ulong, ctypes.c_ulong, DOWNLOADPROC, ctypes.c_void_p, ctypes.c_ulong]
	d.BASS_MIDI_StreamCreateURL.restype = ctypes.c_ulong

	d.BASS_MIDI_StreamCreateFileUser.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(BASS_FILEPROCS), ctypes.c_void_p, ctypes.c_ulong]
	d.BASS_MIDI_StreamCreateFileUser.restype = ctypes.c_ulong

	try:
		d.BASS_MIDI_StreamCreateEvents.argtypes = [ctypes.POINTER(BASS_MIDI_EVENT), ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong]
		d.BASS_MIDI_StreamCreateEvents.restype = ctypes.c_ulong
	except AttributeError:
		pass

	d.BASS_MIDI_StreamGetMark.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(BASS_MIDI_MARK)]
	d.BASS_MIDI_StreamGetMark.restype = ctypes.c_int

	try:
		d.BASS_MIDI_StreamGetMarks.argtypes = [ctypes.c_ulong, ctypes.c_int, ctypes.c_ulong, ctypes.POINTER(BASS_MIDI_MARK)]
		d.BASS_MIDI_StreamGetMarks.restype = ctypes.c_ulong
	except AttributeError:
		pass

	d.BASS_MIDI_StreamSetFonts.argtypes = [ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong]
	d.BASS_MIDI_StreamSetFonts.restype = ctypes.c_int

	d.BASS_MIDI_StreamGetFonts.argtypes = [ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong]
	d.BASS_MIDI_StreamGetFonts.restype = ctypes.c_ulong

	d.BASS_MIDI_StreamLoadSamples.argtypes = [ctypes.c_ulong]
	d.BASS_MIDI_StreamLoadSamples.restype = ctypes.c_int

	d.BASS_MIDI_StreamEvent.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong]
	d.BASS_MIDI_StreamEvent.restype = ctypes.c_int

	try:
		d.BASS_MIDI_StreamEvents.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong]
		d.BASS_MIDI_StreamEvents.restype = ctypes.c_ulong
	except AttributeError:
		pass

	d.BASS_MIDI_StreamGetEvent.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong]
	d.BASS_MIDI_StreamGetEvent.restype = ctypes.c_ulong

	d.BASS_MIDI_StreamGetEvents.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(BASS_MIDI_EVENT)]
	d.BASS_MIDI_StreamGetEvents.restype = ctypes.c_ulong

	try:
		d.BASS_MIDI_StreamGetEventsEx.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(BASS_MIDI_EVENT), ctypes.c_ulong, ctypes.c_ulong]
		d.BASS_MIDI_StreamGetEventsEx.restype = ctypes.c_ulong
	except AttributeError:
		pass

	d.BASS_MIDI_StreamGetChannel.argtypes = [ctypes.c_ulong, ctypes.c_ulong]
	d.BASS_MIDI_StreamGetChannel.restype = ctypes.c_ulong

	try:
		d.BASS_MIDI_StreamGetPreset.argtypes = [ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(BASS_MIDI_FONT)]
		d.BASS_MIDI_StreamGetPreset.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		d.BASS_MIDI_StreamSetFilter.argtypes = [ctypes.c_ulong, ctypes.c_int, MIDIFILTERPROC, ctypes.c_void_p]
		d.BASS_MIDI_StreamSetFilter.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		d.BASS_MIDI_ConvertEvents.argtypes = [ctypes.c_void_p, ctypes.c_ulong, ctypes.POINTER(BASS_MIDI_EVENT), ctypes.c_ulong, ctypes.c_ulong]
		d.BASS_MIDI_ConvertEvents.restype = ctypes.c_ulong
	except AttributeError:
		pass

	# Soundfonts
	d.BASS_MIDI_FontInit.argtypes = [ctypes.c_void_p, ctypes.c_ulong]
	d.BASS_MIDI_FontInit.restype = HSOUNDFONT

	try:
		d.BASS_MIDI_FontInitUser.argtypes = [ctypes.POINTER(BASS_FILEPROCS), ctypes.c_void_p, ctypes.c_ulong]
		d.BASS_MIDI_FontInitUser.restype = HSOUNDFONT
	except AttributeError:
		pass

	d.BASS_MIDI_FontFree.argtypes = [HSOUNDFONT]
	d.BASS_MIDI_FontFree.restype = ctypes.c_int

	d.BASS_MIDI_FontGetInfo.argtypes = [HSOUNDFONT, ctypes.POINTER(BASS_MIDI_FONTINFO)]
	d.BASS_MIDI_FontGetInfo.restype = ctypes.c_int

	d.BASS_MIDI_FontGetPreset.argtypes = [HSOUNDFONT, ctypes.c_int, ctypes.c_int]
	d.BASS_MIDI_FontGetPreset.restype = ctypes.c_char_p

	try:
		d.BASS_MIDI_FontGetPresets.argtypes = [HSOUNDFONT, ctypes.POINTER(ctypes.c_int)]
		d.BASS_MIDI_FontGetPresets.restype = ctypes.c_int
	except AttributeError:
		pass

	d.BASS_MIDI_FontLoad.argtypes = [HSOUNDFONT, ctypes.c_int, ctypes.c_int]
	d.BASS_MIDI_FontLoad.restype = ctypes.c_int

	try:
		d.BASS_MIDI_FontLoadEx.argtypes = [HSOUNDFONT, ctypes.c_int, ctypes.c_int, ctypes.c_ulong]
		d.BASS_MIDI_FontLoadEx.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		d.BASS_MIDI_FontUnload.argtypes = [HSOUNDFONT, ctypes.c_int, ctypes.c_int]
		d.BASS_MIDI_FontUnload.restype = ctypes.c_int
	except AttributeError:
		pass

	d.BASS_MIDI_FontCompact.argtypes = [HSOUNDFONT]
	d.BASS_MIDI_FontCompact.restype = ctypes.c_int

	d.BASS_MIDI_FontPack.argtypes = [HSOUNDFONT, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_ulong]
	d.BASS_MIDI_FontPack.restype = ctypes.c_int

	d.BASS_MIDI_FontUnpack.argtypes = [HSOUNDFONT, ctypes.c_void_p, ctypes.c_ulong]
	d.BASS_MIDI_FontUnpack.restype = ctypes.c_int

	d.BASS_MIDI_FontSetVolume.argtypes = [HSOUNDFONT, ctypes.c_float]
	d.BASS_MIDI_FontSetVolume.restype = ctypes.c_int

	d.BASS_MIDI_FontGetVolume.argtypes = [HSOUNDFONT]
	d.BASS_MIDI_FontGetVolume.restype = ctypes.c_float

	try:
		d.BASS_MIDI_FontFlags.argtypes = [HSOUNDFONT, ctypes.c_ulong, ctypes.c_ulong]
		d.BASS_MIDI_FontFlags.restype = ctypes.c_ulong
	except AttributeError:
		pass

	# MIDI Input
	try:
		d.BASS_MIDI_InGetDeviceInfo.argtypes = [ctypes.c_ulong, ctypes.POINTER(BASS_MIDI_DEVICEINFO)]
		d.BASS_MIDI_InGetDeviceInfo.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		d.BASS_MIDI_InInit.argtypes = [ctypes.c_ulong, MIDIINPROC, ctypes.c_void_p]
		d.BASS_MIDI_InInit.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		d.BASS_MIDI_InFree.argtypes = [ctypes.c_ulong]
		d.BASS_MIDI_InFree.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		d.BASS_MIDI_InStart.argtypes = [ctypes.c_ulong]
		d.BASS_MIDI_InStart.restype = ctypes.c_int
	except AttributeError:
		pass

	try:
		d.BASS_MIDI_InStop.argtypes = [ctypes.c_ulong]
		d.BASS_MIDI_InStop.restype = ctypes.c_int
	except AttributeError:
		pass

class BassMidiAPI:
	"""Proxy de acceso a bassmidi.dll."""
	def __getattr__(self, nombre: str):
		return getattr(_obtener(), nombre)

bassmidi = BassMidiAPI()
