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

public class Campfire : MonoBehaviour {
    public GameState GameState;
    public Light DynamicLight;
    public Flame Flame;
    public CampfireSfx Sfx;
    public float GoodFuelAmount;
    [Tooltip("The light turns this color when Fuel < GoodFuelAmount. Otherwise it'll be as it is in the editor.")]
    public Color TooLowFuelColor;
    public float RandomVarianceDuration;
    public float RandomVarianceMagnitude;
    [Tooltip("How long of a break the campfire takes between eating logs, if multiple are placed on it.")]
    public float LogBurningCooldown;

    [Header("Out-of-camp mechanic")]
    public float CampRadius;
    [Tooltip("Fuel won't go below this threshold if the player is outside of the camp.")]
    public float OutOfCampFuelThreshold;
    public float OutOfCampFuelRateMultiplier;

    [Header("Runtime values")]
    public float Fuel;
    public bool OutOfCamp = false;
    public float TimeToEnd {
        get {
            return Fuel - 0.7f;
        }
    }

    private Color EnoughFuelColor;
    private float FullRange;

    private float RandomVariance = 0;
    private float NextRandomVariance = 0;
    private float LastRandomVarianceChange = 0;

    private List<Item> LogQueue = new List<Item>();
    private float NextLogTime = 0;

    private Transform Player;

    private void Awake() {
        EnoughFuelColor = DynamicLight.color;
        FullRange = DynamicLight.range;
        Player = GameObject.FindGameObjectWithTag("Player").transform;
    }

    private void Update() {
        TickFuel();

        if (LogQueue.Count > 0 && Time.time > NextLogTime) {
            if (BurnLog(LogQueue[0])) {
                LogQueue.RemoveAt(0);
                if (LogQueue.Count > 0) {
                    NextLogTime = Time.time + LogQueue[0].Quality.BurnTime;
                }
            }
        }

        if (Time.time - LastRandomVarianceChange > RandomVarianceDuration) {
            NextRandomVariance = (Random.value - 0.5f) * 2f * RandomVarianceMagnitude;
            LastRandomVarianceChange = Time.time;
        }
        RandomVariance = Mathf.Lerp(RandomVariance, NextRandomVariance, (Time.time - LastRandomVarianceChange) / RandomVarianceDuration);

        DynamicLight.range = Fuel / GoodFuelAmount / 2f * FullRange + RandomVariance;
        DynamicLight.color = Color.Lerp(DynamicLight.color, Fuel < GoodFuelAmount ? TooLowFuelColor : EnoughFuelColor, 10f * Time.deltaTime);
        Flame.Aliveness = Mathf.Log(Mathf.Max(0.01f, TimeToEnd), 10) / 2f;

        if (Fuel <= 0) {
            GameState.Current = State.GameOver;
        }
    }

    private void TickFuel() {
        OutOfCamp = true;
        if ((Player.position - transform.position).magnitude < CampRadius) {
            // Player is inside of the camp, tick fuel at normal rate
            Fuel -= Time.deltaTime;
            OutOfCamp = false;
        } else if (Fuel > OutOfCampFuelThreshold) {
            // Player is outside of the camp, and the campfire is within safe levels, tick fuel at a slow rate
            Fuel -= Time.deltaTime * OutOfCampFuelRateMultiplier;
        }
        Fuel = Mathf.Max(0, Fuel);
    }

    private bool BurnLog(Item burnable) {
        if (Fuel >= GoodFuelAmount * 2) {
            return false;
        } else {
            Fuel += burnable.Quality.FuelValue * Mathf.Max(0.5f, (2 - Fuel / GoodFuelAmount));
            Destroy(burnable.gameObject);
            return true;
        }
    }

    private void OnCollisionEnter(Collision c) {
        if (c.collider.attachedRigidbody != null && c.collider.attachedRigidbody) {
            Item Burnable = c.collider.attachedRigidbody.GetComponent<Item>();
            if (Burnable != null && !LogQueue.Contains(Burnable)) {
                Flame.AddFuelEffect += Burnable.Quality.FlameEffect;
                Sfx.ActiveBurn += Burnable.Quality.SoundEffect;
                if (LogQueue.Count == 0) {
                    NextLogTime = Time.time + Burnable.Quality.BurnTime;
                }
                LogQueue.Add(Burnable);
            }
        }
    }

    private void OnCollisionExit(Collision c) {
        if (c.collider.attachedRigidbody != null && c.collider.attachedRigidbody) {
            Item Burnable = c.collider.attachedRigidbody.GetComponent<Item>();
            if (Burnable != null) {
                LogQueue.Remove(Burnable);
            }
        }
    }
}
