using UnityEngine;
using UnityEngine.SceneManagement;
using Saltosion.OneWeapon.Utils;

namespace Saltosion.OneWeapon.Effects {
    public enum DebrisType {
        Blood, Structural, Wood
    }

    public class DebrisLauncher : MonoBehaviour {
        private static DebrisLauncher Singleton;
        private static int SingletonSceneIndex = -1;

        public GameObject StructuralParticlePrefab;
        public GameObject WoodParticlePrefab;
        public GameObject BloodParticlePrefab;
        public GameObject CensoredBloodParticlePrefab;
        public Transform ParticleRoot;
        public int MaxParticles;
        public bool DebugLaunch = false;

        public static void Splatter(DebrisType Type, Vector2 origin, Vector2 direction, int particleCount, float force, float degrees, bool sticky = true) {
            int ParticleCount = (int)(particleCount * (Type == DebrisType.Blood ? Singleton.GetBloodParticleCountMultiplier() : 1));
            LaunchParticles(Singleton.GetDebrisPrefab(Type), origin, direction, particleCount, force, degrees, sticky);
        }

        private static void LaunchParticles(GameObject prefab, Vector2 origin, Vector2 direction, int particleCount, float force, float degrees, bool sticky) {
            for (int i = 0; i < particleCount; i++) {
                if (Singleton.ParticleRoot.childCount >= Singleton.MaxParticles) {
                    Destroy(Singleton.ParticleRoot.GetChild((int)(Random.value * Singleton.ParticleRoot.childCount)).gameObject);
                }
                GameObject Obj = Instantiate(prefab, origin, new Quaternion(), Singleton.ParticleRoot);
                DebrisParticle Particle = Obj.GetComponent<DebrisParticle>();
                float Intensity = Mathf.Pow(Random.value, 0.8f) * force;
                float Cone = degrees / 360.0f;
                float Offset = Mathf.Atan2(direction.y, direction.x);
                float Radians = Offset + Mathf.Pow(Cone * (Random.value - 0.5f) * 2f, 2f) * Mathf.PI * 2.0f;
                Particle.LaunchForce = new Vector2(Mathf.Cos(Radians), Mathf.Sin(Radians)) * Intensity;
                Particle.GetsStuck = sticky && Random.value < 0.5;
            }
        }

        private void Start() {
            int Index = SceneManager.GetActiveScene().buildIndex;
            if (SingletonSceneIndex == Index) {
                Debug.LogWarning($"The scene '{SceneManager.GetActiveScene().name}' has multiple DebrisLaunchers!\nOnly the last to run Start() will be used.");
            }
            SingletonSceneIndex = Index;
            Singleton = this;
        }

        private GameObject GetDebrisPrefab(DebrisType Type) {
            switch (Type) {
                case DebrisType.Blood:
                    return Options.CensorGore ? CensoredBloodParticlePrefab : BloodParticlePrefab;
                case DebrisType.Structural:
                    return StructuralParticlePrefab;
                case DebrisType.Wood:
                    return WoodParticlePrefab;
                default:
                    return CensoredBloodParticlePrefab;
            }
        }

        private float GetBloodParticleCountMultiplier() {
            return Options.CensorGore ? 0.1f : 1.5f;
        }
    }
}
