using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//----------------------------------------------------
// TP Unity EFREI M1 ST2INRV 2023-2024
// Classe  placer sous l'Empty Object GrosObjet
//
// 
public class GereSelection : 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
    public float gain = 0.15F; // Gain  mettre  jour si besoin dans le Game, pour l'ajustement de la position de l'objet manipul par rapport au curseur de la souris
    public GameObject objetSelectionne = null; // Pointe vers l'objet slectionnable
    public GameObject objetSelectionnable = null; // Pointe vers l'objet slectionn
    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'


    // 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<SelectionObjet>().etatObjets == SelectionObjet.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;
        objetSelectionne = null;
        objetSelectionnable = null;
        // 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++;
                }
            }
        }
        cameraAuSol.enabled = false; // La camra au sol est dsactive au Run
    }

    // Update is called once per frame
    // Implmenta la Machine  Etats associe au jeu
    void Update()
    {
        if (partieTerminee == false)
        {
            if (Input.GetMouseButtonDown(0) && (objetSelectionnable != null) && (objetSelectionne == null)) // Appuie sur le bouton gauche de la souris et un objet est selectionnable?
            {
                int indexSelectionne = objetGetIndex(objetSelectionnable.name);
                Debug.Log("*** " + objetSelectionnable.name + " est slectionn");
                objetSelectionne = objetSelectionnable;
                tfils[indexSelectionne].GetComponent<SelectionObjet>().SetSelectionne(); // L'objet est slectionn
                objetSelectionnable = null;
                mp_past = Camera.main.ScreenToWorldPoint(
                    new Vector3(Input.mousePosition.x,
                    Input.mousePosition.y,
                    Camera.main.nearClipPlane));
            }
            else if (Input.GetMouseButton(0) && (objetSelectionnable == null) && (objetSelectionne != null)) // Appuie sur le bouton gauche de la souris et un objet est selectionn?
            {
                int indexSelectionne = objetGetIndex(objetSelectionne.name);
                tfils[indexSelectionne].GetComponent<SelectionObjet>().SetManipule(); // L'objet est manipul
                Vector3 mp = Camera.main.ScreenToWorldPoint( // Position 3d associ au curseur de la souris dans l'environnement virtuel,  l'instant t
                      new Vector3(Input.mousePosition.x,
                      Input.mousePosition.y,
                      Camera.main.nearClipPlane));
                Debug.Log("Dure entre deux frames graphiques (s): " + Time.deltaTime);
                Vector3 delta = (mp - mp_past) / (Time.deltaTime); // Vitesse de dplacement de l'avatar port par la souris dans le monde virtuel
                mp_past = mp;
                objetSelectionne.transform.position += gain * delta;
                Debug.Log("*** " + objetSelectionne.name + " est  la position (" + mp.x.ToString() + "," + mp.y + "," + mp.z + ")");
            }
            else if (Input.GetMouseButtonUp(0) && (objetSelectionne != null)) // Relache le bouton gauche de la souris et un objet est selectionn?
            {
                int indexSelectionne = objetGetIndex(objetSelectionne.name);
                tfils[indexSelectionne].GetComponent<SelectionObjet>().SetEnChute(); // L'objet est dans l'tat EnChute
                Debug.Log("*** " + objetSelectionne.name + " est relach.");
                objetSelectionne.transform.GetComponent<Rigidbody>().isKinematic = false;
                objetSelectionne = null;
                cameraAuSol.enabled = true; // La camra au sol est active pendant la chute
            }
        }
    }

    // Implmente ce qui not sur l'cran du Game
    // Excut  chaque frame graphique
    void OnGUI() // Scne 5
    {
        GUI.contentColor = Color.blue;
        if (PartieTerminee() == false)
        {
            compteur_temps = Time.time.ToString("0.") + " sec";
            GUI.Label(new Rect(10, 5, 150, 20), compteur_temps);
            for (int i = 0; i < nfils; i++)
            {
                GUI.Label(new Rect(10, 5 + (i + 1) * 20, 150, 20), tfils[i].name + "(" + tfils[i].GetComponent<SelectionObjet>().etatObjets + ")");
            }
        }
        else
        {
            GUI.Label(new Rect(10, 5, 250, 20), "PARTIE TERMINEE EN " + compteur_temps);
            partieTerminee = true;
        }
    }
}
