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

public class ActiveScoppedElements : MonoBehaviour
{
    
    [Serializable]
    public struct ObjectToInstantiate {
        public List<String> elements;
        public GameObject obj;
    }


    // Start is called before the first frame update
    public HashSet<String> actives = new HashSet<String>();
    public HashSet<GameObject> InstantiatesObject = new HashSet<GameObject>();
    public TextMeshProUGUI textToUpdate;
    public TextMeshProUGUI objectInstantiateText;
    public ObjectToInstantiate[] objectToInstantiates;
    public HashSet<GameObject> DisableGameObjects = new HashSet<GameObject>();
    public GameObject[] InformationObjs;
    public GameObject[] DebugObjs;

    void Start()
    {
        if (this.textToUpdate != null)
        {
            textToUpdate.text = "Scanner des Markers...";
        }
    }

    public void AddScoppedElement(String name)
    {
        Debug.Log("Added " + name);
        if (!actives.Contains(name))
        {
            actives.Add(name);
            RefreshText();
            RefreshAtom();
        }
    }

    private void RefreshText()
    {
        if (this.textToUpdate != null)
        {
            this.textToUpdate.text = String.Join(", ", this.actives);
        }
    }

    private void RefreshAtom()
    {
        foreach (var objt in objectToInstantiates)
        {
            if (objt.elements.TrueForAll((s => actives.Contains(s))))
            {
                foreach (var objName in objt.elements)
                {
                    var a = GameObject.Find("OBJ_" + objName);
                    if (a != null)
                    {
                        a.SetActive(false);
                        DisableGameObjects.Add(a);
                    }
                }
                // Obtenez la position de la caméra
                Vector3 cameraPosition = Camera.main.transform.position;

                // Obtenez la rotation de la caméra sans inclure la rotation autour de l'axe Y
                Quaternion cameraRotation = Quaternion.Euler(0, Camera.main.transform.rotation.eulerAngles.y, 0);

                // Calculez la position finale en ajoutant la direction vers l'avant multipliée par la distance désirée
                Vector3 position = cameraPosition + cameraRotation * Vector3.forward * 0.35f;

                var instantiatedObj = Instantiate(objt.obj, position, cameraRotation);
                instantiatedObj.name = "[N] " + objt.obj.name;
                InstantiatesObject.Add(instantiatedObj);
                this.OnInstantiateObject(instantiatedObj);
                Debug.Log("Instantiate " + instantiatedObj.name);
            }
            else
            {
                var a = InstantiatesObject.FirstOrDefault(s => s.name == ("[N] " + objt.obj.name));
                if (a != null)
                {
                    Debug.Log("Destroy " + a.name);
                    InstantiatesObject.Remove(a);
                    OnDestroyObject(a);
                    Destroy(a);
                    foreach (var disableGameObject in DisableGameObjects)
                    {
                        disableGameObject.SetActive(true);
                    }
                    DisableGameObjects.Clear();
                }
            }
        }

        if (InstantiatesObject.Count > 0)
        {
            objectInstantiateText.text = String.Join(", ", InstantiatesObject.Select((s) => s.name));
        }
        else
        {
            objectInstantiateText.text = "En attente...";
        }
    }

    private void OnInstantiateObject(GameObject obj)
    {
        foreach (var informationObj in InformationObjs)
        {
            informationObj.SetActive(true);
        }
        foreach (var debugObj in DebugObjs)
        {
            debugObj.SetActive(false);
        }
    }

    private void OnDestroyObject(GameObject obj)
    {
        foreach (var informationObj in InformationObjs)
        {
            informationObj.SetActive(false);
        }
        foreach (var debugObj in DebugObjs)
        {
            debugObj.SetActive(true);
        }
    }

    public void RemoveUnscoppedElement(String elementName)
    {
        Debug.Log("Removed " + elementName);
        actives.Remove(elementName);
        RefreshText();
        RefreshAtom();
    }

    void Update()
    {
        
    }
}
