import 'dart:typed_data';

import 'package:fis_vid/cache/io.dart';
import 'package:fis_vid/data_host/interface/data_host.dart';
import 'package:fis_vid/common/vid_download.dart';
import 'package:vid/us/vid_us_image.dart';
import 'package:vid/us/vid_us_image_data.dart';
import 'package:vid/us/vid_us_probe.dart';

import '../base/data_host.dart';

class VidDataHost extends VidDataHostBase {
  VidDataHost(String url) : super(url);

  VidUsImageData? _data;

  VidFileDownloadCancelToken? _downloadCancelToken;

  @override
  VidUsProbe get probe => _data!.probe;

  @override
  int get frameCount => _data == null ? -1 : _data!.imageCount;

  @override
  Future<VidUsImageData?> getData() async => _data;

  @override
  Future<VidDataHostLoadInfo?> load() async {
    final vidFileBuffer = await _loadVidFile(url);
    if (vidFileBuffer == null) return null;

    _data = VidUsImageData(vidFileBuffer);
    return VidDataHostLoadInfo(probe);
  }

  @override
  Future<VidUsImage> getFrame(int index) async {
    if (_data == null) {
      throw Exception(
          "[VidDataHost] getFrame: must call load first and data is not null.");
    }

    final frame = _data!.getImage(index);
    frameLoaded.emit(this, frame);
    return frame;
  }

  @override
  Future<void> release() async {
    try {
      _downloadCancelToken?.cancel();
    } catch (e) {}
    _data = null;
  }

  Future<Uint8List?> _loadVidFile(String url) async {
    try {
      final cachedFile = await VidNativeCache.ins.getCache(url);
      if (cachedFile != null) return cachedFile;

      _downloadCancelToken = VidFileDownloadCancelToken();
      final buffer = await VidFileDownloader.download(
        url,
        cancelToken: _downloadCancelToken,
      );
      if (buffer != null) {
        await VidNativeCache.ins.saveCache(url, buffer);
      }
      return buffer;
    } catch (e) {
      return null;
    }
  }
}