import 'dart:async'; // Log seviyeleri class LogLevel { final String name; const LogLevel._(this.name); static const DEBUG = LogLevel._('DEBUG'); static const INFO = LogLevel._('INFO'); static const WARNING = LogLevel._('WARNING'); static const ERROR = LogLevel._('ERROR'); @override String toString() => name; } // Global Event Sistemi class FikoYTEventSystem { static final FikoYTEventSystem _instance = FikoYTEventSystem._internal(); factory FikoYTEventSystem() { return _instance; } FikoYTEventSystem._internal(); final _eventController = StreamController.broadcast(); final Map> _subscriptions = {}; final Map _events = {}; final Map> _categoryEvents = {}; // Kategori bazlı event'ler // Loglama fonksiyonu void _log(String message, {LogLevel level = LogLevel.INFO}) { final timestamp = DateTime.now().toIso8601String(); print('[$timestamp] [${level.name}] $message'); } // Event sınıfını ekler void addEvent(FikoYTEvent event) { final eventName = event.name; final category = event.category; if (_events.containsKey(eventName)) { _log("Event '$eventName' mevcut, argümanlar birleştirildi.", level: LogLevel.DEBUG); _events[eventName]?.mergeArguments(event.arguments); } else { _events[eventName] = event; _log("Yeni event eklendi: $eventName", level: LogLevel.INFO); } // Kategoriye göre event'i ekle if (category != null) { if (!_categoryEvents.containsKey(category)) { _categoryEvents[category] = []; } _categoryEvents[category]?.add(event); _log("Kategori '$category' için event eklendi: $eventName", level: LogLevel.INFO); } } // Event gönderme void sendEvent(String eventName, [dynamic argument, String? category]) { if (!_events.containsKey(eventName)) { _log("Event '$eventName' tanımlı değil!", level: LogLevel.ERROR); throw Exception("Event '$eventName' tanımlı değil!"); } final event = _events[eventName]; if (category != null && event?.category != category) { _log("Event '$eventName' kategorisi '$category' ile uyuşmuyor!", level: LogLevel.ERROR); throw Exception("Event '$eventName' kategorisi '$category' ile uyuşmuyor!"); } event?.send(argument); } // Event dinleme StreamSubscription onEvent(String eventName, void Function(FikoYTEvent) onData, {dynamic customArgs, String? category}) { if (!_events.containsKey(eventName)) { _log("Event '$eventName' tanımlı değil!", level: LogLevel.ERROR); throw Exception("Event '$eventName' tanımlı değil!"); } final event = _events[eventName]; if (category != null && event?.category != category) { _log("Event '$eventName' kategorisi '$category' ile uyuşmuyor!", level: LogLevel.ERROR); throw Exception("Event '$eventName' kategorisi '$category' ile uyuşmuyor!"); } final subscription = _eventController.stream.where((e) => e.name == eventName).listen((event) { _log("Event tetiklendi: ${event.name}, Argüman: ${event.arguments}", level: LogLevel.DEBUG); // customArgs yalnızca bu dinleyici için geçerli olacak if (customArgs != null) { event.mergeArguments(customArgs); } // onData fonksiyonunu çağırıyoruz onData(event); }); _subscriptions[eventName] = subscription; _log("Event dinleniyor: $eventName", level: LogLevel.INFO); return subscription; } // Event duraklatma void pauseEvent(String eventName, {String? category}) { if (!_events.containsKey(eventName)) { _log("Event '$eventName' tanımlı değil!", level: LogLevel.ERROR); return; } final event = _events[eventName]; if (category != null && event?.category != category) { _log("Event '$eventName' kategorisi '$category' ile uyuşmuyor!", level: LogLevel.ERROR); return; } _subscriptions[eventName]?.pause(); _log("Event '$eventName' duraklatıldı.", level: LogLevel.INFO); } // Event'e devam ettirme void resumeEvent(String eventName, {String? category}) { if (!_events.containsKey(eventName)) { _log("Event '$eventName' tanımlı değil!", level: LogLevel.ERROR); return; } final event = _events[eventName]; if (category != null && event?.category != category) { _log("Event '$eventName' kategorisi '$category' ile uyuşmuyor!", level: LogLevel.ERROR); return; } _subscriptions[eventName]?.resume(); _log("Event '$eventName' devam ettirildi.", level: LogLevel.INFO); } // Event'i iptal etme void cancelEvent(String eventName, {String? category}) { if (!_subscriptions.containsKey(eventName)) { _log("Event '$eventName' zaten iptal edilmiş veya bulunmuyor.", level: LogLevel.WARNING); return; } final event = _events[eventName]; if (category != null && event?.category != category) { _log("Event '$eventName' kategorisi '$category' ile uyuşmuyor!", level: LogLevel.ERROR); return; } _subscriptions[eventName]?.cancel(); _subscriptions.remove(eventName); _events.remove(eventName); _log("Event '$eventName' iptal edildi ve sistemden kaldırıldı.", level: LogLevel.INFO); } // Tüm event'leri iptal etme void cancelAllEvents({String? category}) { if (category != null && _categoryEvents.containsKey(category)) { for (final event in _categoryEvents[category]!) { _subscriptions[event.name]?.cancel(); _subscriptions.remove(event.name); _events.remove(event.name); _log("Kategori '$category' içindeki event iptal edildi ve sistemden kaldırıldı.", level: LogLevel.INFO); } _categoryEvents.remove(category); } else { for (final subscription in _subscriptions.values) { subscription.cancel(); } _subscriptions.clear(); _events.clear(); _categoryEvents.clear(); _log("Tüm event'ler iptal edildi ve sistem sıfırlandı.", level: LogLevel.WARNING); } } void dispose() { _eventController.close(); cancelAllEvents(); _log("Global Event System tamamen kapatıldı.", level: LogLevel.ERROR); } } // Event veri sınıfı class FikoYTEvent { final String name; dynamic _arguments; // private variable for arguments final dynamic defaultArguments; // Varsayılan argümanlar final String? category; // Kategori // İsimli parametrelerle constructor FikoYTEvent({ required this.name, this._arguments = const {}, this.defaultArguments = const {}, this.category, }); // Getter dynamic get arguments => _arguments ?? defaultArguments; // Setter (Kopyalama işlemi ile) void mergeArguments(dynamic newArguments) { if (_arguments is Map && newArguments is Map) { _arguments = {..._arguments, ...newArguments}; } else { _arguments = newArguments; } } // Event gönderme void send(dynamic argument) { dynamic finalArguments; // Eğer o anlık bir argüman verilmişse, sadece o anlık işlemde geçerli olacak şekilde birleştirilecek if (argument != null) { finalArguments = argument is Map && _arguments is Map ? {..._arguments, ...argument} : argument; } else { finalArguments = _arguments ?? defaultArguments; } // O anlık argümanları gönderme işlemi FikoYTEventSystem()._eventController.add(FikoYTEvent( name: name, _arguments: finalArguments, category: category, // Kategori parametresi eklendi )); } }