using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using System;
using UnityEngine.Events;
using Newtonsoft.Json;
using System.Text;
using UnityEngine.UI;
using Shatalmic;
using UnityEngine.Android;
using Newtonsoft.Json.Linq;
using System.Threading.Tasks;

public enum APP_ID
{
    NONE,
    LUCIOLE,
    ELARGIR,
    EVASION,
    EVALULU,
}

public class HM_PluginController : MonoBehaviour
{
    public enum NAV_CONTEXT
    {
        NONE,
        LOT,
        LETTRE,
        NEW_TEACHER,
        SYNCHRO,
    }


    //pour lancer automatiquement le plugin sur l'écran de choix profil (lancement d'une application TRANS3). Laissez à false pour le prefab !
    public bool sceneStart = false;

    public APP_ID appID = APP_ID.NONE;//choix de l'app concernée, à modifier via Inspector

    [HideInInspector]
    public static NAV_CONTEXT navContext = NAV_CONTEXT.NONE;
    [HideInInspector]
    public int navMaxID = 0;

    public string sceneNameAfterLogin = "";
    public UnityEvent callbackSecondChildLogin;
    public UnityEvent onAppSettingCancel;
    public UnityEvent onAppSettingEnd;
    public UnityEvent<List<string>, List<string>, List<string>> onSynchroEnd;

    public List<Sprite> childAvatars = new List<Sprite>();

    public TextMeshProUGUI appName;
    public Image appImage;
    public TextMeshProUGUI appVersion;

    public List<Sprite> appsImages = new List<Sprite>();

    public bool isActive = false;
    private int isActiveCpt = 0;

    [HideInInspector]
    public Image colorDeviceInfo = null;

#if UNITY_ANDROID && !UNITY_EDITOR
    private AndroidJavaObject androidVersion = null;
#endif

    public void CheckAndroidPermissions(bool force = false)
    {
        int alreadyAsked = PlayerPrefs.GetInt("HM_BluetoothPermissions", -1);

        var callbacks = new PermissionCallbacks();
        callbacks.PermissionDenied += PermissionCallbacks_PermissionDenied;
        callbacks.PermissionGranted += PermissionCallbacks_PermissionGranted;
        callbacks.PermissionDeniedAndDontAskAgain += PermissionCallbacks_PermissionDeniedAndDontAskAgain;

        if (force || alreadyAsked <= 0)//demande de permission 
        {
#if UNITY_ANDROID && !UNITY_EDITOR
            int sdkVersion = androidVersion.GetStatic<int>("SDK_INT");
#else
            int sdkVersion = 31;
#endif

            if (sdkVersion >= 31)
            {
                if (!Permission.HasUserAuthorizedPermission("android.permission.BLUETOOTH_SCAN"))
                {
                    Permission.RequestUserPermission("android.permission.BLUETOOTH_SCAN", callbacks);
                }
                else
                {
                    if (!Permission.HasUserAuthorizedPermission("android.permission.BLUETOOTH_ADVERTISE"))
                    {
                        Permission.RequestUserPermission("android.permission.BLUETOOTH_ADVERTISE", callbacks);
                    }
                    else
                    {
                        if (!Permission.HasUserAuthorizedPermission("android.permission.BLUETOOTH_CONNECT"))
                        {
                            Permission.RequestUserPermission("android.permission.BLUETOOTH_CONNECT", callbacks);
                        }
                        else
                        {
                            PlayerPrefs.SetInt("HM_BluetoothPermissions", 2);
                        }
                    }
                }
            }
            else
            {
                if (!Permission.HasUserAuthorizedPermission("android.permission.ACCESS_FINE_LOCATION"))
                {
                    Permission.RequestUserPermission("android.permission.ACCESS_FINE_LOCATION", callbacks);
                }
                else
                {
                    if (!Permission.HasUserAuthorizedPermission("android.permission.BLUETOOTH"))
                    {
                        Permission.RequestUserPermission("android.permission.BLUETOOTH", callbacks);
                    }
                    else
                    {
                        PlayerPrefs.SetInt("HM_BluetoothPermissions", 2);
                    }
                }
            }
            
        }
    }

    public bool HasAndroidBluetoothPermissions()
    {
#if UNITY_ANDROID && !UNITY_EDITOR
            int sdkVersion = androidVersion.GetStatic<int>("SDK_INT");
#else
        int sdkVersion = 31;
#endif

        if (sdkVersion >= 31)
        {
            if (Permission.HasUserAuthorizedPermission("android.permission.BLUETOOTH_SCAN")
            && Permission.HasUserAuthorizedPermission("android.permission.BLUETOOTH_ADVERTISE")
            && Permission.HasUserAuthorizedPermission("android.permission.BLUETOOTH_CONNECT"))
            {
                return true;
            }
        }
        else
        {
            if (Permission.HasUserAuthorizedPermission("android.permission.ACCESS_FINE_LOCATION")
            && Permission.HasUserAuthorizedPermission("android.permission.BLUETOOTH"))
            {
                return true;
            }
        }

        return false;
    }


    private void PermissionCallbacks_PermissionDenied(string permissionName)
    {
        PlayerPrefs.SetInt("HM_BluetoothPermissions", 1);
    }

    private void PermissionCallbacks_PermissionGranted(string permissionName)
    {
        CheckAndroidPermissions(true);
    }

    private void PermissionCallbacks_PermissionDeniedAndDontAskAgain(string permissionName)
    {
        PlayerPrefs.SetInt("HM_BluetoothPermissions", 0);
    }

