﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
using Arugula.Math;

namespace Arugula.Games
{
    public class RaycastProjectile : Projectile
    {
        [Header("Raycast")]
        public Vector3 initialVelocity;
        public Vector3 gravity;
        [Min(0)]
        public float radius = 0;
        public QueryTriggerInteraction triggerInteraction;
        public bool alignToVelocity = true;
        public float alignRoll = 0;

        Vector3 velocity;
        float startTime = 0;

        public override void Start()
        {
            base.Start();
            startTime = Time.time;
            velocity = transform.rotation * initialVelocity;
        }

        private void FixedUpdate()
        {
            Vector3 nextPoint = GetNextPoint(transform.position, velocity, Time.deltaTime);
            RaycastHit hit = new RaycastHit();
            Ray ray = new Ray(transform.position, nextPoint - transform.position);
            float dist = Vector3.Distance(transform.position, nextPoint);
            if (radius == 0)
            {
                //raycast
                Physics.Raycast(ray, out hit, dist, damageMask | impactMask, triggerInteraction);
            }
            else
            {
                //spherecast
                Physics.SphereCast(ray, radius, out hit, dist, damageMask | impactMask, triggerInteraction);
            }

            if (hit.collider != null)
            {
                bool impact = false;
                if (IsImpactable(hit.collider))
                {
                    transform.position = hit.point;
                    _OnImpact();
                    impact = true;
                }

                if (IsDamageable(hit.collider))
                {
                    var d = DestructibleObject.Get(hit.collider);
                    if (d)
                    {
                        transform.position = hit.point;
                        Use();
                        damageInfo.meta = hit;
                        d.Damage(damageInfo);
                        _OnDamage();
                    }
                }

                if (useOnImpact && impact && !used)
                {
                    Use();
                }
            }
            else
            {
                transform.position = nextPoint;
            }

            if (alignToVelocity)
            {
                transform.rotation = Quaternion.LookRotation(ray.direction);
                transform.Rotate(0, 0, alignRoll);
            }

            velocity += gravity * Time.deltaTime;
        }

        Vector3 GetNextPoint(Vector3 position, Vector3 velocity, float deltaTime)
        {
            return position + (velocity * deltaTime);
        }


#if UNITY_EDITOR
        private void OnDrawGizmosSelected()
        {
            Vector3 velocity = (Application.isPlaying ? this.velocity : (transform.rotation * initialVelocity));
            //Vector3[] points = new Vector3[100];
            List<Vector3> list = new List<Vector3>();
            list.Add(transform.position);
            //points[0] = transform.position;
            float t = LifespanRemaining;
            if (radius > 0)
                Handles.DrawWireDisc(list[0], velocity, radius);
            for (int i = 1; i < 100; i++)
            {
                t -= Time.fixedDeltaTime;

                if (t <= 0)
                    break;

                velocity += gravity * Time.fixedDeltaTime;
                list.Add(GetNextPoint(list[i - 1], velocity, Time.fixedDeltaTime));
                if (radius > 0 && (i + 1) % 5 == 0)
                    Handles.DrawWireDisc(list[i], velocity, radius);
            }

            Handles.DrawPolyLine(list.ToArray());
        }
#endif
    }
}

