using System;
using UnityEngine;
using Object = UnityEngine.Object;

namespace Assets.Source.Utils
{
    public static class Instantiator
    {
        public static event Action<Object, Transform> OnInstantiate;

        public static GameObject InstantiateGO(string name)
        {
            var newGO = new GameObject(name);
            OnInstantiate?.Invoke(newGO, newGO.transform);
            return newGO;
        }

        public static GameObject InstantiateGO(GameObject prefab)
        {
            var go = Object.Instantiate(prefab);
            return go;
        }

        public static T Instantiate<T>(T prefab) where T : Object
        {
            return Instantiate(prefab, Vector3.zero, Quaternion.identity, null);
        }

        public static T Instantiate<T>(T prefab, Vector3 position) where T : Object
        {
            return Instantiate(prefab, position, Quaternion.identity, null);
        }

        public static T Instantiate<T>(T prefab, Vector3 position, Quaternion rotation) where T : Object
        {
            return Instantiate(prefab, position, rotation, null);
        }

        public static T Instantiate<T>(T prefab, Vector3 position, Quaternion rotation, Transform parent) where T : Object
        {
            T obj = Object.Instantiate(prefab);

            Transform t = obj is GameObject ? (obj as GameObject).transform :
                                              (obj as Component).transform;

            t.position = position;
            t.name = prefab.name;
            t.SetParent(parent);

            OnInstantiate?.Invoke(obj, t);

            // for 'editor cases' spawning
            if (!Application.isPlaying)
            {
                var connected = ConnectToPrefab(prefab, obj, t.gameObject);
                if (connected != null)
                    obj = connected;
            }

            return obj;
        }

        private static T ConnectToPrefab<T>(T prefab, T obj, GameObject cloneGO) where T : Object
        {
            //if (obj is Level)
            //    return null;
            var prefabGO = prefab is GameObject
                ? prefab as GameObject
                : (prefab as Component).gameObject;

            var connectedGO = UnityFakeEditorUtils.ConnectToPrefab(cloneGO.gameObject, prefabGO);
            obj = connectedGO.GetComponent<T>();

            return obj;
        }
    }
}