    void Awake()
    {
        HM_Scripts.Initialize();

        //HM_Model.Initialize();

#if UNITY_ANDROID && !UNITY_EDITOR
        androidVersion = new AndroidJavaObject("android.os.Build$VERSION");
        CheckAndroidPermissions();
#endif

        if (sceneStart)
        {
            HM_Log.ReplaceTextFile("HM_Log.txt", "");
            HM_Log.ReplaceTextFile("HM_LogResult.txt", "");

            //Debug.Log("Load");
            HM_Model.Load();
            HM_Scripts.optionPanel.UpdateData();
            HM_Scripts.debugPanel.buttonSwitchPanel.gameObject.SetActive(true);

        }
        else
        {
            HM_Scripts.debugPanel.buttonSwitchPanel.gameObject.SetActive(false);
        }

        isActive = false;
        isActiveCpt = 0;

        //l'appID est sensé exister dans un contexte normal. Il doit étre renseigner sur chaque instance de HM_PluginController existant dans le projet
        //(dans la scéne HM_SceneStart et sur toutes les instances prefabs utilisés dans les scénes de l'application)
        if (appID == APP_ID.NONE)
        {
            Debug.LogWarning("Un script HM_PluginController n'a pas été configuré pour une app en particulier. Merci de renseigner l'app !");
        }

        colorDeviceInfo = GameObject.Find("HM_ColorDeviceInfo").GetComponent<Image>();

        switch (HM_DataController.model.currentColorID)
        {
            case 1:
                colorDeviceInfo.color = new Color32(246, 115, 172, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "A";
                break;
            case 2:
                colorDeviceInfo.color = new Color32(155, 47, 174, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "B";
                break;
            case 3:
                colorDeviceInfo.color = new Color32(64, 84, 178, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "C";
                break;
            case 4:
                colorDeviceInfo.color = new Color32(29, 170, 241, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "D";
                break;
            case 5:
                colorDeviceInfo.color = new Color32(31, 188, 210, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "E";
                break;
            case 6:
                colorDeviceInfo.color = new Color32(80, 174, 85, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "F";
                break;
            case 7:
                colorDeviceInfo.color = new Color32(205, 218, 73, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "G";
                break;
            case 8:
                colorDeviceInfo.color = new Color32(253, 192, 47, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "H";
                break;
            case 9:
                colorDeviceInfo.color = new Color32(164, 125, 112, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "I";
                break;
            case 10:
                colorDeviceInfo.color = new Color32(97, 125, 138, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "J";
                break;
            case 11:
                colorDeviceInfo.color = new Color32(255, 140, 120, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "K";
                break;
            case 12:
                colorDeviceInfo.color = new Color32(0, 121, 135, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "L";
                break;
            case 13:
                colorDeviceInfo.color = new Color32(30, 223, 145, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "M";
                break;
            case 14:
                colorDeviceInfo.color = new Color32(201, 130, 255, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "N";
                break;
            case 15:
                colorDeviceInfo.color = new Color32(255, 49, 49, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "O";
                break;
            case 16:
                colorDeviceInfo.color = new Color32(68, 74, 255, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "P";
                break;
            case 17:
                colorDeviceInfo.color = new Color32(255, 110, 13, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "Q";
                break;
            case 18:
                colorDeviceInfo.color = new Color32(84, 67, 59, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "R";
                break;
            case 19:
                colorDeviceInfo.color = new Color32(37, 96, 58, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "S";
                break;
            case 20:
                colorDeviceInfo.color = new Color32(36, 28, 110, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "T";
                break;
            case 21:
                colorDeviceInfo.color = new Color32(168, 94, 94, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "U";
                break;
            case 22:
                colorDeviceInfo.color = new Color32(128, 94, 168, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "V";
                break;
            case 23:
                colorDeviceInfo.color = new Color32(126, 74, 74, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "W";
                break;
            case 24:
                colorDeviceInfo.color = new Color32(131, 183, 151, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "X";
                break;
            case 25:
                colorDeviceInfo.color = new Color32(226, 132, 74, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "Y";
                break;
            case 26:
                colorDeviceInfo.color = new Color32(255, 68, 212, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "Z";
                break;
            case 27:
                colorDeviceInfo.color = new Color32(127, 47, 235, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "Δ";
                break;
            case 28:
                colorDeviceInfo.color = new Color32(95, 95, 95, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "Θ";
                break;
            case 29:
                colorDeviceInfo.color = new Color32(97, 158, 196, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "Ξ";
                break;
            case 30:
                colorDeviceInfo.color = new Color32(214, 167, 113, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "Φ";
                break;
            case 31:
                colorDeviceInfo.color = new Color32(123, 53, 110, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "Ψ";
                break;
            case 32:
                colorDeviceInfo.color = new Color32(89, 96, 1, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "Ω";
                break;
            case -1:
                colorDeviceInfo.color = new Color32(200, 200, 200, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "-";
                break;
            default:
                colorDeviceInfo.color = new Color32(200, 200, 200, 255);
                colorDeviceInfo.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "-";
                break;
        }

        HM_Content.contentBackgroundCG = GameObject.FindGameObjectsWithTag("HM_ContentBackground")[0].GetComponent<CanvasGroup>();
        HM_Content.contentBackgroundCG.alpha = 0;
        HM_Content.contentBackgroundCG.interactable = false;
        HM_Content.contentBackgroundCG.blocksRaycasts = false;

        HM_Content.popupBackgroundCG = GameObject.FindGameObjectsWithTag("HM_PopupBackground")[0].GetComponent<CanvasGroup>();
        HM_Content.popupBackgroundCG.alpha = 0;
        HM_Content.popupBackgroundCG.interactable = false;
        HM_Content.popupBackgroundCG.blocksRaycasts = false;

        switch(appID)
        {
            case APP_ID.ELARGIR:
                appName.text = "Elargir";
                appImage.sprite = appsImages[0];
                break;
            case APP_ID.EVASION:
                appName.text = "Evasion";
                appImage.sprite = appsImages[1];
                break;
            case APP_ID.LUCIOLE:
                appName.text = "Luciole";
                appImage.sprite = appsImages[2];
                break;
            case APP_ID.EVALULU:
                appName.text = "EvaLulu";
                appImage.sprite = appsImages[3];
                break;
            default:
                appName.text = "APP NAME";
                appImage.sprite = null;
                break;
        }

        appVersion.text = "v" + Application.version;

        HM_Scripts.pluginController = this;

        if (!sceneStart)
        {
            StopPlugin();
        }
    }

    void Start()
    {
        if (HM_NetworkController.currentENV == HM_NetworkController.ENV.DEVELOP)
            GameObject.Find("HM_TextVersion").GetComponent<TextMeshProUGUI>().text = "v1.6.5 - DEVELOP";
        else if (HM_NetworkController.currentENV == HM_NetworkController.ENV.PREPROD)
            GameObject.Find("HM_TextVersion").GetComponent<TextMeshProUGUI>().text = "v1.6.5 - PREPROD";
        else
            GameObject.Find("HM_TextVersion").GetComponent<TextMeshProUGUI>().text = "v1.6.5 - PROD";

        HM_Scripts.optionPanel.HideButton(true);

        //si démarrage auto, on lance le contenu de choix du profil enfant
        if (sceneStart)
        {
            switch (appID)
            {
                case APP_ID.ELARGIR:
                    //tente d'envoyer les données Audio Elargir en attente (si il y en a)
                    HM_NetworkController.instance.SendAudioData();
                    break;
            }

            if (HM_DataController.model.teacherAccounts.Count == 0)
            {
                navContext = NAV_CONTEXT.NEW_TEACHER;
                HM_Scripts.contentCodeTeacher.OpenContent();
            }
            else
            {
                HM_DataController.currentChildUser = null;
                HM_DataController.currentTeacherAccount = null;

                bool synchroNeeded = false;

                foreach(HM_TeacherAccount t in HM_DataController.model.teacherAccounts)
                {
                    if(t.dataAWS._idToken != null && t.dataAWS._idToken.Length > 0)
                    {
                        synchroNeeded = true;
                        break;
                    }
                }

                if(synchroNeeded && Application.internetReachability != NetworkReachability.NotReachable)
                {
                    HM_Scripts.contentRefreshAWS.OpenContent();
                }
                else
                {
                    HM_Scripts.contentProfil.OpenContent();
                }

            }

        }
    }

    //Active le Plugin sur un contenu en particulier (ne devrait étre appelé que par le plugin lui méme)
    public void StartPlugin(HM_Content content = null)
    {
        //this.gameObject.SetActive(true);
        isActive = true;
        isActiveCpt++;

        if(content != null)
        {
            content.OpenContent();
        }
    }

    //Met en pause le Plugin (ne devrait étre appelé que par le plugin lui méme)
    public void StopPlugin()
    {
        //this.gameObject.SetActive(false);
        isActiveCpt--;

        if(isActiveCpt <= 0)
        {
            isActiveCpt = 0;
            isActive = false;

            HM_Content.contentBackgroundCG.alpha = 0;
            HM_Content.contentBackgroundCG.interactable = false;
            HM_Content.contentBackgroundCG.blocksRaycasts = false;

            HM_Content.popupBackgroundCG.alpha = 0;
            HM_Content.popupBackgroundCG.interactable = false;
            HM_Content.popupBackgroundCG.blocksRaycasts = false;
        }
    }


    public bool CheckTeacherCodeValid(string code)
    {
        //calcul checksum
        int checksum = ChecksumTeacherCode(code);

        //vérification si 6ème lettre OK
        if (code[5] == (char)('A' + checksum))
        {
            return true;
        }

        return false;
    }

    private int ChecksumTeacherCode(string code)
    {
        int checksum = 0;

        //checkum via calcul "(1 * lettre1 + 2 * lettre2 + 3 * lettre3 + 4 * lettre4 + 5 * lettre5) modulo 26"
        //lettre1~5 étant la position du caractère dans l'alphabet : A=1, B=2, ...

        for (int j = 0; j < 5; j++)
        {
            checksum += (j + 1) * (int)(code[j] - 64); //-64 pour retrouver la bonne position en partant de A=1
        }

        checksum = checksum % 26;// 0 to 25

        return checksum;
    }



    /// <summary>
    /// Les fonctions suivantes sont les points d'entrée pour utilisation de ce plugin HM
    /// </summary>

    //Démarre le Plugin sur le contenu pour identifier un profil enfant de type "évaluateur", différent du profil actuellement connecté
    //Utilisation type : Application Elargir si demande d'évaluation par un pair pour un texte
    public static void OpenLoginSecondaryChild()
    {
        //le profilID est sensé exister dans un contexte normal, car il aura été renseigné via la scéne de démarrage HM_SceneStart

        //on lance la page de choix du profil
        HM_Scripts.pluginController.StartPlugin(HM_Scripts.contentProfil);
    }

    //Démarre le Plugin sur le contenu pour identifier un professeur afin de configurer l'enfant actuellement connecté
    public static void OpenTeacherAdmin(int contextID = -1)
    {
        //l'appID est sensé exister dans un contexte normal. Il doit étre renseigner sur chaque instance de HM_PluginController existant dans le projet
        //(dans la scéne HM_SceneStart et sur toutes les instances prefabs utilisés dans les scénes de l'application)

        if(HM_Scripts.pluginController.appID == APP_ID.NONE)
        {
            Debug.LogError("Pas de paramétrage possible sans avoir indiqué l'app concernée sur le script HM_PluginController via l'Inspector");
            HM_Log.AppendTextToFile("HM_Log.txt", "OpenTeacherAdmin error : Pas de paramétrage possible sans avoir indiqué l'app concernée sur le script HM_PluginController via l'Inspector");
            return;
        }
        else if(HM_Scripts.pluginController.appID == APP_ID.EVASION || HM_Scripts.pluginController.appID == APP_ID.EVALULU)
        {
            Debug.LogError("Pas de paramétrage possible pour cette application");
            HM_Log.AppendTextToFile("HM_Log.txt", "OpenTeacherAdmin error : Pas de paramétrage possible pour cette application");
            return;
        }

        switch(HM_Scripts.pluginController.appID)
        {
            case APP_ID.ELARGIR:
                HM_ContentSettingApp_Elargir.contextID = contextID;
                break;
            case APP_ID.LUCIOLE:
                HM_ContentSettingApp_Luciole.contextID = contextID;
                break;
        }

        //le currentChildUser est sensé exister dans un contexte normal, car il aura été renseigné via la scéne de démarrage HM_SceneStart
        if (HM_DataController.currentChildUser == null)
        {
            Debug.LogError("Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            HM_Log.AppendTextToFile("HM_Log.txt", "OpenTeacherAdmin error : Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            return;
        }

        //on lance la page de demande du code enseignant
        HM_Scripts.pluginController.StartPlugin(HM_Scripts.contentCodeTeacher);
    }

    public static void DisconnectUser()
    {
        HM_Scripts.pluginController.StartPlugin(HM_Scripts.popupAlertDisconnect);
    }

    public void DeleteSaveData()
    {
        HM_DataController.model.DeleteSaveData();
    }

    public static string GetMainUserID()
    {
        if (HM_DataController.currentChildUser == null)
        {
            Debug.LogError("Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            HM_Log.AppendTextToFile("HM_Log.txt", "GetMainUserID error : Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            return "";
        }

        return HM_DataController.currentChildUser.userID;
    }

    public static string GetSecondUserID()
    {
        if (HM_DataController.secondaryChildUser == null)
        {
            Debug.LogError("Le plugin HM ne retrouve pas l'enfant secondaire actuellement connecté");
            HM_Log.AppendTextToFile("HM_Log.txt", "GetSecondUserID error : Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            return "";
        }

        return HM_DataController.secondaryChildUser.userID;
    }

    public static string GetProgression()
    {
        if (HM_DataController.currentChildUser == null)
        {
            Debug.LogError("Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            HM_Log.AppendTextToFile("HM_Log.txt", "GetProgression error : Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            return "";
        }

        if (HM_Scripts.pluginController.appID == APP_ID.NONE)
        {
            Debug.LogWarning("Un script HM_PluginController n'a pas été configuré pour une app en particulier. Merci de renseigner l'app !");
            HM_Log.AppendTextToFile("HM_Log.txt", "GetProgression error : Un script HM_PluginController n'a pas été configuré pour une app en particulier.");
            return "";
        }
        else if (HM_Scripts.pluginController.appID == APP_ID.EVALULU)
        {
            Debug.LogError("Cette application n'a pas été configuré pour utiliser cette fonction");
            HM_Log.AppendTextToFile("HM_Log.txt", "GetProgression error : Cette application n'a pas été configuré pour utiliser cette fonction");
            return "";
        }

        switch (HM_Scripts.pluginController.appID)
        {
            case APP_ID.ELARGIR:
                return JsonConvert.SerializeObject(HM_DataController.currentChildUser.appElargirUserData.progression);
            case APP_ID.LUCIOLE:
                return JsonConvert.SerializeObject(HM_DataController.currentChildUser.appLucioleUserData.progression);
            case APP_ID.EVASION:
                return JsonConvert.SerializeObject(HM_DataController.currentChildUser.appEvasionUserData.progression);
        }

        return "";
    }

    public static void SetProgression(string jsonProgression)
    {
        if(HM_DataController.currentChildUser == null)
        {
            Debug.LogError("Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            HM_Log.AppendTextToFile("HM_Log.txt", "SetProgression error : Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            return;
        }

        if (HM_Scripts.pluginController.appID == APP_ID.NONE)
        {
            Debug.LogWarning("Un script HM_PluginController n'a pas été configuré pour une app en particulier. Merci de renseigner l'app !");
            HM_Log.AppendTextToFile("HM_Log.txt", "SetProgression error : Un script HM_PluginController n'a pas été configuré pour une app en particulier.");
            return;
        }
        else if (HM_Scripts.pluginController.appID == APP_ID.EVALULU)
        {
            Debug.LogError("Cette application n'a pas été configuré pour utiliser cette fonction");
            HM_Log.AppendTextToFile("HM_Log.txt", "SetProgression error : Cette application n'a pas été configuré pour utiliser cette fonction");
            return;
        }

        try
        {
            switch (HM_Scripts.pluginController.appID)
            {
                case APP_ID.ELARGIR:
                    //cas particulier : on remet settings.difficultyMode à 0
                    HM_DataController.currentChildUser.appElargirUserData.settings.difficultyMode = 0;
                    HM_DataController.currentChildUser.appElargirUserData.settings.revisionDate = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssK");

                    HM_DataController.currentChildUser.appElargirUserData.progression = JsonConvert.DeserializeObject<HM_AppElargirUserProgression>(jsonProgression);
                    HM_DataController.currentChildUser.appElargirUserData.progression.dateUpdate = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssK");
                    break;
                case APP_ID.LUCIOLE:
                    HM_DataController.currentChildUser.appLucioleUserData.progression = JsonConvert.DeserializeObject<HM_AppLucioleUserProgression>(jsonProgression);
                    HM_DataController.currentChildUser.appLucioleUserData.progression.dateUpdate = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssK");
                    break;
                case APP_ID.EVASION:
                    HM_DataController.currentChildUser.appEvasionUserData.progression = JsonConvert.DeserializeObject<HM_AppEvasionUserProgression>(jsonProgression);
                    HM_DataController.currentChildUser.appEvasionUserData.progression.dateUpdate = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssK");
                    break;
            }
        }
        catch (Exception e)
        {
            Debug.LogError("SetProgression jsonProgression Deserialize ERROR : " + e.Message);
            HM_Log.AppendTextToFile("HM_Log.txt", "SetProgression jsonProgression Deserialize ERROR : " + e.Message);
        }

        HM_DataController.model.Save();
    }

    public static string GetSettingsSession()
    {
        if (HM_DataController.currentChildUser == null)
        {
            Debug.LogError("Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            HM_Log.AppendTextToFile("HM_Log.txt", "GetSettingsSession error : Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            return "";
        }

        if (HM_Scripts.pluginController.appID == APP_ID.NONE)
        {
            Debug.LogWarning("Un script HM_PluginController n'a pas été configuré pour une app en particulier. Merci de renseigner l'app !");
            HM_Log.AppendTextToFile("HM_Log.txt", "GetSettingsSession error : Un script HM_PluginController n'a pas été configuré pour une app en particulier.");
            return "";
        }
        else if (HM_Scripts.pluginController.appID == APP_ID.EVALULU)
        {
            Debug.LogError("Cette application n'a pas été configuré pour utiliser cette fonction");
            HM_Log.AppendTextToFile("HM_Log.txt", "GetSettingsSession error : Cette application n'a pas été configuré pour utiliser cette fonction");
            return "";
        }

        switch (HM_Scripts.pluginController.appID)
        {
            case APP_ID.ELARGIR:
                return JsonConvert.SerializeObject(HM_DataController.currentChildUser.appElargirUserData.settings);
            case APP_ID.LUCIOLE:
                return JsonConvert.SerializeObject(HM_DataController.currentChildUser.appLucioleUserData.settings);
            case APP_ID.EVASION:
                return JsonConvert.SerializeObject(HM_DataController.currentChildUser.appEvasionUserData.settings);
        }

        return "";
    }

    public static void SetSettingsSession(string jsonSettings)
    {
        if (HM_DataController.currentChildUser == null)
        {
            Debug.LogError("Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            HM_Log.AppendTextToFile("HM_Log.txt", "SetSettingsSession error : Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            return;
        }

        if (HM_Scripts.pluginController.appID == APP_ID.NONE)
        {
            Debug.LogWarning("Un script HM_PluginController n'a pas été configuré pour une app en particulier. Merci de renseigner l'app !");
            HM_Log.AppendTextToFile("HM_Log.txt", "SetSettingsSession error : Un script HM_PluginController n'a pas été configuré pour une app en particulier.");
            return;
        }
        else if (HM_Scripts.pluginController.appID == APP_ID.EVALULU)
        {
            Debug.LogError("Cette application n'a pas été configuré pour utiliser cette fonction");
            HM_Log.AppendTextToFile("HM_Log.txt", "SetSettingsSession error : Cette application n'a pas été configuré pour utiliser cette fonction");
            return;
        }

        try
        {
            switch (HM_Scripts.pluginController.appID)
            {
                case APP_ID.ELARGIR:
                    HM_DataController.currentChildUser.appElargirUserData.settings = JsonConvert.DeserializeObject<HM_AppElargirUserSettings>(jsonSettings);
                    HM_DataController.currentChildUser.appElargirUserData.settings.revisionDate = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssK");
                    break;
                case APP_ID.LUCIOLE:
                    HM_DataController.currentChildUser.appLucioleUserData.settings = JsonConvert.DeserializeObject<HM_AppLucioleUserSettings>(jsonSettings);
                    HM_DataController.currentChildUser.appLucioleUserData.settings.revisionDate = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssK");
                    break;
                case APP_ID.EVASION:
                    HM_DataController.currentChildUser.appEvasionUserData.settings = JsonConvert.DeserializeObject<HM_AppEvasionUserSettings>(jsonSettings);
                    HM_DataController.currentChildUser.appEvasionUserData.settings.revisionDate = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssK");
                    break;
            }
        }
        catch (Exception e)
        {
            Debug.LogError("SetSettingsSession jsonSettings Deserialize ERROR : " + e.Message);
            HM_Log.AppendTextToFile("HM_Log.txt", "SetSettingsSession jsonSettings Deserialize ERROR : " + e.Message);
        }

        HM_DataController.model.Save();
    }


    public static void AddResultData(string jsonProgression, float playDuration, string jsonResult)
    {
        if (HM_DataController.currentChildUser == null)
        {
            Debug.LogError("Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            HM_Log.AppendTextToFile("HM_Log.txt", "AddResultData error : Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            return;
        }

        if (HM_Scripts.pluginController.appID == APP_ID.NONE)
        {
            Debug.LogWarning("Un script HM_PluginController n'a pas été configuré pour une app en particulier. Merci de renseigner l'app !");
            HM_Log.AppendTextToFile("HM_Log.txt", "AddResultData error : Un script HM_PluginController n'a pas été configuré pour une app en particulier.");
            return;
        }
        else if (HM_Scripts.pluginController.appID == APP_ID.EVALULU)
        {
            Debug.LogError("Cette application n'a pas été configuré pour utiliser cette fonction");
            HM_Log.AppendTextToFile("HM_Log.txt", "AddResultData error : Cette application n'a pas été configuré pour utiliser cette fonction");
            return;
        }

        HM_Log.AppendTextToFile("HM_Log.txt", "AddResultData playDuration reçu : " + playDuration);
        SetProgression(jsonProgression);
        
        switch (HM_Scripts.pluginController.appID)
        {
            case APP_ID.EVASION:
                HM_AppEvasionUserResult resultEvasion = new HM_AppEvasionUserResult();
                resultEvasion.activityId = 834;
                resultEvasion.resultId = System.Guid.NewGuid().ToString();
                resultEvasion.userId = HM_DataController.currentChildUser.userID;
                resultEvasion.globalDuration = Time.realtimeSinceStartup;
                resultEvasion.playDuration = playDuration;
                resultEvasion.playDate = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssK");
                resultEvasion.taskId = HM_AppEvasionUserResult.taskId_session;
                resultEvasion.revisionDate = resultEvasion.playDate;
                try
                {
                    JObject o = JObject.Parse(jsonResult);

                    //si à tout hasard contient une valeur "appData", cela veut dire qu'on doit désérialiser dans HM_AppEvasionUserResult
                    if (o.ContainsKey("appData"))
                    {
                        HM_AppEvasionUserResult resultEvasionTemp = JsonConvert.DeserializeObject<HM_AppEvasionUserResult>(jsonResult);
                        resultEvasion.appData = resultEvasionTemp.appData;
                    }
                    else//sinon on désérialise dans HM_AppEvasionUserResult_SessionData
                    {
                        HM_AppEvasionUserResult_SessionData appDataEvasionTemp = JsonConvert.DeserializeObject<HM_AppEvasionUserResult_SessionData>(jsonResult);
                        resultEvasion.appData = appDataEvasionTemp;
                    }
                    HM_DataController.currentChildUser.appEvasionUserData.results.Add(resultEvasion);
                    HM_Log.AppendTextToFile("HM_LogResult.txt", JsonConvert.SerializeObject(resultEvasion));
                }
                catch(Exception e)
                {
                    Debug.LogError("AddResultData jsonResult Deserialize ERROR : "+e.Message);
                    HM_Log.AppendTextToFile("HM_Log.txt", "AddResultData jsonResult Deserialize ERROR : " + e.Message);
                }
                break;
            case APP_ID.ELARGIR:
                //cas particulier : on remet settings.difficultyMode à 0
                HM_DataController.currentChildUser.appElargirUserData.settings.difficultyMode = 0;
                HM_DataController.currentChildUser.appElargirUserData.settings.revisionDate = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssK");

                HM_AppElargirUserResult resultElargir = new HM_AppElargirUserResult();
                resultElargir.activityId = 835;
                resultElargir.resultId = System.Guid.NewGuid().ToString();
                resultElargir.userId = HM_DataController.currentChildUser.userID;
                resultElargir.globalDuration = Time.realtimeSinceStartup;
                resultElargir.playDuration = playDuration;
                resultElargir.playDate = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssK");
                resultElargir.taskId = HM_AppElargirUserResult.taskId_session;
                resultElargir.revisionDate = resultElargir.playDate;
                try
                {

                    JObject o = JObject.Parse(jsonResult);

                    //si à tout hasard contient une valeur "appData", cela veut dire qu'on doit désérialiser dans HM_AppElargirUserResult
                    if (o.ContainsKey("appData"))
                    {
                        HM_AppElargirUserResult resultElargirTemp = JsonConvert.DeserializeObject<HM_AppElargirUserResult>(jsonResult);
                        resultElargir.appData = resultElargirTemp.appData;
                    }
                    else//sinon on désérialise dans HM_AppElargirUserResult_SessionData
                    {
                        HM_AppElargirUserResult_SessionData appDataElargirTemp = JsonConvert.DeserializeObject<HM_AppElargirUserResult_SessionData>(jsonResult);
                        resultElargir.appData = appDataElargirTemp;

                    }

                    //audio présent
                    if (resultElargir.appData.audio != null && resultElargir.appData.audio.Length > 0 && resultElargir.appData.audio.Split('/').Length > 0)
                    {
                        List<HM_DataAudio> audioPending = new List<HM_DataAudio>();
                        string audioData = PlayerPrefs.GetString("HM_DataAudio", "");

                        if (audioData != null && audioData.Length > 0)
                        {
                            audioPending = JsonConvert.DeserializeObject<List<HM_DataAudio>>(audioData);
                        }

                        string filename = resultElargir.appData.audio.Split('/')[resultElargir.appData.audio.Split('/').Length - 1];

                        HM_DataAudio da = new HM_DataAudio();
                        da.localPath = resultElargir.appData.audio;
                        da.filename = filename;
                        da.resultID = resultElargir.resultId;
                        da.childIconID = HM_DataController.currentChildUser.userIconID;
                        da.childCode = HM_DataController.currentChildUser.loginCode;
                        da.teacherCode = HM_DataController.currentTeacherAccount.teacherCode;

                        resultElargir.appData.audioLink = "audios/" + da.childIconID + "/" + da.childCode + "/" + da.resultID + "/" + da.filename;

                        audioPending.Add(da);

                        PlayerPrefs.SetString("HM_DataAudio", JsonConvert.SerializeObject(audioPending));
                    }


                    HM_DataController.currentChildUser.appElargirUserData.results.Add(resultElargir);
                    HM_Log.AppendTextToFile("HM_LogResult.txt", JsonConvert.SerializeObject(resultElargir));
                }
                catch (Exception e)
                {
                    Debug.LogError("AddResultData jsonResult Deserialize ERROR : " + e.Message);
                    HM_Log.AppendTextToFile("HM_Log.txt", "AddResultData jsonResult Deserialize ERROR : " + e.Message);
                }
                break;
            case APP_ID.LUCIOLE:
                HM_AppLucioleUserResult resultLuciole = new HM_AppLucioleUserResult();
                resultLuciole.activityId = 836;
                resultLuciole.resultId = System.Guid.NewGuid().ToString();
                resultLuciole.userId = HM_DataController.currentChildUser.userID;
                resultLuciole.globalDuration = Time.realtimeSinceStartup;
                resultLuciole.playDuration = playDuration;
                resultLuciole.playDate = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssK");
                resultLuciole.taskId = HM_AppLucioleUserResult.taskId_session;
                resultLuciole.revisionDate = resultLuciole.playDate;
                resultLuciole.appData.parcours = HM_DataController.currentChildUser.appLucioleUserData.settings.parcours;
                resultLuciole.appData.avancementGlobal = HM_DataController.currentChildUser.appLucioleUserData.progression.lucioleParameters.avancementGlobal;
                resultLuciole.appData.avancementCurrentMission = HM_DataController.currentChildUser.appLucioleUserData.progression.lucioleParameters.avancementCurrentMission;
                resultLuciole.appData.nbrEtoilesGain = HM_DataController.currentChildUser.appLucioleUserData.progression.lucioleParameters.nbrEtoilesGain;
                resultLuciole.appData.nbrEtoilesTotal = HM_DataController.currentChildUser.appLucioleUserData.progression.lucioleParameters.nbrEtoilesTotal;
                resultLuciole.appData.currentGrade = HM_DataController.currentChildUser.appLucioleUserData.progression.lucioleParameters.currentGrade;
                try
                {
                    JObject o = JObject.Parse(jsonResult);

                    //si à tout hasard contient une valeur "appData", cela veut dire qu'on doit désérialiser dans HM_AppLucioleUserResult
                    if (o.ContainsKey("appData"))
                    {
                        HM_AppLucioleUserResult resultLucioleTemp = JsonConvert.DeserializeObject<HM_AppLucioleUserResult>(jsonResult);
                        resultLuciole.appData = resultLucioleTemp.appData;
                    }
                    else//sinon on désérialise dans HM_AppLucioleUserResult_SessionData
                    {
                        HM_AppLucioleUserResult_SessionData appDataLuciolerTemp = JsonConvert.DeserializeObject<HM_AppLucioleUserResult_SessionData>(jsonResult);
                        resultLuciole.appData = appDataLuciolerTemp;

                    }
                    HM_DataController.currentChildUser.appLucioleUserData.results.Add(resultLuciole);
                    HM_Log.AppendTextToFile("HM_LogResult.txt", JsonConvert.SerializeObject(resultLuciole));
                }
                catch (Exception e)
                {
                    Debug.LogError("AddResultData jsonResult Deserialize ERROR : " + e.Message);
                    HM_Log.AppendTextToFile("HM_Log.txt", "AddResultData jsonResult Deserialize ERROR : " + e.Message);
                }
                break;
        }

        HM_DataController.model.Save();

    }

    public static void AddResultDataAdmin(string jsonProgression, float playDuration, string jsonResult, int addJours = 0, int addMinutes = 0)
    {
        SetProgression(jsonProgression);

        switch (HM_Scripts.pluginController.appID)
        {
            case APP_ID.EVASION:
                HM_AppEvasionUserResult resultEvasion = new HM_AppEvasionUserResult();
                resultEvasion.activityId = 834;
                resultEvasion.resultId = System.Guid.NewGuid().ToString();
                resultEvasion.userId = HM_DataController.currentChildUser.userID;
                resultEvasion.globalDuration = Time.realtimeSinceStartup;
                resultEvasion.playDuration = playDuration;
                resultEvasion.playDate = DateTime.UtcNow.AddDays(-addJours).AddMinutes(addMinutes).ToString("yyyy-MM-ddTHH:mm:ssK");
                resultEvasion.revisionDate = resultEvasion.playDate;
                try
                {
                    HM_AppEvasionUserResult resultEvasionTemp = JsonConvert.DeserializeObject<HM_AppEvasionUserResult>(jsonResult);
                    resultEvasion.appData = resultEvasionTemp.appData;
                    resultEvasion.taskId = resultEvasionTemp.taskId;
                    Debug.Log(resultEvasion.taskId);

                    HM_DataController.currentChildUser.appEvasionUserData.results.Add(resultEvasion);
                    HM_Log.AppendTextToFile("HM_LogResult.txt", JsonConvert.SerializeObject(resultEvasion));
                }
                catch (Exception e)
                {
                    Debug.LogError("AddResultData jsonResult Deserialize ERROR : " + e.Message);
                    HM_Log.AppendTextToFile("HM_Log.txt", "AddResultData jsonResult Deserialize ERROR : " + e.Message);
                }
                break;
            case APP_ID.ELARGIR:
                HM_AppElargirUserResult resultElargir = new HM_AppElargirUserResult();
                resultElargir.activityId = 835;
                resultElargir.resultId = System.Guid.NewGuid().ToString();
                resultElargir.userId = HM_DataController.currentChildUser.userID;
                resultElargir.globalDuration = Time.realtimeSinceStartup;
                resultElargir.playDuration = playDuration;
                resultElargir.playDate = DateTime.UtcNow.AddDays(-addJours).AddMinutes(addMinutes).ToString("yyyy-MM-ddTHH:mm:ssK");
                resultElargir.revisionDate = resultElargir.playDate;
                try
                {
                    HM_AppElargirUserResult resultElargirTemp = JsonConvert.DeserializeObject<HM_AppElargirUserResult>(jsonResult);
                    resultElargir.appData = resultElargirTemp.appData;
                    resultElargir.taskId = resultElargirTemp.taskId;
                    Debug.Log(resultElargir.taskId);

                    //audio présent
                    if (resultElargir.appData.audio != null && resultElargir.appData.audio.Length > 0 && resultElargir.appData.audio.Split('/').Length > 0)
                    {
                        List<HM_DataAudio> audioPending = new List<HM_DataAudio>();
                        string audioData = PlayerPrefs.GetString("HM_DataAudio", "");

                        if (audioData != null && audioData.Length > 0)
                        {
                            audioPending = JsonConvert.DeserializeObject<List<HM_DataAudio>>(audioData);
                        }

                        resultElargir.appData.audio = resultElargir.appData.audio.Replace('\\', '/');

                        string filename = resultElargir.appData.audio.Split('/')[resultElargir.appData.audio.Split('/').Length - 1];

                        HM_DataAudio da = new HM_DataAudio();
                        da.localPath = resultElargir.appData.audio;
                        da.filename = filename;
                        da.resultID = resultElargir.resultId;
                        da.childIconID = HM_DataController.currentChildUser.userIconID;
                        da.childCode = HM_DataController.currentChildUser.loginCode;
                        da.teacherCode = HM_DataController.currentTeacherAccount.teacherCode;

                        resultElargir.appData.audioLink = "audios/" + da.childIconID + "/" + da.childCode + "/" + da.resultID + "/" + da.filename;

                        audioPending.Add(da);

                        Debug.Log(resultElargir.appData.audioLink);

                        PlayerPrefs.SetString("HM_DataAudio", JsonConvert.SerializeObject(audioPending));

                        PlayerPrefs.Save();
                    }

                    HM_DataController.currentChildUser.appElargirUserData.results.Add(resultElargir);
                    HM_Log.AppendTextToFile("HM_LogResult.txt", JsonConvert.SerializeObject(resultElargir));
                }
                catch (Exception e)
                {
                    Debug.LogError("AddResultData jsonResult Deserialize ERROR : " + e.Message);
                    HM_Log.AppendTextToFile("HM_Log.txt", "AddResultData jsonResult Deserialize ERROR : " + e.Message);
                }
                break;
            case APP_ID.LUCIOLE:
                HM_AppLucioleUserResult resultLuciole = new HM_AppLucioleUserResult();
                resultLuciole.activityId = 836;
                resultLuciole.resultId = System.Guid.NewGuid().ToString();
                resultLuciole.userId = HM_DataController.currentChildUser.userID;
                resultLuciole.globalDuration = Time.realtimeSinceStartup;
                resultLuciole.playDuration = playDuration;
                resultLuciole.playDate = DateTime.UtcNow.AddDays(-addJours).AddMinutes(addMinutes).ToString("yyyy-MM-ddTHH:mm:ssK");
                resultLuciole.revisionDate = resultLuciole.playDate;
                resultLuciole.appData.parcours = HM_DataController.currentChildUser.appLucioleUserData.settings.parcours;
                resultLuciole.appData.avancementGlobal = HM_DataController.currentChildUser.appLucioleUserData.progression.lucioleParameters.avancementGlobal;
                resultLuciole.appData.avancementCurrentMission = HM_DataController.currentChildUser.appLucioleUserData.progression.lucioleParameters.avancementCurrentMission;
                resultLuciole.appData.nbrEtoilesGain = HM_DataController.currentChildUser.appLucioleUserData.progression.lucioleParameters.nbrEtoilesGain;
                resultLuciole.appData.currentGrade = HM_DataController.currentChildUser.appLucioleUserData.progression.lucioleParameters.currentGrade;
                try
                {
                    HM_AppLucioleUserResult resultLucioleTemp = JsonConvert.DeserializeObject<HM_AppLucioleUserResult>(jsonResult);
                    resultLuciole.appData = resultLucioleTemp.appData;
                    resultLuciole.taskId = resultLucioleTemp.taskId;
                    Debug.Log(resultLuciole.taskId);

                    HM_DataController.currentChildUser.appLucioleUserData.results.Add(resultLuciole);
                    HM_Log.AppendTextToFile("HM_LogResult.txt", JsonConvert.SerializeObject(resultLuciole));
                }
                catch (Exception e)
                {
                    Debug.LogError("AddResultData jsonResult Deserialize ERROR : " + e.Message);
                    HM_Log.AppendTextToFile("HM_Log.txt", "AddResultData jsonResult Deserialize ERROR : " + e.Message);
                }
                break;
        }

        HM_DataController.model.Save();

    }

    public static void ResetCurrentUser()
    {
        if (HM_DataController.currentChildUser == null)
        {
            Debug.LogError("Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            HM_Log.AppendTextToFile("HM_Log.txt", "ResetCurrentUser error : Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            return;
        }

        switch (HM_Scripts.pluginController.appID)
        {
            case APP_ID.ELARGIR:
                HM_AppElargirUserData baseDataElargir = new HM_AppElargirUserData();
                HM_DataController.currentChildUser.appElargirUserData = baseDataElargir;
                break;
            case APP_ID.LUCIOLE:
                HM_AppLucioleUserData baseDataLuciole = new HM_AppLucioleUserData();
                HM_DataController.currentChildUser.appLucioleUserData = baseDataLuciole;
                break;
            case APP_ID.EVASION:
                HM_AppEvasionUserData baseDataEvasion = new HM_AppEvasionUserData();
                HM_DataController.currentChildUser.appEvasionUserData = baseDataEvasion;
                break;
        }

        HM_DataController.model.Save();
    }

    public static string GetCurrentTeacherCode()
    {
        if (HM_DataController.currentChildUser == null)
        {
            Debug.LogError("Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            HM_Log.AppendTextToFile("HM_Log.txt", "GetCurrentTeacherCode error : Le plugin HM ne retrouve pas l'enfant actuellement connecté");
            return null;
        }

        if (HM_DataController.currentTeacherAccount == null)
        {
            Debug.LogError("Le plugin HM ne retrouve pas le professeur actuellement lié à l'enfant connecté");
            HM_Log.AppendTextToFile("HM_Log.txt", "GetCurrentTeacherCode error : Le plugin HM ne retrouve pas le professeur actuellement lié à l'enfant connecté");
            return null;
        }

        return HM_DataController.currentTeacherAccount.teacherCode;

    }

    public static List<string> GetAllTeacherAccounts()
    {
        List<string> teacherCodes = new List<string>();

        foreach(HM_TeacherAccount t in HM_DataController.model.teacherAccounts)
        {
            teacherCodes.Add(t.teacherCode);
        }

        return teacherCodes;
    }

    public static List<HM_ChildUser> GetAllActiveChildsOfTeacher(string teacherCode)
    {
        List<HM_ChildUser> activeChildAccount = new List<HM_ChildUser>();

        foreach (HM_TeacherAccount t in HM_DataController.model.teacherAccounts)
        {
            if(t.teacherCode.ToUpper().Equals(teacherCode.ToUpper()))
            {
                foreach (HM_ChildUser c in t.childUsers)
                {
                    if (c.activeUser)
                    {
                        activeChildAccount.Add(c);
                    }
                }
                return activeChildAccount;
            }
        }

        return null;
    }

    public void TestSecondUserLoginSuccess()
    {
        Debug.Log("TestSecondUserLoginSuccess");
        Debug.Log(GetSecondUserID());
    }
    public void TestAppSettingsCancel()
    {
        Debug.Log("TestAppSettingsCancel");
        Debug.Log(GetSettingsSession());
    }

    public void TestAppSettingsEnd()
    {
        Debug.Log("TestAppSettingsEnd");
        Debug.Log(GetSettingsSession());        
    }

    public static void CheckTraceExist(string fileURL, System.Action<int,string> callback, int userIconId = -1, int userLoginCode = -1)
    {
        HM_Scripts.pluginController.StartPlugin();

        HM_ReturnInfo returnInfo = new HM_ReturnInfo();
        
        if (userIconId == -1 && userLoginCode == -1 && HM_DataController.currentChildUser == null)
        {
            returnInfo.code = -1;
            returnInfo.message = "Le plugin HM ne retrouve pas l'enfant actuellement connecté";
            HM_Scripts.pluginController.StartCoroutine(OnCheckTraceExistResponse(returnInfo, callback));
            return;
        }

        if (Application.internetReachability == NetworkReachability.NotReachable)
        {
            returnInfo.code = -2;
            returnInfo.message = "Pas de connexion Internet détecté";
            HM_Scripts.pluginController.StartCoroutine(OnCheckTraceExistResponse(returnInfo, callback));
            return;
        }

        if (HM_DataController.currentTeacherAccount.dataAWS._idToken == null 
            || HM_DataController.currentTeacherAccount.dataAWS._idToken.Length == 0 
            || HM_DataController.currentTeacherAccount.dataAWS.identityId == null 
            || HM_DataController.currentTeacherAccount.dataAWS.identityId.Length == 0)
        {
            returnInfo.code = -3;
            returnInfo.message = "Compte professeur non authentifié";
            HM_Scripts.pluginController.StartCoroutine(OnCheckTraceExistResponse(returnInfo, callback));
            return;
        }

        if ((userIconId == -1 && userLoginCode != -1) || (userIconId != -1 && userLoginCode == -1))
        {
            returnInfo.code = -4;
            returnInfo.message = "Une des deux données userIconId ou userLoginCode n'est pas renseigné";
            HM_Scripts.pluginController.StartCoroutine(OnCheckTraceExistResponse(returnInfo, callback));
            return;
        }

        fileURL = fileURL.Replace('\\', '/');

        //construction URL
        string filename = fileURL.Split('/')[fileURL.Split('/').Length - 1];
        string appName = "";
        switch (HM_Scripts.pluginController.appID)
        {
            case APP_ID.NONE:
                appName = "none";
                break;
            case APP_ID.LUCIOLE:
                appName = "luciole";
                break;
            case APP_ID.ELARGIR:
                appName = "elargir";
                break;
            case APP_ID.EVASION:
                appName = "evasion";
                break;
            case APP_ID.EVALULU:
                appName = "evalulu";
                break;
        }

        string serverPath = "private/" + HM_DataController.currentTeacherAccount.dataAWS.identityId + "/traces/" + appName + "/";

        if (userIconId != -1 && userLoginCode != -1)
        {
            serverPath += userIconId + "/" + userLoginCode + "/" + filename;
        }
        else
        {
            serverPath += HM_DataController.currentChildUser.userIconID + "/" + HM_DataController.currentChildUser.loginCode + "/" + filename;
        }

        Task.Run(async () =>
        {
            returnInfo = await HM_NetworkController.instance.S3List_v2(serverPath);

            UnityMainThreadDispatcher.Instance().Enqueue(OnCheckTraceExistResponse(returnInfo, callback));
        });
    }

    private static IEnumerator OnCheckTraceExistResponse(HM_ReturnInfo returnInfo, System.Action<int, string> callback)
    {
        HM_Scripts.pluginController.StopPlugin();

        if (returnInfo.code > 0)
        {
            callback.Invoke(1, "Le fichier a été trouvé sur le serveur");
        }
        else if(returnInfo.code == 0)
        {
            callback.Invoke(0, "Le fichier n'a pas été trouvé sur le serveur");
        }
        else
        {
            callback.Invoke(returnInfo.code, returnInfo.message);

            string logMsg = "OnCheckTraceExistResponse ERROR " + returnInfo.code + " / " + returnInfo.message;
            Debug.LogError(logMsg);
            HM_Log.AppendTextToFile("HM_Log.txt", logMsg);
        }

        yield return null;
    }

    public static void UploadTrace(string fileURL, System.Action<int, string> callback, int userIconId = -1, int userLoginCode = -1)
    {
        HM_Scripts.pluginController.StartPlugin();

        HM_ReturnInfo returnInfo = new HM_ReturnInfo();

        if (userIconId == -1 && userLoginCode == -1 && HM_DataController.currentChildUser == null)
        {
            returnInfo.code = -1;
            returnInfo.message = "Le plugin HM ne retrouve pas l'enfant actuellement connecté";
            HM_Scripts.pluginController.StartCoroutine(OnUploadTraceResponse(returnInfo, callback));
            return;
        }

        if (Application.internetReachability == NetworkReachability.NotReachable)
        {
            returnInfo.code = -2;
            returnInfo.message = "Pas de connexion Internet détecté";
            HM_Scripts.pluginController.StartCoroutine(OnUploadTraceResponse(returnInfo, callback));
            return;
        }

        if (HM_DataController.currentTeacherAccount.dataAWS._idToken == null
            || HM_DataController.currentTeacherAccount.dataAWS._idToken.Length == 0
            || HM_DataController.currentTeacherAccount.dataAWS.identityId == null
            || HM_DataController.currentTeacherAccount.dataAWS.identityId.Length == 0)
        {
            returnInfo.code = -3;
            returnInfo.message = "Compte professeur non authentifié";
            HM_Scripts.pluginController.StartCoroutine(OnUploadTraceResponse(returnInfo, callback));
            return;
        }

        if ((userIconId == -1 && userLoginCode != -1) || (userIconId != -1 && userLoginCode == -1))
        {
            returnInfo.code = -4;
            returnInfo.message = "Une des deux données userIconId ou userLoginCode n'est pas renseigné";
            HM_Scripts.pluginController.StartCoroutine(OnUploadTraceResponse(returnInfo, callback));
            return;
        }

        fileURL = fileURL.Replace('\\', '/');

        //construction URL
        string filename = fileURL.Split('/')[fileURL.Split('/').Length - 1];
        string appName = "";
        switch (HM_Scripts.pluginController.appID)
        {
            case APP_ID.NONE:
                appName = "none";
                break;
            case APP_ID.LUCIOLE:
                appName = "luciole";
                break;
            case APP_ID.ELARGIR:
                appName = "elargir";
                break;
            case APP_ID.EVASION:
                appName = "evasion";
                break;
            case APP_ID.EVALULU:
                appName = "evalulu";
                break;
        }

        string serverPath = "private/" + HM_DataController.currentTeacherAccount.dataAWS.identityId + "/traces/" + appName + "/";

        if (userIconId != -1 && userLoginCode != -1)
        {
            serverPath += userIconId + "/" + userLoginCode + "/" + filename;
        }
        else
        {
            serverPath += HM_DataController.currentChildUser.userIconID + "/" + HM_DataController.currentChildUser.loginCode + "/" + filename;
        }

        Task.Run(async () =>
        {
            returnInfo = await HM_NetworkController.instance.S3Upload_v2(fileURL,serverPath);

            UnityMainThreadDispatcher.Instance().Enqueue(OnUploadTraceResponse(returnInfo, callback));
        });
    }

    private static IEnumerator OnUploadTraceResponse(HM_ReturnInfo returnInfo, System.Action<int, string> callback)
    {
        HM_Scripts.pluginController.StopPlugin();

        if (returnInfo.code == 0)
        {
            callback.Invoke(0, "Le fichier a bien été uploadé");
        }
        else
        {
            callback.Invoke(returnInfo.code, returnInfo.message);

            string logMsg = "OnUploadTraceResponse ERROR " + returnInfo.code + " / " + returnInfo.message;
            Debug.LogError(logMsg);
            HM_Log.AppendTextToFile("HM_Log.txt", logMsg);
        }

        yield return null;
    }
}