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

namespace BigSock {
	// Common class for all characters.
	public class Character : Entity {

		/*
			Attack speed of the character.
		*/
		public float AttackSpeed => baseAttackSpeed;
		public float baseAttackSpeed = 1;

		/*
			Cooldown between attacks.
		*/
		public float AttackCooldown => 1.0f / AttackSpeed;
		
		/*
			Movement speed of the character.
		*/
		public float MovementSpeed => baseMovementSpeed;
		public float baseMovementSpeed = 1;

		
		/*
			Damage of the character.
		*/
		public float Damage => baseDamage;
		public float baseDamage = 1;

		/*
			Knockback force
		*/
		public float KnockbackForce => knockbackForce;
		public float knockbackForce = 150;

		
		/*
			Hit points of the character.
		*/
		public float HP { 
			get => baseHP; 
			set => baseHP = value; 
		}
		public float baseHP = 10;

		
		/*
			Maximum hit points of the character.
		*/
		public float MaxHP => baseMaxHP;
		public float baseMaxHP = 10;



		/*
			Indicates whether or not the characer is a live.
		*/
		public bool Alive { get; private set; } = true;
		
		/*
			Stores the next time the character can recieve damage.
		*/
		public DateTime NextTimeCanTakeDamage { get; private set; } = DateTime.Now;
		
		/*
			How long between each time the character can take damage.
		*/
		public TimeSpan IFrameDuration { 
			get => _iFrameDuration; 
			private set => _iFrameDuration = value; 
		}
		public TimeSpan _iFrameDuration = new TimeSpan(0, 0, 0, 0, 333);



		protected Rigidbody2D rb;


		void Start() {
				rb = GetComponent<Rigidbody2D>();
		}

		/*
			Add Kcockback. 
		*/
		//public void KnockBack(float force, Vector2 difference) {
		//	rb.AddForce(difference * force, ForceMode2D.Impulse);
		//}
		public void KnockBack(IAttackStats attack) {
			Vector2 difference = ((Vector2) transform.position - attack.Source).normalized;
			//KnockBack(attack.Knockback, difference);
			rb.AddForce(difference * attack.Knockback, ForceMode2D.Impulse);

		}

		/*
			Adds damage to the player if they don't have IFrames.
		*/
		public bool TakeDamage(float amount) {
			return TakeDamage(new AttackStats{
				Damage = amount,
			});
		}

		/*
			Adds damage to the player if they don't have IFrames.
		*/
		public bool TakeDamage(IAttackStats attack) {
			// Check if player has IFrames
			if(NextTimeCanTakeDamage > DateTime.Now)
				return false;

			// Start new IFrames
			NextTimeCanTakeDamage = DateTime.Now + IFrameDuration;


			// Add damage
			HP -= attack.Damage;
			OnDamage(attack);

			TryKill();

			return true;
		}


		/*
			Try to kill the player.
		*/
		public bool TryKill() {
			if(Alive && HP <= 0) {
				Alive = false;

				OnDeath();

				return true;
			}
			return false;
		}


		/*
			Method for what to do when the character takes damage.
		*/
		protected virtual void OnDamage(IAttackStats attack) {
			print($"[Character.TakeDamage()] {HP} - {attack.Damage}");
			KnockBack(attack);
		}

		/*
			Method for what to do when the character dies.
		*/
		protected void OnDeath() {
			print($"[Character.TryKill()] start. | {HP}, {Alive}");
			Destroy(gameObject);
		}

	}
}