using Godot;
using System;

public partial class IQEnemy : CharacterBody2D
{	
	// Misc
	float GlobalTimer;
	Node2D VAH; // Shorthand refrence
	
	// Enemy Stats
	public int IQ;
	public float HP;
	public float MaxHP;
	float RegenerationAmmount;
	float RegenerationInterval;
	float WalkSpeed;
	float JumpHeight;
	
	// Enemy Conditions
	float CurrentYVelocity;
	float PreviousYVelocity;
	bool GroundDetected;
	bool LedgeDetected;
	bool WallDetected;
	String FacingDirection;
	
	// Enemy Abilities
	bool AbilityJump = false;
	bool AbilityMove = false;
	bool AbilityAttack = false;
	bool AbilityDash = false;
	bool AbilityCloak = false;
	bool AbilityTeleport = false;
	bool AbilityRegenerate = false;
	
	public override void _Ready()
	{	
		// Read & Set Abilities
		if (HasMeta("AbilityJump")) AbilityJump = (bool)GetMeta("AbilityJump");
		if (HasMeta("AbilityMove")) AbilityMove = (bool)GetMeta("AbilityMove");
		if (HasMeta("AbilityAttack")) AbilityAttack = (bool)GetMeta("AbilityAttack");
		if (HasMeta("AbilityDash")) AbilityDash = (bool)GetMeta("AbilityDash");
		if (HasMeta("AbilityCloak")) AbilityCloak = (bool)GetMeta("AbilityCloak");
		if (HasMeta("AbilityTeleport")) AbilityTeleport = (bool)GetMeta("AbilityTeleport");
		if (HasMeta("AbilityRegenerate")) AbilityRegenerate = (bool)GetMeta("AbilityRegenerate");
		if (HasMeta("RegenerationAmmount")) RegenerationAmmount = (float)GetMeta("RegenerationAmmount");
			else RegenerationAmmount = 1.0f;
		if (HasMeta("RegenerationInterval")) RegenerationInterval = (float)GetMeta("RegenerationInterval");
			else RegenerationInterval = 1.0f;
		if (HasMeta("WalkSpeed")) WalkSpeed = (float)GetMeta("WalkSpeed");
			else WalkSpeed = 20.0f;
		if (HasMeta("JumpHeight")) JumpHeight = (float)GetMeta("JumpHeight");
			else JumpHeight = 250.0f;
		JumpHeight *= -1;
			
		// Read and set stats
		if (HasMeta("MaxHP")) MaxHP = (float)GetMeta("MaxHP");
		
		FacingDirection = "RIGHT";
		VAH = GetNode<Node2D>("VisualsAndHitboxes");
		
		// Set up collision detection
		VAH.GetNode<Area2D>("GroundDetector").BodyEntered += OnGroundEntered; // Ground
		VAH.GetNode<Area2D>("GroundDetector").BodyExited += OnGroundExited;
		VAH.GetNode<Area2D>("LedgeDetector").BodyEntered += OnLedgeEntered; // Ledge
		VAH.GetNode<Area2D>("LedgeDetector").BodyExited += OnLedgeExited;
		VAH.GetNode<Area2D>("WallDetector").BodyEntered += OnWallEntered; // Wall
		VAH.GetNode<Area2D>("WallDetector").BodyExited += OnWallExited;
		
		GroundDetected = false;
		LedgeDetected = false;
		WallDetected = false;
		
		// Apply IQ based permenant modifiers
		IQ = (int)GetMeta("IQ"); // Read IQ
		
		if (IQ >= 100) MaxHP += 20;
		HP = MaxHP;
		if (IQ >= 100 && HasMeta("RegenerationInterval")) RegenerationInterval *= 0.9f;
		if (IQ >= 100 && HasMeta("RegenerationAmmount")) RegenerationAmmount *= 1.05f; // 5% increase
		
		WalkSpeed += IQ / 10;
		JumpHeight += IQ / 15;
	}
	
