using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Thinksquirrel.CShake;

public class Ball : MonoBehaviour
{
    public static Ball instance;

    public Rigidbody myBody;
    Collider collie;

    bool hasPossessor;
    Soccerman possessor;

    public PhysicMaterial bounceMaterial;
    public PhysicMaterial stickyMaterial;

    List<Collider> nearbyPlayers = new List<Collider>();

    CameraShake shaker;

    SpriteRenderer sr;
    Collider c;

    //public GameObject particleHitRed;
    //public GameObject particleHitBlue;

    ParticleSystem blueHit;
    ParticleSystem redHit;

    TrailRenderer trail;
    //Color[] trailColors;
    public Material[] redToBlueMaterials;
    public Material[] blueToRedMaterials;
    Material activeTrailMaterial;
    int materialIndex = 0;

    bool ballIsRed = true;

    public List<Soccerman> players;
    const float goalForce = 12.0f;

    void Awake()
    {
        instance = this;
        myBody = GetComponent<Rigidbody>();
    }

	// Use this for initialization
	void Start ()
    {
        collie = GetComponent<Collider>();
        shaker = Camera.main.GetComponent<CameraShake>();

        sr = GetComponentInChildren<SpriteRenderer>();
        c = GetComponent<Collider>();
        blueHit = transform.Find("BlueHit").GetComponent<ParticleSystem>();
        redHit = transform.Find("RedHit").GetComponent<ParticleSystem>();

        foreach (Renderer r in GetComponentsInChildren<Renderer>())
        {
            r.material.renderQueue = 8003;
        }

        foreach (Material m in redToBlueMaterials)
            m.renderQueue = 8004;

        trail = GetComponent<TrailRenderer>();

        //Invoke("NextMaterial", 0.2f);

        //trail.material = trailMaterials[2];
    }

    void NextRtBMaterial()
    {
        materialIndex++;
        if (materialIndex > redToBlueMaterials.Length - 1)
            materialIndex = 0;

        activeTrailMaterial = redToBlueMaterials[materialIndex];
        trail.material = activeTrailMaterial;

        if(materialIndex < redToBlueMaterials.Length-1)
            Invoke("NextRtBMaterial", 0.1f);
    }

    void PrevRtBMaterial()
    {
        materialIndex--;
        if (materialIndex < 0 )
            materialIndex = blueToRedMaterials.Length - 1;

        activeTrailMaterial = blueToRedMaterials[materialIndex];
        trail.material = activeTrailMaterial;

        if (materialIndex > 0)
            Invoke("PrevRtBMaterial", 0.1f);
    }
	
    public void RedToBlue()
    {
        ballIsRed = false;
        materialIndex = 0;
        activeTrailMaterial = redToBlueMaterials[materialIndex];
        Invoke("NextRtBMaterial", 0.1f);
    }

    public void BlueToRed()
    {
        ballIsRed = true;
        materialIndex = blueToRedMaterials.Length - 1;
        activeTrailMaterial = blueToRedMaterials[materialIndex];
        Invoke("PrevRtBMaterial", 0.1f);
    }

	// Update is called once per frame
	void Update ()
    {
        //if (Input.GetKeyDown(KeyCode.M))
        //{
        //    materialIndex = 0;
        //    activeTrailMaterial = redToBlueMaterials[materialIndex];
        //    Invoke("NextRtBMaterial", 0.1f);
        //}

        //if(Input.GetKeyDown(KeyCode.N))
        //{
        //    materialIndex = blueToRedMaterials.Length - 1;
        //    activeTrailMaterial = blueToRedMaterials[materialIndex];
        //    Invoke("PrevRtBMaterial", 0.1f);
        //}

        //if(hasPossessor)
        //   {
        //       transform.position = possessor.ballPos;
        //   }
    }

    void FixedUpdate()
    {
        //Debug.Log(myBody.velocity.magnitude);

        myBody.velocity = Vector3.ClampMagnitude(myBody.velocity, 20.0f);
    }

    public void Shoot(Vector3 forceToAdd)
    {
        //myBody.isKinematic = false;
        //transform.SetParent(null);

        //hasPossessor = false;
        //possessor = null;

        myBody.AddForce(forceToAdd);
    }

