using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using UnityEngine;
using UnityEngine.UIElements;

public class KF3StaticContainer : KF3ObjectContainer
{
    public bool CanBeSaved = true;
    private bool paused = false;
    public int SelectedMaterialVariant = 0;
    private Dictionary<Renderer, List<Material[]>> _materialVariants = new Dictionary<Renderer, List<Material[]>>();
    private Material lineMaterial;
    public List<GameObject> DetachableObjects = new List<GameObject>();
    private Dictionary<GameObject, Transform[]> linePoints = new Dictionary<GameObject, Transform[]>();

    public UIKF3StaticSettings SettingsPanel;

    //private void Start()
    //{
    //    KF3ModelContainer mc = gameObject.AddComponent<KF3ModelContainer>();
    //    mc.Renderers = this.renderers;
    //}
    public static KF3StaticContainer Create(AssetBundle ab)
    {
        if(ab == null) return null;

        GameObject go = Instantiate(ab.LoadAsset(ab.GetAllAssetNames()[0]) as GameObject);
        var container = go.AddComponent<KF3StaticContainer>();
        container.name = ab.name;
        UIHandleProp.CreateAsChild(container, go.transform);
        container.Init();

        ab.Unload(false);

        return container;
    }

    public void Init()
    {
        Renderer[] renderers = gameObject.GetComponentsInChildren<Renderer>();

        foreach (Renderer renderer in renderers)
        {
            Material[] overrideMaterials = new Material[renderer.materials.Length];
            Material[] overrideMaterials2 = new Material[renderer.materials.Length];
            for (int i = 0; i < renderer.materials.Length; i++)
            {
                if (renderer.materials[i].shader.name == "PRD/Stage")
                {
                    overrideMaterials[i] = new Material(Shader.Find("PRD/FriendsShaderV2"));
                    {
                        overrideMaterials[i].SetTexture("_BaseMap", renderer.materials[i].mainTexture);
                        overrideMaterials[i].SetTexture("_1st_ShadeMap", renderer.materials[i].mainTexture);
                    }
                    overrideMaterials2[i] = new Material(renderer.materials[i]);
                    {
                        overrideMaterials2[i].SetTexture("_ShadowTex", null);
                    }
                }
                else
                {
                    overrideMaterials[i] = overrideMaterials2[i] = renderer.materials[i];
                }
            }
            AddMaterialVariant(renderer, renderer.materials);
            AddMaterialVariant(renderer, overrideMaterials);
            AddMaterialVariant(renderer, overrideMaterials2);
        }

        SettingsPanel = UIKF3StaticSettings.Create(this);
        InstantiatedObjects.Add(SettingsPanel.gameObject);
    }

    public void PauseAll()
    {
        foreach (var par in transform.GetComponentsInChildren<ParticleSystem>())
        {
            par.Pause();
        }
        foreach (var anim in transform.GetComponentsInChildren<Animator>())
        {
            anim.speed = 0;
        }
        paused = true;
    }

    public void PlauseAll()
    {
        if (paused)
            UnPauseAll();
        else
            PauseAll();
    }

    public void UnPauseAll()
    {
        foreach (var par in transform.GetComponentsInChildren<ParticleSystem>())
        {
            par.Play();
        }
        foreach (var anim in transform.GetComponentsInChildren<Animator>())
        {
            anim.speed = 1;
        }
        paused = false;
    }

    public void ReStartAll()
    {
        foreach (var par in transform.GetComponentsInChildren<ParticleSystem>())
        {
            par.time = 0;
            par.Play();
        }
        foreach (var anim in transform.GetComponentsInChildren<Animator>())
        {
            anim.Play(anim.GetCurrentAnimatorStateInfo(0).shortNameHash, 0, 0);
            anim.speed = 1;
        }
        paused = false;
    }

    public void ToggleLines()
    {
        bool value = false;
        foreach(var linePoint in linePoints)
        {
            value = !linePoint.Key.GetComponent<LineRenderer>().enabled;
            break;
        }
        foreach (var linePoint in linePoints)
        {
            linePoint.Key.GetComponent<LineRenderer>().enabled = value;
        }
    }

