import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:manager_api/api.dart'; import 'package:mymuseum_visitapp/Helpers/DatabaseHelper.dart'; import 'package:mymuseum_visitapp/Helpers/modelsHelper.dart'; import 'package:mymuseum_visitapp/Models/resourceModel.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; import 'package:mymuseum_visitapp/Services/apiService.dart'; import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/constants.dart'; class DownloadConfiguration { static Future> download(BuildContext buildContext, AppContext appContext, ConfigurationDTO configuration) async { VisitAppContext visitAppContext = (appContext.getContext() as VisitAppContext); bool isAllLanguages = false; List audiosNotWorking = []; if(visitAppContext.isAllLanguages != null) { isAllLanguages = visitAppContext.isAllLanguages!; if(isAllLanguages) { print("Admin here and all download all audios !"); ScaffoldMessenger.of(buildContext).showSnackBar( const SnackBar( content: Text("Tous les audios vont être téléchargés"), backgroundColor: kMainColor), ); } } print("Start export configuration to store it locally"); ExportConfigurationDTO? exportConfigurationDTO; try{ exportConfigurationDTO = await ApiService.exportConfiguration(appContext.clientAPI, configuration.id!, isAllLanguages ? null : visitAppContext.language!); } catch(e) { print("Erreur lors du téléchargement de la visite"); print(e); } if(exportConfigurationDTO != null) { // Delete all from local DB ref to this configurationId then add it all await DatabaseHelper.instance.insert(DatabaseTableType.configurations, ModelsHelper.configurationToMap(configuration)); List usedImageOrAudioIds = []; var currentLanguage = (appContext.getContext() as VisitAppContext).language; if(configuration.imageId != null) { usedImageOrAudioIds.add(configuration.imageId!); var imageData = exportConfigurationDTO.resources!.where((element) => element.id == configuration.imageId); if(imageData.isNotEmpty) { ResourceModel resourceModel = ResourceModel(id: imageData.first.id, source: configuration.imageSource, /*data: imageData.first.data,*/ type: imageData.first.type); try { await DatabaseHelper.instance.insert(DatabaseTableType.resources, resourceModel.toMap()); } catch (e) { print("We got an issue inserting image data ${imageData.first.id}"); } } } List? sections = exportConfigurationDTO.sections; if(sections!.isNotEmpty) { List sectionsInDB = await DatabaseHelper.instance.queryWithConfigurationId(DatabaseTableType.sections, configuration.id!); List sectionsToKeep = sections.where((s) => s.type == SectionType.Article || s.type == SectionType.Quizz).toList(); // TODO handle other type of section (for now, Article and Quizz) sectionsToKeep.sort((a,b) => a.order!.compareTo(b.order!)); int newOrder = 0; // Update local DB - Sections for(var section in sectionsToKeep) { section.order = newOrder; try { await DatabaseHelper.instance.insert(DatabaseTableType.sections, ModelsHelper.sectionToMap(section)); } catch (e) { print("We got an issue inserting section data ${section.id}"); } // Download section image if(section.imageId != null) { usedImageOrAudioIds.add(section.imageId!); var imageData = exportConfigurationDTO.resources!.where((element) => element.id == section.imageId); if(imageData.isNotEmpty) { // TODO get all resources from API + store it in download directory of the app ResourceModel resourceModel = ResourceModel(id: imageData.first.id, source: section.imageSource, /*data: imageData.first.data,*/ type: imageData.first.type); try { await DatabaseHelper.instance.insert(DatabaseTableType.resources, resourceModel.toMap()); } catch (e) { print("We got an issue inserting image data ${imageData.first.id}"); } } } // Download all images.. ArticleDTO? articleDTO = ArticleDTO.fromJson(jsonDecode(section.data!)); if(articleDTO != null) { for(var image in articleDTO.contents!) { usedImageOrAudioIds.add(image.resourceId!); var imageData = exportConfigurationDTO.resources!.where((element) => element.id == image.resourceId); if(imageData.isNotEmpty) { // TODO get all resources from API + store it in download directory of the app ResourceModel resourceModel = ResourceModel(id: imageData.first.id, source: image.resourceUrl, /*data: imageData.first.data,*/ type: imageData.first.type); try { await DatabaseHelper.instance.insert(DatabaseTableType.resources, resourceModel.toMap()); } catch (e) { print("We got an issue inserting image data ${imageData.first.id}"); } } } var audioIdsArticle = isAllLanguages ? articleDTO.audioIds! : articleDTO.audioIds!.where((audioId) => audioId.language == currentLanguage); for(var audioId in audioIdsArticle) { if(audioId.value != null) { usedImageOrAudioIds.add(audioId.value!); audiosNotWorking = await importAudio(visitAppContext, exportConfigurationDTO, audioId.value!, audiosNotWorking); } } } newOrder = newOrder + 1; } List sectionIdsToRemove = sectionsInDB.map((s) => s.id).where((sectionId) => !sectionsToKeep.map((sk) => sk.id).contains(sectionId)).toList(); for(var sectionIdToRemove in sectionIdsToRemove) { print("section with id removed"); print(sectionIdToRemove); try { await DatabaseHelper.instance.delete(sectionIdToRemove!, DatabaseTableType.sections); } catch (e) { print("We got an issue deleting section id: ${sectionIdToRemove}"); } } cleanLocalResources(usedImageOrAudioIds, configuration); } } return audiosNotWorking; } } Future> importAudio(VisitAppContext visitAppContext, ExportConfigurationDTO exportConfigurationDTO, String audioId, List audiosNotWorking) async { var audioData = exportConfigurationDTO.resources!.where((element) => element.id == audioId); if(audioData.isNotEmpty) { // TODO get all resources from API + store it in download directory of the app ResourceModel resourceModel = ResourceModel(id: audioData.first.id, source: "", /*data: audioData.first.data,*/ type: audioData.first.type); try { await DatabaseHelper.instance.insert(DatabaseTableType.resources, resourceModel.toMap()); return audiosNotWorking; } catch (e) { print("We got an issue inserting audio data ${audioData.first.id}"); resourceModel.label = audioData.first.label; print(resourceModel.label); // Update context with not working audios //VisitAppContext visitAppContext = appContext.getContext() as VisitAppContext; audiosNotWorking.add(resourceModel); audiosNotWorking = audiosNotWorking.toSet().toList(); // Remove duplicates // appContext.setContext(visitAppContext); return audiosNotWorking; } } return audiosNotWorking; } void cleanLocalResources(List usedImageIds, ConfigurationDTO configuration) async { List> resourcesInDB = await DatabaseHelper.instance.queryAllRows(DatabaseTableType.resources); List resourcesModel = []; for(var resource in resourcesInDB) { resourcesModel.add(DatabaseHelper.instance.getResourceFromDB(resource)); } List resourceIdsToRemove = resourcesModel.map((r) => r.id).where((resourceId) => !usedImageIds.contains(resourceId)).toList(); for(var resourceIdToRemove in resourceIdsToRemove) { print("resource with id removed ________________ !!!!!"); print(resourceIdToRemove); try { await DatabaseHelper.instance.delete(resourceIdToRemove!, DatabaseTableType.resources); } catch (e) { print("We got an issue deleting resource id: ${resourceIdToRemove}"); } } }