using UnityEngine;
using System.Collections;
using Framework.Entities;
using Framework.Extensions;
using System.Linq;
using System.Collections.Generic;
using Framework.InteractionSystem;
using Framework.Utility;
using Framework.Debugging;
using Project.Player;

namespace Project.Actors
{
    public class Woundable : CoreBehaviour
    {
        public class HurtAction : CoreAction 
        {
            public float attackForce;
            public Vector3 sourcePosition;

            public HurtAction(CoreBehaviour sender, float attackForce, Vector3 sourcePosition) : base(sender)
            {
                this.attackForce = attackForce;
                this.sourcePosition = sourcePosition;
            }
        }
        public class HealAction : CoreAction { }
        public class DeadAction : CoreAction { }

        public int maxWounds = 1;
        public int wounds = 0;
        public float hurtGraceTime = 1f;
        private UnityTimer hurtTimer;
        private ActorClassifier classifier;

        // Use this for initialization
        protected override void InnerAwake()
        {
            AddGlobalActionHandler<PlayerDeathHandler.ResetLevelAction>(this, Reset);
            AddActionHandler<HurtAction>(Hurt);
            AddActionHandler<HealAction>(Heal);
            this.hurtTimer = new UnityTimer(hurtGraceTime, true);
            this.classifier = GetComponent<ActorClassifier>();
        }

        // Update is called once per frame
        protected override void InnerUpdate()
        {
            if (!this.hurtTimer.IsComplete())
            {
                this.hurtTimer.Advance();
            }
        }

        protected virtual void Hurt(HurtAction action)
        {
            Debug.Log("Hurt");
            int otherTeamNumber = -1;
            ActorClassifier classifier = action.GetSender().GetGameObject().GetComponent<ActorClassifier>();
            if (classifier != null)
            {
                otherTeamNumber = classifier.teamNumber;
            }
            if (this.hurtTimer.IsComplete() && otherTeamNumber != this.classifier.teamNumber)
            {
                this.hurtTimer.Reset();
                Rigidbody rigidbody = GetComponent<Rigidbody>();
                if (rigidbody != null)
                {
                    rigidbody.AddForce((this.transform.position - action.sourcePosition) * action.attackForce);
                    this.wounds += 1;
                    if(GetComponent<PlayerInput>() != null)
                    {
                        Announce(new PlayerInput.PlayerHurtAction());
                    }
                    Debug.Log(this.name + " hurt by: " + action.GetSender().GetGameObject().name);

                    // Die?
                    if (this.wounds >= this.maxWounds)
                    {
                        Interact(new DeadAction());
                    }
                }
            }
        }

        private void Heal(HealAction action)
        {
            if (this.wounds > 0)
            {
                this.wounds -= 1;
            }
        }

        private void Reset(PlayerDeathHandler.ResetLevelAction action)
        {
            this.wounds = 0;
        }
    }
}