import 'dart:ui' as ui; import 'package:dio/dio.dart'; import 'package:flame/components.dart'; import 'package:flutter/foundation.dart'; import '../config.dart'; /// بارگذاریِ تصاویرِ کارت از backend (نه bundle داخل اپ) تا حجم اپ کم بماند. /// هر اسکین یک پوشه روی سرور دارد: `/cards//.png` و `/cards//back.jpg`. /// تصاویرِ دانلودشده در حافظه کش می‌شوند تا هر کارت فقط یک‌بار از شبکه بیاید. class CardImages { CardImages._(); static const _fallbackSkin = 'simple'; static final Dio _dio = Dio(BaseOptions( responseType: ResponseType.bytes, connectTimeout: const Duration(seconds: 10), receiveTimeout: const Duration(seconds: 12), validateStatus: (s) => s != null && s >= 200 && s < 300, )); static final Map> _cache = {}; static String _url(String skin, String file) => '${AppConfig.baseUrl}/cards/$skin/$file'; /// اسپرایتِ رویِ یک کارت (مثل "AS"). در صورت خطا/۴۰۴ به اسکینِ پیش‌فرض و /// سپس به `null` (کشیدنِ برداری در CardComponent) برمی‌گردد. static Future front(String skin, String code) => _load(skin, '$code.png'); /// اسپرایتِ پشتِ کارت برای اسکین داده‌شده. static Future back(String skin) => _load(skin, 'back.jpg'); static Future _load(String skin, String file) { final key = '$skin/$file'; return _cache.putIfAbsent(key, () => _fetch(skin, file)); } static Future _fetch(String skin, String file) async { final sprite = await _fetchFrom(skin, file); if (sprite != null) return sprite; if (skin != _fallbackSkin) return _fetchFrom(_fallbackSkin, file); return null; } static Future _fetchFrom(String skin, String file) async { try { final res = await _dio.get>(_url(skin, file)); final data = res.data; if (data == null || data.isEmpty) return null; final image = await _decode(Uint8List.fromList(data)); return Sprite(image); } catch (e) { debugPrint('CardImages: $skin/$file failed: $e'); return null; } } /// تصویرِ فرش (برای سطحِ میز) از URL کاملِ backend. کش‌شده با کلیدِ URL. static Future carpetByUrl(String url) { if (url.isEmpty) return Future.value(null); return _cache.putIfAbsent('carpet/$url', () async { try { final res = await _dio.get>(url); final data = res.data; if (data == null || data.isEmpty) return null; return Sprite(await _decode(Uint8List.fromList(data))); } catch (e) { debugPrint('CardImages: carpet $url failed: $e'); return null; } }); } static Future _decode(Uint8List bytes) async { final codec = await ui.instantiateImageCodec(bytes); final frame = await codec.getNextFrame(); return frame.image; } }