import 'package:flutter/foundation.dart';

import '../../../core/contracts/library.dart';
import '../session/playback_target.dart';
import 'playlist.dart';


@immutable
class CrossServerPlaylistEntry {
  const CrossServerPlaylistEntry({
    required this.serverId,
    required this.serverName,
    required this.serverUrl,
    required this.token,
    required this.userId,
    required this.itemId,
    this.label = '',
    this.preloadedItem,
  });

  final String serverId;
  final String serverName;
  final String serverUrl;
  final String token;
  final String userId;
  final String itemId;
  final String label;
  final EmbyRawItem? preloadedItem;

  PlaybackServerIdentity toIdentity() => PlaybackServerIdentity(
    serverId: serverId,
    baseUrl: serverUrl,
    token: token,
    userId: userId,
    serverName: serverName,
  );

  @override
  bool operator ==(Object other) =>
      other is CrossServerPlaylistEntry &&
      other.serverId == serverId &&
      other.serverName == serverName &&
      other.serverUrl == serverUrl &&
      other.token == token &&
      other.userId == userId &&
      other.itemId == itemId &&
      other.label == label &&
      other.preloadedItem == preloadedItem;

  @override
  int get hashCode => Object.hash(
    serverId,
    serverName,
    serverUrl,
    token,
    userId,
    itemId,
    label,
    preloadedItem,
  );
}


class CrossServerPlaylist implements Playlist {
  CrossServerPlaylist({
    required List<CrossServerPlaylistEntry> sequence,
    required int initialIndex,
    bool initialPlayFromStart = false,
  }) : assert(sequence.isNotEmpty, 'cross-server sequence cannot be empty'),
       assert(initialIndex >= 0 && initialIndex < sequence.length),
       _entries = List.unmodifiable(sequence),
       _currentIndex = ValueNotifier<int>(initialIndex),
       _current = ValueNotifier<PlaylistItem>(
         _toItem(sequence[initialIndex], playFromStart: initialPlayFromStart),
       );

  final List<CrossServerPlaylistEntry> _entries;
  final ValueNotifier<PlaylistItem> _current;
  final ValueNotifier<int> _currentIndex;

  bool _disposed = false;

  @override
  ValueListenable<PlaylistItem> get current => _current;
  @override
  ValueListenable<int> get currentIndex => _currentIndex;
  @override
  int get length => _entries.length;
  @override
  bool get hasNext => _currentIndex.value < _entries.length - 1;
  @override
  bool get hasPrev => _currentIndex.value > 0;

  @override
  Future<void> next() => goTo(_currentIndex.value + 1);
  @override
  Future<void> prev() => goTo(_currentIndex.value - 1);

  @override
  Future<void> goTo(int index) async {
    if (_disposed) return;
    if (index < 0 || index >= _entries.length) return;
    if (index == _currentIndex.value) return;
    final target = _entries[index];
    _currentIndex.value = index;
    _current.value = _toItem(target);
  }

  @override
  Future<void> goToItemId(String itemId) async {
    final idx = _entries.indexWhere((e) => e.itemId == itemId);
    if (idx < 0) return;
    await goTo(idx);
  }

  static PlaylistItem _toItem(
    CrossServerPlaylistEntry e, {
    bool playFromStart = false,
  }) => PlaylistItem(
    itemId: e.itemId,
    serverId: e.serverId,
    serverIdentity: e.toIdentity(),
    displayLabel: e.label,
    playFromStart: playFromStart,
    preloadedItem: e.preloadedItem,
  );

  @override
  void dispose() {
    _disposed = true;
    _current.dispose();
    _currentIndex.dispose();
  }
}
