package com.pesets.game;

import java.util.LinkedList;

import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.pesets.game.skills.Skill;
import com.pesets.resources.ResourceManager;

public class GameObject {
	public static enum ObjectState {
		Idle, 
		Moving, 
		Attack,
		Death
	}
	
	protected float x, y;
	protected float width, height;
	protected float speed = 150;
	protected LinkedList<Vector2> path = new LinkedList<Vector2>();
	protected IGameObjectCallback callback;
	protected ObjectState state = ObjectState.Idle;
	protected Vector2 dir = new Vector2();
	
	protected int strength = 5;
	protected int agility = 5;
	protected int stamina = 5;
	protected int intelligence = 5;
	
	protected int level;
	protected float hp;
	protected float attackCD = 0;
	protected float effects[] = new float[3];
	
	public GameObject(IGameObjectCallback callback)
	{
		this.callback = callback;
	}

	public float getX() {
		return x;
	}

	public void setX(float x) {
		this.x = x;
	}

	public float getY() {
		return y;
	}

	public void setY(float y) {
		this.y = y;
	}
	
	public void setPos(float x, float y)
	{
		setX(x);
		setY(y);
	}
	
	public void render(SpriteBatch batch)
	{
		
	}
	
	public void update(float dt)
	{
		if (state.equals(ObjectState.Moving) && path.isEmpty() == false)
		{
			Vector2 v = path.peek();
			if (v.dst(x, y) <= speed * dt)
			{
				x = v.x;
				y = v.y;
				path.poll();
			}
			else
			{
				dir.set(v);
				dir.sub(x, y).nor().mul(speed).mul(dt);
				x += dir.x;
				y += dir.y;
			}
		}
	}

	public void setCallback(IGameObjectCallback callback) {
		this.callback = callback;
	}

	public ObjectState getState() {
		return state;
	}

	public void setState(ObjectState state) {
		this.state = state;
	}
	
	public float dist2(GameObject o)
	{
		return (o.x - x) * (o.x - x) + (o.y - y) * (o.y - y);
	}
	
	public float getMaxHP()
	{
		return getStamina() * 10;
	}
	
	public float getDamageReduction()
	{
		float reduction = getAgility() / 500f;
		if (effects[Skill.EffectArmorReduction] > 0)
			reduction *= 0.75f;
		return Math.max(0.25f, 1 - reduction);
	}
	
	public float getAttackColdown()
	{
		return (float) (4 / (1 + Math.log(getAgility())));
	}
	
	public int getMaxWeight()
	{
		return getStrength() * 2 + 100;
	}
	
	public void hit(GameObject obj)
	{
		hp -= getRawDamage(obj);
		if (hp < 0)
			 hp = 0;
		int i = MathUtils.random(3);
		ResourceManager.getInstance().playSound("hit_0" + i + ".ogg");
	}
	
	public boolean isDead()
	{
		return (hp <= 0);
	}
	
	public float getHP()
	{
		return hp;
	}
	
	public void setHP(float hp) {
		this.hp = hp;
	}
	
	public int getStrength()
	{
		return strength;
	}

	public int getAgility() {
		return agility;
	}

	public int getStamina() {
		return stamina;
	}

	public int getIntelligence() {
		return intelligence;
	}

	public float getAttackCD() {
		return attackCD;
	}
	
	public int getLevel() {
		return level;
	}
	
	public float getAttackPower() {
		return getStrength();
	}
	
	public float getRawDamage(GameObject obj) {
		return obj.getAttackPower() * getDamageReduction();
	}
	
	public float getEffectDuration(int index) {
		return effects[index];
	}
	
	public float getColdownReduction() {
		return Math.max(0, getIntelligence() / 400f - 0.05f);
	}

	public float getWidth() {
		return width;
	}

	public float getHeight() {
		return height;
	}
	
	
}
