part of 'audio_effector.dart';

/// Created by Haoyi on 2022/7/12
class SoundPoolCache {
  final Soundpool _pool;

  late Cache<AudioEffect, int> _cache;

  SoundPoolCache()
      : _pool = Soundpool.fromOptions(
            options: const SoundpoolOptions(
                maxStreams: 8,
                iosOptions: SoundpoolOptionsIos(
                    audioSessionCategory: AudioSessionCategory.ambient,
                    audioSessionMode: AudioSessionMode.normal))) {
    _cache = MapCache<AudioEffect, int>.lru(
        maximumSize: 32,
        onRemoved: (streamId) {
          _pool.stop(streamId);
        });
  }

  Future<int> _loadAudio(AudioEffect audio) async {
    final assetName = "assets/audio/${audio.path}";
    final soundData = await rootBundle.load(audio.package != null
        ? "packages/${audio.package}/$assetName"
        : assetName);
    final soundId = await _pool.load(soundData);
    await _pool.setVolume(soundId: soundId, volume: 0.8);
    return soundId;
  }

  Future load(AudioEffect audio) async {
    await _cache.get(audio, ifAbsent: _loadAudio);
  }

  Future<AudioStreamControl?> play(AudioEffect audio, int repeat) async {
    final soundId = await _cache.get(audio, ifAbsent: _loadAudio);
    Log.d("soundId: $soundId");
    if (soundId != null) {
      return _pool.playWithControls(soundId, repeat: repeat);
    }
    return null;
  }

  void invalidate(AudioEffect effect) {
    _cache.invalidate(effect);
  }
}
