// ignore_for_file: use_build_context_synchronously import 'dart:convert'; import 'dart:math'; import 'package:filcnaplo/api/providers/user_provider.dart'; import 'package:filcnaplo/api/providers/database_provider.dart'; import 'package:filcnaplo/models/user.dart'; import 'package:filcnaplo_kreta_api/client/api.dart'; import 'package:filcnaplo_kreta_api/client/client.dart'; import 'package:filcnaplo_kreta_api/models/message.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class MessageProvider with ChangeNotifier { late List _messages; late List _recipients; late BuildContext _context; List get messages => _messages; List get recipients => _recipients; MessageProvider({ List initialMessages = const [], required BuildContext context, }) { _messages = List.castFrom(initialMessages); _recipients = []; _context = context; if (_messages.isEmpty) restore(); if (_recipients.isEmpty) restoreRecipients(); } Future restore() async { String? userId = Provider.of(_context, listen: false).id; // Load messages from the database if (userId != null) { var dbMessages = await Provider.of(_context, listen: false) .userQuery .getMessages(userId: userId); _messages = dbMessages; notifyListeners(); } } // Fetches all types of Messages Future fetchAll() => Future.forEach(MessageType.values, (MessageType v) => fetch(type: v)); // Fetches Messages from the Kreta API then stores them in the database Future fetch({MessageType type = MessageType.inbox}) async { // Check Message Type if (type == MessageType.draft) return; String messageType = ["beerkezett", "elkuldott", "torolt"].elementAt(type.index); // Check User User? user = Provider.of(_context, listen: false).user; if (user == null) throw "Cannot fetch Messages for User null"; // Get messages List? messagesJson = await Provider.of(_context, listen: false) .getAPI(KretaAPI.messages(messageType)); if (messagesJson == null) throw "Cannot fetch Messages for User ${user.id}"; // Parse messages List messages = []; await Future.wait(List.generate(messagesJson.length, (index) { return () async { Map message = messagesJson.cast()[index]; Map? messageJson = await Provider.of(_context, listen: false) .getAPI(KretaAPI.message(message["azonosito"].toString())); if (messageJson != null) { messages.add(Message.fromJson(messageJson, forceType: type)); } }(); })); await store(messages, type); } // Stores Messages in the database Future store(List messages, MessageType type) async { // Only store the specified type _messages.removeWhere((m) => m.type == type); _messages.addAll(messages); User? user = Provider.of(_context, listen: false).user; if (user == null) throw "Cannot store Messages for User null"; String userId = user.id; await Provider.of(_context, listen: false) .userStore .storeMessages(_messages, userId: userId); notifyListeners(); } // restore recipients Future restoreRecipients() async { String? userId = Provider.of(_context, listen: false).id; // Load messages from the database if (userId != null) { var dbRecipients = await Provider.of(_context, listen: false) .userQuery .getRecipients(userId: userId); _recipients = dbRecipients; notifyListeners(); } } // fetch all recipients Future fetchAllRecipients() => Future.forEach( AddresseeType.values, (AddresseeType v) => fetchRecipients(type: v)); // fetch recipients Future fetchRecipients( {AddresseeType type = AddresseeType.teachers}) async { Map addressable = {}; // check user User? user = Provider.of(_context, listen: false).user; if (user == null) throw "Cannot fetch Messages for User null"; // get categories List? availableCategoriesJson = await Provider.of(_context, listen: false) .getAPI(KretaAPI.recipientCategories); // print(availableCategoriesJson); // get recipients List? recipientTeachersJson = await Provider.of(_context, listen: false) .getAPI(KretaAPI.recipientTeachers); List? recipientDirectorateJson = await Provider.of(_context, listen: false) .getAPI(KretaAPI.recipientDirectorate); if (availableCategoriesJson == null || recipientTeachersJson == null || recipientDirectorateJson == null) { throw "Cannot fetch Recipients for User ${user.id}"; } for (var e in availableCategoriesJson) { // print(e); switch (e['kod']) { case 'TANAR': addressable .addAll({AddresseeType.teachers: SendRecipientType.fromJson(e)}); break; case 'IGAZGATOSAG': addressable.addAll( {AddresseeType.directorate: SendRecipientType.fromJson(e)}); break; default: break; } } // parse recipients List recipients = []; if (addressable.containsKey(AddresseeType.teachers) && type == AddresseeType.teachers) { recipients.addAll(recipientTeachersJson.map((e) => SendRecipient.fromJson(e, addressable[AddresseeType.teachers]!))); } if (addressable.containsKey(AddresseeType.directorate) && type == AddresseeType.directorate) { recipients.addAll(recipientDirectorateJson.map((e) => SendRecipient.fromJson(e, addressable[AddresseeType.directorate]!))); } // if (kDebugMode) { // print(addressable); // print(recipients); // print(recipients.first.json); // } await storeRecipients(recipients, type); } // store recipients Future storeRecipients( List recipients, AddresseeType type) async { _recipients.removeWhere((r) => (type == AddresseeType.teachers ? (r.type.code == 'TANAR') : (type == AddresseeType.directorate ? (r.type.code == 'IGAZGATOSAG') : r.type.code != ''))); _recipients.addAll(recipients); User? user = Provider.of(_context, listen: false).user; if (user == null) throw "Cannot store Recipients for User null"; String userId = user.id; await Provider.of(_context, listen: false) .userStore .storeRecipients(_recipients, userId: userId); notifyListeners(); } // send message Future sendMessage({ required List recipients, String subject = "Nincs tárgy", required String messageText, }) async { List recipientList = []; User? user = Provider.of(_context, listen: false).user; if (user == null) throw "Cannot send Message as User null"; // for (var r in recipients) { // recipientList.add({ // "azonosito": r.id ?? "", // "kretaAzonosito": r.kretaId ?? "", // "nev": r.name ?? "Teszt Lajos", // "tipus": { // "kod": r.type.code, // "leiras": r.type.description, // "azonosito": r.type.id, // "nev": r.type.name, // "rovidNev": r.type.shortName, // } // }); // } recipientList.addAll(recipients.map((e) => e.kretaJson)); Map body = { "cimzettLista": recipientList, "csatolmanyok": [], "azonosito": (Random().nextInt(10000) + 10000), "feladoNev": user.name, "feladoTitulus": user.role == Role.parent ? "Szülő" : "Diák", "kuldesDatum": DateTime.now().toIso8601String(), "targy": subject, "szoveg": messageText, // "elozoUzenetAzonosito": 0, }; Map headers = { "content-type": "application/json", }; var res = await Provider.of(_context, listen: false).postAPI( KretaAPI.sendMessage, autoHeader: true, json: true, body: json.encode(body), headers: headers, ); if (res!['hibakod'] == 'UzenetKuldesEngedelyRule') { return 'send_permission_error'; } return 'successfully_sent'; } }