using KF3.Containers;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class KF3CeruleanContainer : KF3CharacterContainer
{
    public UIKF3CharacterPanel CharacterPanel;

    public static IEnumerator CreateAsync(string modelName, string animationSetName, System.Action<KF3CeruleanContainer> callback = null)
    {
        GameObject go = new GameObject(modelName);
        var container = go.AddComponent<KF3CeruleanContainer>();
        yield return container.BuildGeneral(modelName, animationSetName);
        UIHandleCerulean.CreateAsChild(container);
        Main.SelectObject(container);
        container.LoadInProgress = false;
        callback?.Invoke(container);
    }

    public override void SetAnimationReferences()
    {
        if (BodyAnimation)
        {
            BodySimpleAnimation = Body.GetComponentInChildren<SimpleAnimation>();
            if (Main.OverrideClip != null)
            {
                foreach (var anim in BodyAnimation.prefabAnimeList)
                {
                    anim.clip = Main.OverrideClip;
                }
            }
            Body.refAnimationObj = BodyAnimation.gameObject;
            Body.JoinReferenceParam();
        }
        else
        {
            Error.Log(Color.blue, "Body Animations Missing");
        }
    }

    public override void SetBones()
    {
        var bones = Body.boneList;
        var extraBones = bones.Where(b => b.name.Contains("osg")).ToList();

        foreach (var bone in bones)
        {
            if (!bone.gameObject.TryGetComponent(out UIHandle bone1))
            {
                if (bone.GetComponent<Osage>() != null)
                {
                    bone1 = UIHandlePhysicsBone.CreateAsChild(this, bone, new List<SerializableBone.BoneTags>() { SerializableBone.BoneTags.Dynamic }).SetColor(Color.cyan).SetName(bone.name);
                }
                else
                {
                    bone1 = UIHandleBone.CreateAsChild(this, bone, new List<SerializableBone.BoneTags>()).SetColor(Color.gray).SetName(bone.name);
                }
            }
        }
    }

    public override void DoStuff()
    {
        foreach (Renderer r in GetComponentsInChildren<Renderer>())
        {
            Material[] overrideMaterials = new Material[r.materials.Length];
            for (int i = 0; i < r.materials.Length; i++)
            {
                overrideMaterials[i] = new Material(Shader.Find("PRD/FriendsShaderV2"));
                if (ModelId >= 40400)
                {
                    overrideMaterials[i].SetTexture("_BaseMap", r.materials[i].GetTexture("_BaseMap"));
                    overrideMaterials[i].SetTexture("_1st_ShadeMap", r.materials[i].GetTexture("_1st_ShadeMap"));
                }
                else if (ModelId >= 40000)
                {
                    overrideMaterials[i].SetTexture("_BaseMap", r.materials[i].mainTexture);
                    overrideMaterials[i].SetTexture("_1st_ShadeMap", r.materials[i].mainTexture);
                }
                else
                {
                    overrideMaterials[i].SetTexture("_BaseMap", r.materials[i].GetTexture("_BaseMap") as Texture2D);
                    overrideMaterials[i].SetTexture("_1st_ShadeMap", r.materials[i].GetTexture("_BaseMap") as Texture2D);
                }
            }
            r.materials = overrideMaterials;
            Renderers.Add(r);
        }

        var charaPanel = CharacterPanel = UIKF3CharacterPanel.Create(this);
        InstantiatedObjects.Add(charaPanel.gameObject);
    }

    public override void PastePose(KeyframeData frame, PoseLoadOptions pasteParams)
    {
        var bones = frame as CharacterKeyframeData;

        this.PlayBodyAnimation("");
        if (pasteParams.Root)
        {
            bones.Root.ApplyTo(transform);
        }
        if (pasteParams.Body)
        {
            foreach (var bone in this.Body.boneList)
            {
                if (pasteParams.Other || bone.GetComponent<Osage>() == null)
                    bones.Bones.FirstOrDefault(b => b.Name == "Body").Bones.FirstOrDefault(b => b.Name == bone.name)?.Transform.ApplyTo(bone, pasteParams);
            }
        }
        if (bones.Renderers != null)
        {
            foreach (var renderer in bones.Renderers)
            {
                var rend = this.Renderers.FirstOrDefault(r => KF3CharacterContainerSerializable.GetRendererName(this, r) == renderer.Name);
                if (rend != null)
                {
                    rend.enabled = renderer.Value;
                }
            }
        }
    }

    public override IEnumerator GetModel(string bodyIdLong, string costumeId)
    {
        KF3AssetLibrary lib = Main.Assets;
        List<KF3AssetBundle> abList = lib.AssetBundles.Where(ab => ab.FileName.StartsWith($"ch_{bodyIdLong}_")).ToList();
        KF3AssetBundle bundle;

        //load body
        bundle = abList.FirstOrDefault(ab => ab.FileName == $"ch_{bodyIdLong}_{costumeId}.prefab");
        yield return lib.LoadAsset(bundle, (ab) =>
        {
            Body = spawnAndGetReferencer(ab);
        });
    }

    public override IEnumerator GetAnimations(string idLong)
    {
        KF3AssetLibrary lib = Main.Assets;
        KF3AssetBundle bundle;
        List<KF3AssetBundle> abList = lib.AssetBundles.Where(ab => ab.FileName.StartsWith($"ch_{idLong}_")).ToList();

        bundle = lib.CeruleanAnimationSets.FirstOrDefault(ab => ab.FileName == $"ch_{idLong}_a_mot.prefab");
        yield return lib.LoadAsset(bundle, (ab) =>
        {
            BodyAnimation = spawnAndGetReferencer(ab);
        });
    }

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

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