using System;
using System.Collections.Generic;
using UniRx;
using UnityEngine;

namespace Hazards
{
    /// <summary>
    /// Fire becomes a child of this object, whenever it is ignited.
    /// </summary>
    public class Ignitable : MonoBehaviour
    {
        private List<Ignitable> neighbourIgnitable = new();
        public BoolReactiveProperty isIgnited = new BoolReactiveProperty(false);

        [SerializeField] private GameObject firePrefab;
        [SerializeField] private float spreadDelay = 6f;

        private CompositeDisposable disposables = new CompositeDisposable();

        private void Start()
        {
            Debug.Log($"I am an Ignitable and have {neighbourIgnitable.Count} neighbours");
        }

        public void AddIgnitableNeighbour(Ignitable neighbour)
        {
            neighbourIgnitable.Add(neighbour);

            // Subscribe to neighbour's ignition state
            neighbour.isIgnited
                .Where(ignited => ignited && !isIgnited.Value) // Only react when neighbour ignites and we're not already ignited
                .SelectMany(ignited => 
                        Observable.Timer(TimeSpan.FromSeconds(spreadDelay))
                            .TakeUntil(neighbour.isIgnited.Where(x => !x)) // Cancel if neighbour is extinguished
                            .Where(_ => !isIgnited.Value) // Final check before igniting
                )
                .Subscribe(_ => Ignite())
                .AddTo(disposables);
        }

        private void OnTriggerStay2D(Collider2D other)
        {
            if (!isIgnited.Value && other.CompareTag("Fire"))
            {
                Ignite();
            }
        }
        
        public void Ignite()
        {
            if (isIgnited.Value) return; // Already ignited
            
            isIgnited.Value = true;
            SpawnFire();
        }

        private void SpawnFire()
        {
            if (firePrefab != null)
            {
                Instantiate(firePrefab, transform.position, Quaternion.identity, transform);
            }
        }

        private void OnDestroy()
        {
            disposables.Dispose();
        }
    }
}