using UnityEngine;
using Saltosion.OneWeapon.Utils;
using Saltosion.OneWeapon.Player;

namespace Saltosion.OneWeapon.Effects {
    public class Explodable : MonoBehaviour {
        public GameObject[] BodypartPrefabs;
        public bool DebugExplode = false;
        public int ParticlesPerBodypart = 70;
        public float BodypartMinCount = 1;
        public float BodypartMaxCount = 1;
        public DebrisType DebrisType;
        public bool IsFurniture = true;

        private CameraFX CameraFX;
        private PlayerFun PlayerFun;
        private Transform ExplodableContainer;

        private bool DestroyedAlready = false;

        private void Start() {
            foreach (GameObject Obj in BodypartPrefabs) {
                Rigidbody2D Body = Obj.GetComponent<Rigidbody2D>();
                if (Body == null) {
                    Debug.LogError($"'{Obj.name}' is an explodable bodypart, and does not have a Rigidbody2D!\n\n" +
                        "Therefore it cannot be exploded. Please provide one.\n" +
                        "Following is the GameObject that needs to get a Rigidbody2D.");
                }
            }

            CameraFX = Camera.main.GetComponent<CameraFX>();
            PlayerFun = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerFun>();
            ExplodableContainer = GameObject.FindGameObjectWithTag("BodypartContainer").transform;
        }

        private void Update() {
            if (DebugExplode) {
                DebugExplode = false;
                Explode(false, false);
            }
        }

        public void Explode(bool destroyGameObject, bool causedByPlayerAttack) {
            // Destroying the object during explosion implies that it can explode only once,
            // but Destroy() doesn't happen instantly, so here's a guard for that.
            if (destroyGameObject && DestroyedAlready) {
                return;
            }

            int Count = (int)(BodypartMinCount + (BodypartMaxCount - BodypartMinCount) * Random.value);
            for (int i = 0; i < Count; i++) {
                GameObject Obj = BodypartPrefabs[i % BodypartPrefabs.Length];

                float DirectionRadians = Random.value * Mathf.PI * 2.0f;
                Vector2 Direction = new Vector2(Mathf.Cos(DirectionRadians), Mathf.Sin(DirectionRadians));
                if (!Options.CensorGore || DebrisType != DebrisType.Blood) {
                    GameObject NewObj = Instantiate(Obj, transform.position, new Quaternion(), ExplodableContainer);
                    Rigidbody2D Bodypart = NewObj.GetComponent<Rigidbody2D>();
                    if (Bodypart == null) {
                        continue;
                    }
                    float Force = 0.5f + Random.value * 0.5f;
                    Bodypart.AddForce(Direction * Force, ForceMode2D.Impulse);
                    Bodypart.AddTorque((Random.value - 0.5f) * Force, ForceMode2D.Impulse);
                }

                DebrisLauncher.Splatter(DebrisType, transform.position + (Vector3)Direction * 0.5f, Vector2.zero, ParticlesPerBodypart, 50f, 360f);
            }

            if (causedByPlayerAttack) {
                if (!IsFurniture) {
                    PlayerFun.GainKill();
                }
                PlayerFun.Explosion(IsFurniture);
            }
            CameraFX.ScreenShake(10);

            if (destroyGameObject) {
                Destroy(gameObject);
                DestroyedAlready = true;
            }
        }
    }
}
