import 'package:flutter/foundation.dart'; import '../modelos/preset_ecualizador.dart'; import '../servicios/servicio_audio.dart'; import '../servicios/servicio_ecualizador.dart'; /// Equalizer state extracted from `EstadoRadio` (S4-R1). /// /// Owns the main preset, the per-station preset map, the current (applied) /// preset and the enabled flag, plus their persistence through /// [ServicioEcualizador] and their application through [ServicioAudio]. /// Notifies ONLY its own listeners — EQ changes must not rebuild /// `EstadoRadio` consumers (S4-R1-A, S4-R5). class EstadoEcualizador extends ChangeNotifier { EstadoEcualizador({ required this.audio, ServicioEcualizador? servicio, String? Function()? emisoraActualUuid, }) : servicio = servicio ?? ServicioEcualizador(), _emisoraActualUuid = emisoraActualUuid ?? (() => null); final ServicioAudio audio; final ServicioEcualizador servicio; /// Callback into the owner (EstadoRadio) for the currently playing station; /// keeps this notifier free of any station-list coupling. final String? Function() _emisoraActualUuid; final Map _presetsEmisoraMap = {}; PresetEcualizador _presetPrincipal = PresetEcualizador.flat; PresetEcualizador _presetActual = PresetEcualizador.flat; bool _activo = true; PresetEcualizador get presetActual => _presetActual; PresetEcualizador get presetPrincipal => _presetPrincipal; bool get activo => _activo; bool get disponible => audio.ecualizadorDisponible; Map get presetsPorEmisora => Map.unmodifiable(_presetsEmisoraMap); bool get emisoraActualTienePresetPropio { final uuid = _emisoraActualUuid(); if (uuid == null) return false; return tienePresetPorEmisora(uuid); } bool tienePresetPorEmisora(String uuid) => _presetsEmisoraMap.containsKey(uuid); PresetEcualizador? presetPorEmisora(String uuid) => _presetsEmisoraMap[uuid]; PresetEcualizador presetParaEmisora(String uuid) => _presetsEmisoraMap[uuid] ?? _presetPrincipal; /// Loads the persisted EQ configuration and applies it to the audio engine. Future cargarPersistido() async { try { final config = await servicio.cargar(); _presetPrincipal = config.principal; _presetActual = config.principal; _activo = config.activo; _presetsEmisoraMap ..clear() ..addAll(config.porEmisora); await audio.setEcualizadorActivo(_activo); await audio.aplicarPreset(_presetPrincipal); } catch (_) { _presetPrincipal = PresetEcualizador.flat; _presetActual = PresetEcualizador.flat; _activo = true; _presetsEmisoraMap.clear(); } } /// Applies [preset] to the audio engine and tracks it as current /// WITHOUT persisting it (used when switching stations). Future aplicarPresetActivo(PresetEcualizador preset) async { _presetActual = preset; await audio.aplicarPreset(preset); } Future cambiarPresetPrincipal( PresetEcualizador preset, { bool notificar = true, }) async { _presetPrincipal = preset; await servicio.guardarPrincipal(preset); final uuid = _emisoraActualUuid(); final puedeAplicarAhora = uuid == null || !_presetsEmisoraMap.containsKey(uuid); if (puedeAplicarAhora) { await aplicarPresetActivo(preset); } if (notificar) notifyListeners(); } Future guardarPresetPorEmisora( String uuid, PresetEcualizador preset, { bool notificar = true, }) async { _presetsEmisoraMap[uuid] = preset; await servicio.guardarPorEmisora(uuid, preset); if (_emisoraActualUuid() == uuid) { await aplicarPresetActivo(preset); } if (notificar) notifyListeners(); } Future habilitarPresetPorEmisora( String uuid, { PresetEcualizador? base, bool notificar = true, }) async { final presetBase = base ?? _presetsEmisoraMap[uuid] ?? _presetPrincipal; await guardarPresetPorEmisora(uuid, presetBase, notificar: notificar); } Future deshabilitarPresetPorEmisora( String uuid, { bool notificar = true, }) async { _presetsEmisoraMap.remove(uuid); await servicio.eliminarPorEmisora(uuid); if (_emisoraActualUuid() == uuid) { await aplicarPresetActivo(_presetPrincipal); } if (notificar) notifyListeners(); } Future cambiarModoEmisoraActual({required bool usarPropio}) async { final uuid = _emisoraActualUuid(); if (uuid == null) return; if (usarPropio) { await habilitarPresetPorEmisora(uuid); } else { await deshabilitarPresetPorEmisora(uuid); } } Future cambiarActivo(bool activo) async { _activo = activo; await servicio.guardarActivo(activo); await audio.setEcualizadorActivo(activo); if (activo) { await audio.aplicarPreset(_presetActual); } notifyListeners(); } Future cambiarPreset( PresetEcualizador preset, { bool guardarPorEmisora = true, }) async { final uuid = _emisoraActualUuid(); final usarPresetPropio = guardarPorEmisora && uuid != null && _presetsEmisoraMap.containsKey(uuid); if (usarPresetPropio) { await guardarPresetPorEmisora(uuid, preset); return; } await cambiarPresetPrincipal(preset); } Future cambiarBanda(int index, double db) async { final bandas = List.from(_presetActual.bandas); if (index < 0 || index >= bandas.length) return; bandas[index] = db; final modificado = PresetEcualizador( nombre: 'Personalizado', bandas: bandas, ); await cambiarPreset(modificado); } /// Replaces the whole EQ configuration (backup import path): persists it, /// re-applies the preset effective for the current station and notifies. Future importarConfiguracion({ required PresetEcualizador principal, required Map porEmisora, }) async { _presetPrincipal = principal; _presetsEmisoraMap ..clear() ..addAll(porEmisora); await servicio.guardarConfiguracion( ConfiguracionEcualizador( principal: _presetPrincipal, porEmisora: _presetsEmisoraMap, activo: _activo, ), ); final uuid = _emisoraActualUuid(); await aplicarPresetActivo( uuid == null ? _presetPrincipal : presetParaEmisora(uuid), ); notifyListeners(); } }