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



public class AtomeFactory : MonoBehaviour{

    public TextAsset jsonFile;

    private static AtomeFactory instance;

    private AtomesInformation atomeInJson;

    private Dictionary<string, AtomeInformation> AtomeDictionary; 

    public AtomeFactory(TextAsset jsonFile){
        AtomeFactory.instance = this;
        AtomeDictionary = new Dictionary<string, AtomeInformation>();
        atomeInJson = JsonUtility.FromJson<AtomesInformation>(jsonFile.text);
        foreach (var atome in atomeInJson.atomes){
            AtomeDictionary.Add(atome.symbol, atome);
        }
    }

    public static AtomeFactory getInstrance(){
        if(AtomeFactory.instance == null){
            Debug.LogError("no Json file");
        }
        return AtomeFactory.instance;
    }

        public static AtomeFactory getInstrance(TextAsset jsonFile){
        if(AtomeFactory.instance == null){
            AtomeFactory.instance = new AtomeFactory(jsonFile);
        }
        return AtomeFactory.instance;
    }
        
    public bool hasAtome(String symbol)
    {
        return AtomeDictionary.ContainsKey(symbol);
    }

    public AtomeInformation createAtome(string symbol){
        if(!AtomeDictionary.ContainsKey(symbol)){
            Debug.LogError("Atome does not existe in json");
            return null;
        }
        AtomeInformation atome = AtomeDictionary[symbol];
        
        return atome;
    }

    public GameObject createAnimatedAtome(string symbol) {
        if(!AtomeDictionary.ContainsKey(symbol)){
            Debug.LogError("Atome does not existe in json");
            return null;
        }
        AtomeInformation atomeinfo = AtomeDictionary[symbol];
        GameObject Parent = new GameObject(atomeinfo.name);
        int ElectronsNumber = atomeinfo.protons;
        
        //Symbol
        GameObject atome = CreateSymbolAnimation(atomeinfo);
        atome.transform.parent = Parent.transform;

        //Electrons
        for (int i = 1; ElectronsNumber > 0; i++) {
            int nbrElectronLayer = 2 * (i * i);
            GameObject electrons = CreateElectronsAnimation(Mathf.Min(ElectronsNumber, nbrElectronLayer), (float)i);
            electrons.transform.parent = Parent.transform;
            ElectronsNumber -= nbrElectronLayer;
        }
        //rajouter electron == protons
        return Parent;
    }

    private GameObject DrawCircle(float orbitRadius)
    {
        GameObject orbitCircle = new GameObject("Orbit Circle");
        LineRenderer lineRenderer = orbitCircle.AddComponent<LineRenderer>();
        lineRenderer.useWorldSpace = false;
        lineRenderer.widthMultiplier = 0.03f;  // Ajustez l'épaisseur de la ligne si nécessaire.
        lineRenderer.positionCount = 100 + 1;
        //Add Color
        Color myColor = new Color(0, 0, 1, 1);
        ColorUtility.TryParseHtmlString("#7F7F7F", out myColor);
        orbitCircle.GetComponent<Renderer>().material.color = myColor;

        for (int i = 0; i <= 100; i++)
        {
            float angle = i * 2 * Mathf.PI / 100;
            float x = Mathf.Cos(angle) * orbitRadius;
            float y = Mathf.Sin(angle) * orbitRadius;

            lineRenderer.SetPosition(i, new Vector3(x, 0f, y));
        }
        return orbitCircle;
    }


    private GameObject CreateSymbolAnimation(AtomeInformation info) {
        //Create GameObject
        GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
        //Add information
        sphere.name = info.symbol;
        sphere.transform.position = new Vector3(0, 0, 0);
        //Add Color
        Color myColor = new Color(0, 0, 1, 1);
        ColorUtility.TryParseHtmlString(info.representation.color, out myColor);
        sphere.GetComponent<Renderer>().material.color = myColor;

        return sphere;
    }



    private GameObject CreateElectronsAnimation(int electrons, float layer) {
        GameObject ParentLayer = new GameObject("Electrons");

        for (int i = 0; i < electrons; i++) {
            float angle = i * Mathf.PI * 2 / electrons;
            float x = Mathf.Cos(angle) * layer;
            float z = Mathf.Sin(angle) * layer;
            float y = 0f;

            GameObject electron = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            electron.name = "Electron" + i;
            electron.transform.position = new Vector3(x, y, z);
            electron.transform.localScale = new Vector3(0.3f, 0.3f, 0.3f);
            electron.transform.parent = ParentLayer.transform;
        }
        GameObject orbit = DrawCircle(layer);
        orbit.transform.parent = ParentLayer.transform;

        return ParentLayer;
    }
}