using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
using TMPro;

//----------------------------------------------------
// TP Unity EFREI M1 INRV 2022-2023
// Classe  placer sous l'Empty Object GrosObjet
//
// Affiche le tempsen secondes depuis le dbut de l'exprience ainsi que l'tat des objets sous le GameObject courant (GrosObjet)
public class GereSelectionXR : MonoBehaviour
{
    public Camera cameraAuSol; // A lier avec la Camra nomme CameraAuSol dans la Hierarchy
    public bool partieTerminee; // Vaut true ssi tous les objets fils de GrosObjet sont dans l'tat TombAuSol
    private GameObject[] tfils; // tableau contenant la liste des GameObject fils de GrosObjet
    private int nfils;
    private Vector3 mp_past; // Position 3d associ au curseur de la souris dans l'environnement virtuel,  l'instant t-1
    private string compteur_temps; // Temps depuis le dbut du Run, formatt en string, se terminant par ' sec'
    private string affichage;
    private enum EtatsObjets { Idle, Slectionnable, Slectionn, Manipul, EnChute, TombAuSol }; // Etats possibles associs aux objets fils de GrosObjet
    public Canvas canvas;
    public TextMeshProUGUI affiche; // Zone d'affichage 2D dans l'espace 3D
    private InputDevice targetDevice;
    InputDeviceCharacteristics leftControllerCharacteristics = InputDeviceCharacteristics.Left | InputDeviceCharacteristics.Controller; // Ne considre les donnes que du contrleur gauche
    bool partieQuittee = false;
    // Affiche le texte 'text' dans la zone d'affichage 2D rfrence par 'canvas' et 'affiche'
    private void Affiche(string text)
    {
        Debug.Log(text);
        affiche.text = text;
    }

    // Pre: name est le nom d'un des objets fils de GrosObjet
    // Post: index du GameObject de nom 'name' dans le tableau tfils[], ou -1 si name n'est pas un fils de GrosObjet
    private int objetGetIndex( string name)
    {
        for (int i = 0; i < nfils; i++)
            if (name == tfils[i].name)
                return i;
        return -1; // Oups, erreur, name est introuvable, ce qui ne devrait pas arriver ...
    }

    // Pre: les lments de tfils[] sont initialiss et portent le Script SelectionObjet
    // Post: true si tous les objets de tfils[] sont associs  l'tat TombAuSol, false sinon
    public bool PartieTerminee()
    {
        bool term = true;
        for (int i = 0; i < nfils; i++)
            term = term && (tfils[i].GetComponent<SelectionObjetXR>().etatObjets == SelectionObjetXR.EtatsObjets.TombAuSol);
        return term;
    }
    
    // Start is called before the first frame update
    // Initialisation du tableau tfils[], de CameraAuSol, de pertieTerminee, de objetSelectionnable, de objetSelectionne
    void Start()
    {
        partieTerminee = false;
        partieQuittee = false;
        // Rcupre tous les fils de l'objet soutenance le script
        Transform[] ts = this.gameObject.GetComponentsInChildren<Transform>();
        if (ts == null)
            Debug.Log(this.gameObject.name + " n'a pas de fils");
        else
        {
            nfils = ts.Length-1;
            Debug.Log(this.gameObject.name + " possde " + nfils +" fils");
            tfils = new GameObject[nfils];
            int i = 0;
            foreach (Transform t in ts)
            {
                if (t.name != this.gameObject.name)
                {
                    tfils[i] = t.gameObject;
                    i++;
                }
            }
        }
    }

    // Update is called once per frame
    // Mise  jour du temps (sec) et de l'tats des objets sous le GameObject courant
    void Update()
    {
        List<InputDevice> devices = new List<InputDevice>();
        InputDevices.GetDevicesWithCharacteristics(leftControllerCharacteristics, devices);
        if (devices.Count > 0)
        {
            targetDevice = devices[index: 0];
            targetDevice.TryGetFeatureValue(CommonUsages.menuButton, out bool lmenuButtonValue); // Controleur gauche: Appuie du bouton Menu (true, false)
            if (lmenuButtonValue == true)
                partieQuittee = true;
        }
        partieTerminee = PartieTerminee();
        if ((partieTerminee == false) && (partieQuittee == false))
        {
            compteur_temps = Time.time.ToString("0.") + " sec" + "\n";
            affichage = compteur_temps;
            for (int i = 0; i < nfils; i++)
            {
                string text = tfils[i].name + "(" + tfils[i].GetComponent<SelectionObjetXR>().etatObjets + ")\n";
                affichage += text;
            }
            Affiche(affichage);
        }
        else if (partieTerminee == true)
        {
            affichage = "PARTIE TERMINEE EN " + compteur_temps;
            Affiche(affichage);
            StartCoroutine(QuitAfterDelay(5.0F)); // Attend 5 secondes et quitte l'application
        }
        else
        {
            affichage = "PARTIE QUITTEE AU BOUT DE " + compteur_temps;
            Affiche(affichage);
            StartCoroutine(QuitAfterDelay(2.0F));  // Attend 2 secondes et quitte l'application
        }
    }

    // Attend time secondes puis quitte l'application (ne fonctionne pas avec l'diteur Unity)
    IEnumerator QuitAfterDelay(float time)
    {
        yield return new WaitForSeconds(time);

        Application.Quit();
    }
}