    ////Set up UI knobs for every sub-objects of an animated effect
    //public void BuildHierarchy()
    //{
    //    foreach (var par in transform.GetComponentsInChildren<ParticleSystem>())
    //    {
    //        if (par.transform.GetComponent<UIHandle>() == null)
    //        {
    //            par.gameObject.layer = 0;
    //            par.gameObject.AddComponent<UIHandleParticle>()
    //                .Init(par.gameObject).SetScale(1f).SetColor(Color.blue);
    //            NewLine(par.transform.parent, par.transform, 0.01f, Color.blue);
    //        }
    //    }
    //    foreach (var rend in transform.GetComponentsInChildren<Renderer>())
    //    {
    //        if (rend.transform.parent.GetComponent<UIHandle>() == null)
    //        {
    //            Renderers.Add(rend);
    //            rend.transform.parent.gameObject.layer = 0;
    //            rend.transform.parent.gameObject.AddComponent<UIHandleDetachable>()
    //                .Init(rend.transform.parent.gameObject).SetScale(1f).SetColor(Color.gray);
    //            NewLine(transform, rend.transform.parent, 0.01f, Color.gray);
    //            DetachableObjects.Add(rend.transform.gameObject);
    //        }
    //    }
    //}

    //public GameObject DetachObject(int index)
    //{
    //    return DetachObject(DetachableObjects[index]);
    //}

    //public GameObject DetachObject(GameObject go)
    //{
    //    var detached = Instantiate(go);
    //    var knobs = detached.GetComponentsInChildren<UIHandle>();
    //    UIHandle knob = null;
    //    for (int i = knobs.Length - 1; i >= 0; i--)
    //    {
    //        knob = knobs[i];
    //        if(knob.GetType() == typeof(UIHandleParticle))
    //        {
    //            Destroy(knob.ClearForDeletion());
    //            DestroyImmediate(knob.gameObject);
    //        }
    //        else
    //        {
    //            Destroy(knob.ClearForDeletion());
    //        }
    //    }
    //    var container = detached.AddComponent<KF3StaticContainer>();
    //    detached.transform.position = go.transform.position;
    //    detached.transform.rotation = go.transform.rotation;
    //    detached.name = go.name + "_Detached";
    //    container.CanBeSaved = false;
    //    Destroy(detached.GetComponent<UIHandle>().ClearForDeletion());
    //    knob = detached.AddComponent<UIHandleFurniture>()
    //        .Init(detached).SetDefaults(Vector3.zero, Vector3.zero, Vector3.one);
    //    var renderers = detached.GetComponentsInChildren<Renderer>().ToList();
    //    renderers.Remove(detached.GetComponent<Renderer>());
    //    foreach (var rend in renderers)
    //    {
    //        rend.gameObject.layer = 0;
    //        rend.gameObject.AddComponent<UIHandleDetachable>()
    //            .Init(rend.gameObject).SetColor(Color.gray).SetScale(1).SetName(detached.name + "_part");
    //        rend.enabled = true;
    //        //var go2 = container.NewLine(rend.transform, rend.transform.parent, 0.01f, Color.gray);
    //        //go2.name = rend.transform.name + " -> " + rend.transform.parent.name;
    //    }
    //    knob.ScaleReset();
    //    return detached;
    //}

    public GameObject NewLine(Transform point1, Transform point2, float width, Color color)
    {
        if(lineMaterial == null)
        {
            lineMaterial = new Material(Shader.Find("Legacy Shaders/Particles/Alpha Blended Premultiply"));
        }
        GameObject go = new GameObject("line");
        go.layer = 5;
        go.transform.SetParent(this.transform);
        var lr = go.AddComponent<LineRenderer>();
        lr.startWidth = lr.endWidth = width;
        lr.startColor = lr.endColor = color;
        lr.sharedMaterial = lineMaterial;

        linePoints.Add(go, new Transform[] { point1, point2 });
        return go;
    }

    private void Update()
    {
        foreach (var kv in linePoints)
        {
            var lr = kv.Key.GetComponent<LineRenderer>();
            for (int i = 0; i < kv.Value.Length; i++)
            {
                lr.SetPosition(i, kv.Value[i].position);
            }
        }
    }

    public void AddMaterialVariant(Renderer renderer, Material[] materialVariant)
    {
        if (!_materialVariants.ContainsKey(renderer))
        {
            _materialVariants.Add(renderer, new List<Material[]>());
        }

        _materialVariants[renderer].Add(materialVariant);
    }

    public void SetMaterialVariant(int index)
    {
        foreach (var keyValue in _materialVariants)
        {
            keyValue.Key.materials = keyValue.Value[index];
        }
    }

    protected override void OnDestroy()
    {
        Destroy(lineMaterial);
        foreach(var material in _materialVariants)
        {
            foreach(var material1 in material.Value)
            {
                foreach (var material2 in material1)
                {
                    Destroy(material2);
                }
            }
        }
        base.OnDestroy();
    }

    public override void Select()
    {
        SettingsPanel.gameObject.SetActive(true);
    }

    public override void Deselect()
    {
        SettingsPanel.gameObject.SetActive(false);
    }
}