	public override void _PhysicsProcess(double delta)
	{
		// Update Timer
		GlobalTimer = GetTree().Root.GetNode<CommonData>("CommonData").GlobalTimer;
		
		// Show current hp for testing purposes
		if (HasMeta("CurrentHP")) SetMeta("CurrentHP", HP);
		
		// Regenerate Health
		if (AbilityRegenerate){
			if (GlobalTimer % RegenerationInterval == 0){Regenerate(RegenerationAmmount);}
		}
		
		// Movement
		// Add gravity.
		if (GroundDetected == false){Velocity = new Vector2(Velocity[0],Velocity[1] + 10);}
		
		#region 20IQ
		if (IQ >= 0 && IQ <= 20){ // Goomba ahh diddy blud
			if (GroundDetected && LedgeDetected == false){Flip();} // Flip when presented with a ledge
			if (WallDetected){Flip();} // Flip when comeing in contact with a wall
			if (GroundDetected){Velocity = new Vector2(WalkSpeed * VAH.Scale[0], Velocity[1]);} // Walk
		}
		#endregion
		#region 30IQ
		if (IQ > 20 && IQ <= 30){ // Goomba w/ hopps (no judy)
			Velocity = new Vector2(WalkSpeed * VAH.Scale[0], Velocity[1]); // Walk
			if (WallDetected && GroundDetected && Velocity[1] == 0){Velocity = new Vector2(Velocity[0], JumpHeight);} // Jump
			if (WallDetected && GroundDetected && Velocity[1] > 0){Flip();} // Wall too high
		}
		#endregion
		#region 40IQ
		if (IQ > 30 && IQ <= 40){ // Adds jumping when reaching edge as feature (also adding directional x force)
			if (GroundDetected){Velocity = new Vector2(WalkSpeed * VAH.Scale[0], Velocity[1]);} // Walk on ground
				else{Velocity = new Vector2(WalkSpeed * VAH.Scale[0] * 2, Velocity[1]);} // Walk on air
			if (WallDetected && GroundDetected && Velocity[1] == 0){Velocity = new Vector2(Velocity[0], JumpHeight);} // Jump
			//if (GroundDetected && LedgeDetected == false && Velocity[1] == 0){Velocity = new Vector2(Velocity[0] * 50, JumpHeight);} // Jump at ledge
			if (GroundDetected && LedgeDetected == false && Velocity[1] == 0){Velocity = new Vector2(Velocity[0], JumpHeight);} // Jump at ledge
			if (WallDetected && GroundDetected && Velocity[1] > 0){Flip();} // Wall too high
		}
		#endregion
		#region 60IQ
		if (IQ > 40 && IQ <= 60){ // Concious of what side of the enemy the player is on
		}
		#endregion
		#region 80IQ
		if (IQ > 60 && IQ <= 80){ // Maintan distance to avoid melee attacks and optimise ranged attacks 
		}
		#endregion
		#region 1000IQ
		if (IQ > 80 && IQ <= 100){ // Basic Pathfinding
		}
		#endregion
		#region 120IQ
		if (IQ > 100 && IQ <= 120){ // Advanced Pathfindinhg
		}
		#endregion
		#region 140IQ
		if (IQ > 120 && IQ <= 140){ // Advanced movement options
		}
		#endregion
		MoveAndSlide(); // Updates physics applied this frame
	}
	
	void Flip(){
		VAH.Scale = new Vector2(-1 * VAH.Scale[0],1);
		WallDetected = false;
		LedgeDetected = true;
		if (FacingDirection == "RIGHT"){FacingDirection = "LEFT";}
		else if (FacingDirection == "LEFT"){FacingDirection = "RIGHT";}
	}
	
	public void Regenerate(float ammount){
		if (HP < MaxHP) HP += ammount;
		if (HP > MaxHP) HP = MaxHP; // Catch errors
	}
	
	public void Damage(float ammount){
		HP -= ammount;
		if (HP <= 0) Kill();
	}
	
	public void Kill(){
		QueueFree(); // Change to proper death w/ corpse
	}
	
	// Ground Detection
	public void OnGroundEntered(Node2D body){if (body is TileMapLayer tileLayer) GroundDetected = true;}
	public void OnGroundExited(Node2D body){if (body is TileMapLayer tileLayer) GroundDetected = false;}
	// Ledge Detection
	public void OnLedgeEntered(Node2D body){if (body is TileMapLayer tileLayer) LedgeDetected = true;}
	public void OnLedgeExited(Node2D body){if (body is TileMapLayer tileLayer) LedgeDetected = false;}
	// Wall Detection
	public void OnWallEntered(Node2D body){if (body is TileMapLayer tileLayer) WallDetected = true;}
	public void OnWallExited(Node2D body){if (body is TileMapLayer tileLayer) WallDetected = false;}
}
