import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/debug_util.dart';
import 'package:nc_photos/di_container.dart';
import 'package:nc_photos/entity/album.dart';
import 'package:nc_photos/entity/album/item.dart';
import 'package:nc_photos/entity/album/provider.dart';
import 'package:nc_photos/use_case/find_file.dart';

/// Resync files inside an album with the file db
class ResyncAlbum {
  ResyncAlbum(this._c)
      : assert(require(_c)),
        assert(FindFile.require(_c));

  static bool require(DiContainer c) => true;

  Future<List<AlbumItem>> call(Account account, Album album) async {
    _log.info("[call] Resync album: ${album.name}");
    if (album.provider is! AlbumStaticProvider) {
      throw ArgumentError(
          "Resync only make sense for static albums: ${album.name}");
    }
    final items = AlbumStaticProvider.of(album).items;

    final files = await FindFile(_c)(
      account,
      items.whereType<AlbumFileItem>().map((i) => i.file.fileId!).toList(),
      onFileNotFound: (_) {},
    );
    final fileIt = files.iterator;
    var nextFile = fileIt.moveNext() ? fileIt.current : null;
    return items.map((i) {
      if (i is AlbumFileItem) {
        try {
          if (i.file.fileId! == nextFile?.fileId) {
            final newItem = i.copyWith(
              file: nextFile,
            );
            nextFile = fileIt.moveNext() ? fileIt.current : null;
            return newItem;
          } else {
            _log.warning("[call] File not found: ${logFilename(i.file.path)}");
            return i;
          }
        } catch (e, stackTrace) {
          _log.shout(
              "[call] Failed syncing file in album: ${logFilename(i.file.path)}",
              e,
              stackTrace);
          return i;
        }
      } else {
        return i;
      }
    }).toList();
  }

  final DiContainer _c;

  static final _log = Logger("use_case.resync_album.ResyncAlbum");
}