using System.Collections;
using System.Collections.Generic;
using System.IO.Pipes;
using UnityEngine;
using System.Linq;

public class PipeGroup : MonoBehaviour
{

    [SerializeField] private Pipe[] pipes;
    [Range(.01f, .2f)]
    [SerializeField] private float successThreshold;

    [SerializeField] private float timeWithinThresholdForSuccess;

    [SerializeField] private GameEvent enterThresholdEvent;
    [SerializeField] private GameEvent exitThresholdEvent;
    [SerializeField] private GameEvent successEvent;

    [SerializeField] private GameObject audioSourceGameObject;

    private bool isWithinThreshold = false;
    private float successCounter;
    private bool isSolved = false;

    // Start is called before the first frame update
    void Start()
    {
        successCounter = timeWithinThresholdForSuccess;
    }

    // Update is called once per frame
    void Update()
    {
        if (isSolved)
        {
            return;
        }
        if (isWithinThreshold)
        {
            successCounter = Mathf.Clamp(successCounter - Time.deltaTime, 0, timeWithinThresholdForSuccess);
            if (successCounter == 0)
            {
                successEvent.Raise();
                isSolved = true;
                // disable the levers
            }
        }
    }

    public void ChangeWaterForPipe(float amount, Pipe pipe)
    {
        float changedAmount = pipe.ChangeWaterLevel(amount);
        // distribute that changed amount between other two pipes
        List<Pipe> pipesToDistribute = pipes.Where(p => p != pipe).ToList();
        while (pipesToDistribute.Count > 0)
        {
            float amountForPipe = -(changedAmount / (pipesToDistribute.Count));
            Pipe p = pipesToDistribute[0];
            pipesToDistribute.RemoveAt(0);
            float changed = p.ChangeWaterLevel(amountForPipe, true);
            changedAmount -= changed;
        }
        
        foreach (Pipe p in pipes)
        {
            if (p == pipe)
            {
                continue;
            }
        }

        this.CheckPipeThreshold();
        audioSourceGameObject.GetComponent<LerpVolume>().RaiseVolumeForTime(1f, .25f);

    }

    private void CheckPipeThreshold()
    {
        // get waterLevel of each pipe and see how close they are to each other
        bool withinThreshold = pipes.Count(p => this.matchesOtherPipes(p)) == pipes.Length;

        if (withinThreshold && !this.isWithinThreshold)
        {
            this.isWithinThreshold = true;
            // fire the event
            enterThresholdEvent.Raise();
        }
        else if (!withinThreshold && isWithinThreshold)
        {
            isWithinThreshold = false;
            // fire exit event
            exitThresholdEvent.Raise();
        }
    }

    private bool matchesOtherPipes(Pipe pipe)
    {
        foreach (Pipe p in pipes.Where(p => p != pipe))
        {
            if (Mathf.Abs(p.WaterLevel - pipe.WaterLevel) > successThreshold)
            {
                return false;
            }
        }

        return true;
    }
}
