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

public class LeafHandler : MonoBehaviour {
    public int NumLeaves = 0;
    public int MaxLeaves = 700;

    private HashSet<LeafPhysics> leafs = new HashSet<LeafPhysics>();

    public void AddLeaf(LeafPhysics l)
    {
        leafs.Add(l);
        NumLeaves = leafs.Count;
    }

    public void RemoveLeaf(LeafPhysics l)
    {
        leafs.Remove(l);
        NumLeaves = leafs.Count;
    }

    private SimpleTimer timer;
    private SimpleTween tween;
    // Use this for initialization
    void Start () {
        timer = new SimpleTimer();
        tween = new SimpleTween();
        //WaitForNextEvent();
        PickNextEvent();
	}

    private void WaitForNextEvent()
    {
        timer.Start(UnityEngine.Random.Range(7.0f, 20.0f), PickNextEvent);
    }

    private Vector3 windForce = new Vector3();
    private Vector2 whirlwindCenter = new Vector3();
    private float whirlwindRadius = 0;
    private float whirlwindForce = 0;
    private float whirlwindForceUp = 0;

    private void PickNextEvent()
    {
        int eventType = UnityEngine.Random.Range(0, 2);
        switch (eventType)
        {
            case 0:
                {
                    // wind
                    float windAngle = UnityEngine.Random.Range(0, Mathf.PI * 2);
                    Vector3 windVector = new Vector3(Mathf.Sin(windAngle), 0, Mathf.Cos(windAngle));
                    windVector.y = UnityEngine.Random.Range(0.8f, 1.2f);
                    float windStrength = UnityEngine.Random.Range(1.1f, 1.5f);
                    float fadeTime = UnityEngine.Random.Range(1.0f, 2.0f);
                    float windTime = UnityEngine.Random.Range(4.0f, 7.0f);

                    Debug.LogError("WIND: V:" + windVector + " S:" + windStrength + " F:" + fadeTime + " T:" + windTime);

                    tween.Init(v =>
                    {
                        windForce = windVector * windStrength * v;
                    }, SimpleTween.EaseLinear, 0, 1, fadeTime);
                    tween.OnFinish = () =>
                    {
                        tween.Init(v =>
                        {
                            //windForce = windVector * windStrength * (Mathf.Sin(v * 25) + 1) * 0.2f;
                        }, SimpleTween.EaseLinear, 0, windTime, windTime);
                        tween.OnFinish = () =>
                        {
                            tween.Init(v =>
                            {
                                windForce = windVector * windStrength * v;
                            }, SimpleTween.EaseLinear, 1, 0, fadeTime);
                            tween.OnFinish = () =>
                            {
                                WaitForNextEvent();
                            };
                        };

                    };
                    break;
                }
            case 1:
                {
                    // whirlwind
                    whirlwindCenter = UnityEngine.Random.insideUnitCircle * UnityEngine.Random.Range(0, 6.0f);
                    whirlwindRadius = UnityEngine.Random.Range(3.0f, 4.0f);
                    float maxWhirlwindForce = UnityEngine.Random.Range(1.0f, 1.6f);
                    float maxWhirlwindForceUp = UnityEngine.Random.Range(0.3f, 0.8f);

                    float fadeTime = UnityEngine.Random.Range(2.0f, 4.0f);
                    float windTime = UnityEngine.Random.Range(6.0f, 8.0f);

                    Debug.LogError("WHIRLWIND: C:" + whirlwindCenter + " R:" + whirlwindRadius + " F:" + maxWhirlwindForce + " U:" + maxWhirlwindForceUp + " F:" + fadeTime + " T:" + windTime);

                    tween.Init(v =>
                    {
                        whirlwindForce = maxWhirlwindForce * v;
                        whirlwindForceUp = maxWhirlwindForceUp * v;
                    }, SimpleTween.EaseLinear, 0, 1, fadeTime);
                    tween.OnFinish = () =>
                    {
                        tween.Init(v =>
                        {
                            //windForce = windVector * windStrength * (Mathf.Sin(v * 25) + 1) * 0.2f;
                        }, SimpleTween.EaseLinear, 0, windTime, windTime);
                        tween.OnFinish = () =>
                        {
                            tween.Init(v =>
                            {
                                whirlwindForce = maxWhirlwindForce * v;
                                whirlwindForceUp = maxWhirlwindForceUp * v;
                            }, SimpleTween.EaseLinear, 1, 0, fadeTime);
                            tween.OnFinish = () =>
                            {
                                WaitForNextEvent();
                            };
                        };

                    };

                    break;
                }
        }
    }

    // Update is called once per frame
    void Update () {
        bool hasWind = windForce.sqrMagnitude > 0.00001f;
        bool hasWhirlwind = whirlwindForce > 0;
        Vector2 windDir = new Vector2(windForce.x, windForce.y);
        windDir.Normalize();

        float distAway = 9.0f;


        foreach (LeafPhysics leaf in leafs)
        {
            if (hasWind && (UnityEngine.Random.Range(0, 1f) < 0.25f || !leaf.Resting))
            {
                float amount = Vector2.Dot(new Vector2(leaf.Body.velocity.x, leaf.Body.velocity.z), windDir);
                amount = Math.Max(0, Math.Min(1, 8 - amount));
                leaf.Body.AddForce(new Vector3(windForce.x * UnityEngine.Random.Range(0.75f, 1.0f),
                                                windForce.y * UnityEngine.Random.Range(0.9f, 1.0f),
                                                windForce.z * UnityEngine.Random.Range(0.75f, 1.0f)) * Time.deltaTime * 60 * (leaf.Resting ? 3.0f : 0.4f));
            }
            Vector2 d = new Vector2(leaf.transform.position.x, leaf.transform.position.z);

            if (hasWhirlwind && (UnityEngine.Random.Range(0, 1f) < 0.15f || !leaf.Resting))
            {
                Vector2 offset = new Vector2(leaf.transform.position.x, leaf.transform.position.z) - whirlwindCenter;
                Vector2 offsetN = offset.normalized;
                float distFrom = offset.magnitude;

                if (distFrom < whirlwindRadius)
                {

                    Vector2 tangent = new Vector2(-offsetN.y, offsetN.x);
                    Vector2 force = tangent * (whirlwindRadius - distFrom) * whirlwindForce + offset * -0.9f;

                    Vector3 force3D = new Vector3(force.x, whirlwindForceUp * (whirlwindRadius - distFrom + 2), force.y);

                    leaf.Body.AddForce(new Vector3(force3D.x * UnityEngine.Random.Range(0.55f, 1.0f),
                                                   force3D.y * UnityEngine.Random.Range(0.6f, 1.0f),
                                                   force3D.z * UnityEngine.Random.Range(0.55f, 1.0f)) * Time.deltaTime * 60 * (leaf.Resting ? 3.0f : 0.4f));

                }


            }

            if (d.magnitude > distAway && !leaf.Resting)
            {
                //leaf.Body.apply
            }
        }

	}
}
