import 'package:json_annotation/json_annotation.dart'; import 'package:spotiflac_android/models/track.dart'; part 'download_item.g.dart'; enum DownloadStatus { queued, downloading, finalizing, completed, failed, skipped, } enum DownloadErrorType { unknown, notFound, rateLimit, network, permission } @JsonSerializable() class DownloadItem { final String id; final Track track; final String service; final DownloadStatus status; final double progress; final double speedMBps; final int bytesReceived; // Bytes downloaded so far final int bytesTotal; // Total bytes when the server provides content length final String? filePath; final String? error; final DownloadErrorType? errorType; final DateTime createdAt; final String? qualityOverride; // Override quality for this specific download final String? playlistName; // Playlist context for folder organization const DownloadItem({ required this.id, required this.track, required this.service, this.status = DownloadStatus.queued, this.progress = 0.0, this.speedMBps = 0.0, this.bytesReceived = 0, this.bytesTotal = 0, this.filePath, this.error, this.errorType, required this.createdAt, this.qualityOverride, this.playlistName, }); DownloadItem copyWith({ String? id, Track? track, String? service, DownloadStatus? status, double? progress, double? speedMBps, int? bytesReceived, int? bytesTotal, String? filePath, String? error, DownloadErrorType? errorType, DateTime? createdAt, String? qualityOverride, String? playlistName, }) { return DownloadItem( id: id ?? this.id, track: track ?? this.track, service: service ?? this.service, status: status ?? this.status, progress: progress ?? this.progress, speedMBps: speedMBps ?? this.speedMBps, bytesReceived: bytesReceived ?? this.bytesReceived, bytesTotal: bytesTotal ?? this.bytesTotal, filePath: filePath ?? this.filePath, error: error ?? this.error, errorType: errorType ?? this.errorType, createdAt: createdAt ?? this.createdAt, qualityOverride: qualityOverride ?? this.qualityOverride, playlistName: playlistName ?? this.playlistName, ); } String get errorMessage { if (error == null) return ''; switch (errorType) { case DownloadErrorType.notFound: return 'Song not found on any service'; case DownloadErrorType.rateLimit: return 'Service rate limit reached. Wait before retrying.'; case DownloadErrorType.network: return 'Connection failed, check your internet'; case DownloadErrorType.permission: return 'Cannot write to folder, check storage permission'; default: return error ?? 'An error occurred'; } } factory DownloadItem.fromJson(Map json) => _$DownloadItemFromJson(json); Map toJson() => _$DownloadItemToJson(this); }