    public void AddMagnetForce(Vector3 forceToAdd)
    {
        myBody.AddForce(forceToAdd);
    }

    void MakeBouncy() { collie.material = bounceMaterial; }
    void MakeSticky() { collie.material = stickyMaterial; }

    public void AddPlayer(Collider c)
    {
        if (!nearbyPlayers.Contains(c))
            nearbyPlayers.Add(c);
    }

    public void RemovePlayer(Collider c)
    {
        if (nearbyPlayers.Contains(c))
            nearbyPlayers.Remove(c);
    }

    public void RefreshMaterial()
    {
        if (nearbyPlayers.Count > 0)
            MakeSticky();
        else
            MakeBouncy();
    }

    void OnCollisionEnter(Collision other)
    {
        if(other.collider.tag == "Player")
        {
            Vector3 rnd = UnityEngine.Random.onUnitSphere.normalized;
            rnd.y = 0;

            shaker.Shake(CameraShake.ShakeType.CameraMatrix, 1, rnd * 1.2f, Vector3.one, 0.3f, 30, 0.5f, 1.0f, true);
            Soccerman s = other.collider.transform.parent.GetComponent<Soccerman>();
            if (s.teamIndex == 0)
            {
                //GameObject obj = (GameObject)Instantiate(particleHitBlue, other.contacts[0].point, particleHitBlue.transform.rotation);
                ////obj.transform.parent = transform;
                //ParticleSystem ps = obj.GetComponent<ParticleSystem>();

                //Destroy(obj, 2.0f);

                blueHit.Play();

                if (ballIsRed)
                    RedToBlue();
            }
            else
            {
                //GameObject obj = (GameObject)Instantiate(particleHitRed, other.contacts[0].point, particleHitRed.transform.rotation);
                //Destroy(obj, 2.0f);

                redHit.Play();

                if (!ballIsRed)
                    BlueToRed();
            }
            //blueHit.Play();
        }
        else
        {
            Vector3 rnd = UnityEngine.Random.onUnitSphere.normalized;
            rnd.y = 0;

            shaker.Shake(CameraShake.ShakeType.CameraMatrix, 1, rnd * 0.5f, Vector3.one, 0.05f, 80, 0.5f, 1.0f, true);
        }
    }

    public void EnteredGoal()
    {
        myBody.velocity = Vector3.zero;
        myBody.angularVelocity = Vector3.zero;
        myBody.isKinematic = true;

        c.enabled = false;
        sr.enabled = false;

        Invoke("SpawnNewBall", 3.0f);

        Vector3 rnd = UnityEngine.Random.onUnitSphere.normalized;
        rnd.y = 0;

        if(transform.position.x < 0)
        {
            if (rnd.x < 0)
                rnd.x *= -1;
        }
        else
        {
            if (rnd.x > 0)
                rnd.x *= -1;
        }

        shaker.Shake(CameraShake.ShakeType.CameraMatrix, 4, rnd * 2.5f, Vector3.one, 2.0f, 40, 0.25f, 1.0f, false);

        foreach(Soccerman s in players)
        {
            //s.myBody.AddExplosionForce(goalForce, transform.position, 5.0f, 0.0f, ForceMode.Force);


            Vector3 dir = transform.position - s.transform.position;
            //Vector3 dir = -Vector3.right;
            float percent = 1 - (dir.magnitude / 5.0f);
            //float percent = 1.0f;

            //s.myBody.AddForce(dir * goalForce * percent);
            s.myBody.velocity = -dir * goalForce * percent;
            s.isExploding = true;
        }

        Invoke("SetToNormTime", 6.0f * Time.timeScale);
    }

    void SetToNormTime()
    {
        Time.timeScale = 0.9f;
        foreach (Soccerman s in players)
            s.isExploding = false;
    }

    public void SpawnNewBall()
    {
        Vector3 pos = transform.position;
        pos.x = 0;
        pos.z = 0;
        transform.position = pos;

        myBody.isKinematic = false;
        myBody.velocity = Vector3.zero;
        myBody.angularVelocity = Vector3.zero;

        c.enabled = true;
        sr.enabled = true;
    }
}
