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

public class LightRay : MonoBehaviour
{
    public float speed = 1;

    public Rigidbody2D rbody;

    public Vector2 direction = Vector2.up;
    public SineMotion oscillator;
    public TrailRenderer trail;
    public TrailRenderer glowTrail;
    public CircleCollider2D cCollirder;

    [HideInInspector]
    public Config.RayColor currentRayColor;

    void Update()
    {
        try
        {
            transform.position += (Vector3)(direction * speed * Time.deltaTime);
        }
        catch { }
    }

    List<Collider2D> currentColliders = new List<Collider2D>();
    const int raycastLayerMask = 1 << 9;
    void OnTriggerEnter2D(Collider2D other)
    {
        if (currentColliders.Contains(other))
            return;
        currentColliders.Add(other);

        if(other.CompareTag("Goal"))
        {
            //Check goal color
            if (GameController.Instance.currentGoalColor == currentRayColor)
            {
                GameController.Instance.Win();
            }

            StartCoroutine(Utils.DoDelayed(0.1f, () =>
            {
                DestroyRay();
            }));

        }
        else if(other.CompareTag("Mirror"))
        {
            //Reflect
            print("Collide with mirror!");
            Vector2 startPoint = transform.position;
            //RaycastHit2D hit = Physics2D.Raycast(startPoint, direction.normalized, 100, raycastLayerMask);
            //Vector2 normal = 
            float deg = other.transform.parent.localEulerAngles.z;
            Vector2 normal = new Vector2(Mathf.Cos(deg * Mathf.Deg2Rad), Mathf.Sin(deg * Mathf.Deg2Rad));
            Vector2 newDir = Vector2.Reflect(direction, normal);
            SetDirection(newDir);
        }
        else if (other.CompareTag("MirrorBack"))
        {
            //Absorb
            DestroyRay();
        }
        else if(other.CompareTag("Prism"))
        {
            //Refract
            LevelElement prism = other.gameObject.GetComponent<LevelElement>() ?? other.gameObject.GetComponentInParent<LevelElement>();
            float deg = prism.transform.localEulerAngles.z;
            
            Vector2 normal = new Vector2(Mathf.Sin(deg * Mathf.Deg2Rad), Mathf.Cos(deg * Mathf.Deg2Rad));

            //RaycastHit2D hit = Physics2D.Raycast(transform.position - (Vector3)direction.normalized * cCollirder.radius, direction, 100, raycastLayerMask);
            Vector2 newDir = prism.Refract(direction, normal, false, currentRayColor);
            Debug.DrawRay(transform.position, direction, Color.blue, 2);
            Debug.DrawRay(transform.position, newDir, Color.red, 2);
            SetDirection(newDir);
        }
        else if (other.CompareTag("Filter"))
        {
            //Filter unrelated color
            LevelElement filter = other.gameObject.GetComponent<LevelElement>() ?? other.gameObject.GetComponentInParent<LevelElement>();
            if (currentRayColor != filter.filterColor)
            {
                DestroyRay();
            }
        }
    }

    void OnTriggerExit2D(Collider2D other)
    {
        if (currentColliders.Contains(other))
            currentColliders.Remove(other);
        for (int i = 0; i < currentColliders.Count; i++)
        {
            if (currentColliders[i] == null)
            {
                currentColliders.RemoveAt(i);
                i--;
            }
        }
        
        if (other.CompareTag("Boundary"))
        {
            DestroyRay();
        }
        else if (other.CompareTag("Prism"))
        {
            //Refract
            LevelElement prism = other.gameObject.GetComponent<LevelElement>() ?? other.gameObject.GetComponentInParent<LevelElement>();

            float deg = prism.transform.localEulerAngles.z;
            Vector2 normal = new Vector2(Mathf.Sin((deg + 30) * Mathf.Deg2Rad), Mathf.Cos((deg + 30) * Mathf.Deg2Rad));
            Vector2 newDir = prism.Refract(direction, normal, true, currentRayColor);
            SetDirection(newDir);
        }
    }

    public void DestroyRay()
    {
        //Destroy ray after some effects
        speed = 0;
        GetComponentInChildren<SineMotion>().enabled = false;
        float t0 = trail.time;
        StartCoroutine(Utils.DoOverTime(1f, (dt) =>
        {
            trail.time = Mathf.Lerp(t0, 1f, dt);
        }));
        trail.time = 1;
        Destroy(this.gameObject, 3);
    }

    public void SetDirection(Vector2 dir)
    {
        direction = dir;
        Vector3 ang = transform.localEulerAngles;
        ang.z = -Mathf.Atan2(direction.x, direction.y) * Mathf.Rad2Deg;
        transform.localEulerAngles = ang;
    }

    public void SetColor(Config.RayColor rayColor)
    {
        Color color = Config.RayColors[(int)rayColor];
        trail.startColor = color;
        Color color2 = color;
        color2.a *= 0.5f;
        glowTrail.startColor = color2;
        color.a = 0;
        color2.a = 0;
        trail.endColor = color2;
        glowTrail.endColor = color;
        currentRayColor = rayColor;
    }

    
}
