package com.pesets.game.items;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Random;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.MathUtils;

public class EquipItem implements Item{
	public static final int SlotHelm = 0;
	public static final int SlotChest = 1;
	public static final int SlotLeftHand = 2;
	public static final int SlotRightHand = 3;
	public static final int SlotBoots = 4;
	
	public static final int GradeOrdinary = 0;
	public static final int GradeMagic = 1;
	public static final int GradeRare = 2;
	public static final int GradeEpic = 3;
	
	public static final int StateStr = 1;
	public static final int StateSta = 0;
	public static final int StateAgi = 2;
	public static final int StateInt = 3;
	
	private static float[] stateWeight = { 1.4f, 1f, 0.7f };
	private static int[] slotWeight = { 10, 20, 7, 15, 5}; 
	private static float[] gradeDropChance = { 0.2f, 0.1f, 0.02f, 0.005f};
	private static float[] slotStateCoefficient = { 0.75f, 1.25f, 0.5f, 1f, 0.5f};
	private static float[] gradeStateCoefficient = { 1f, 1.5f, 2f, 2.5f};
	private static float[] slotTripleStatChance = { 0.05f, 0.25f, 0.05f, 0.25f, 0.15f};
	private static float[] slotDoubleStatChance = { 0.2f, 0.8f, 0.5f, 0.9f, 0.7f};
	private static float[] gradeDoubleStatChance = { -0.1f, 0f, 0.2f, 0.8f};
	
	private static String[][] slotNames = { {"Helmet", "Hat", "Hood"},
											{"Armor","Jacket" ,"Robe"},
											{"Shield", "Gloves", "Book"},
											{"Sword", "Dagger", "Staff"},
											{"Boots", "Boots", "Shoes"}  };
	private static String[] gradeNames = { "Magic", "Superior", "Epic" };
	public static String[] stateNames = { "Stamina", "Strength", "Agility", "Intelligence" };
	private static Color[] gradeColor = { new Color(1, 1, 1, 1), new Color(0, 1, 0, 1), new Color(1, 1, 0, 1), new Color(1, 0, 1, 1)};
	
	private static Random randomSlot = new Random();
	private static Random randomGrade = new Random();
	
	private int slot;
	private int states[] = new int[4];
	private int grade;
	private int level;
	private int itemIcon;
	private String name;
	private int weight;
	
	public static EquipItem drop(int level)
	{
		int itemLevel = Math.max(1, MathUtils.random(level - 2, level + 2));
		float chance = randomGrade.nextFloat();
		int grade = -1;
		for (int i = 0; i < 4; i++)
		{
			if (chance < gradeDropChance[i])
			{
				grade = i;
			}
		}
		if (grade == -1) return null;
		
		int slot = randomSlot.nextInt(5);
		
		return new EquipItem(itemLevel, grade, slot);
	}
	
	private void genName()
	{
		int primaryState = 0;
		for (int i = 1; i < states.length; i++)
		{
			if (states[i] > states[primaryState])
				primaryState = i;
		}
		int secondaryState = primaryState == 0 ? 1 : 0;
		for (int i = 0; i < states.length; i++)
		{
			if (states[i] > states[secondaryState] && i != primaryState)
				secondaryState = i;
		}
		
		name = getItemPartName(slot, primaryState == StateSta ? secondaryState : primaryState);
		itemIcon = slot * 3 + (primaryState == StateSta ? secondaryState : primaryState) - 1;
		if (grade > 0)
		{
			name = gradeNames[grade - 1] + " " + name;
		}
		
		if (primaryState != StateSta && states[secondaryState] > 0)
		{
			name = name + " of " + stateNames[secondaryState];
		}
		else if (primaryState == StateSta)
		{
			name = name + " of " + stateNames[primaryState];
		}
		
		weight = (int) (slotWeight[slot] * stateWeight[(primaryState == StateSta ? secondaryState : primaryState) - 1]);
	}
	
	private static String getItemPartName(int slot, int primaryState)
	{
		return slotNames[slot][primaryState - 1];
	}
	
	public EquipItem(int level, int grade, int slot)
	{
		this.level = level;
		this.slot = slot;
		this.grade = grade;
		
		float statSum = level * slotStateCoefficient[slot] * gradeStateCoefficient[grade];
		int state1 = MathUtils.random(0, 3);
		
		if (MathUtils.random() < slotTripleStatChance[slot])
		{
			int state2 = 0;
			int state3 = 0;
			do
				state2 = MathUtils.random(0, 3);
			while (state2 == state1);

			do
				state3 = MathUtils.random(0, 3);
			while (state3 == state1 || state3 == state2);
			
			states[state1] = (int) (Math.max(1, (statSum * 4) / 9));
			states[state2] = (int) (Math.max(1, (statSum * 3) / 9));
			states[state3] = (int) (Math.max(1, (statSum * 2) / 9));
		}
		else if (MathUtils.random() < slotDoubleStatChance[slot] + gradeDoubleStatChance[grade])
		{
			int state2 = 0;
			do
				state2 = MathUtils.random(0, 3);
			while (state2 == state1);
			
			states[state1] = (int) (Math.max(1, (statSum * 3) / 5));
			states[state2] = (int) (Math.max(1, (statSum * 2) / 5));
		}
		else
		{
			states[state1] = (int) Math.max(1, statSum);
		}
		
		genName();
	}
	
	public EquipItem(int level,int strCount, int agiCount, int staCount, int intCount, int slot, int grade)
	{
		this.level = level;
		this.slot = slot;
		this.grade = grade;
		states[StateStr] = strCount;
		states[StateAgi] = agiCount;
		states[StateSta] = staCount;
		states[StateInt] = intCount;
		genName();
	}

	public int getSlot() {
		return slot;
	}

	public int getLevel() {
		return level;
	}
	
	public int getStamina() {
		return states[StateSta];
	}
	
	public int getStrength() {
		return states[StateStr];
	}
	
	public int getAgility() {
		return states[StateAgi];
	}
	
	public int getIntelligence() {
		return states[StateInt];
	}

	@Override
	public int getWeight() {
		return weight;
	}

	@Override
	public int getCost() {
		int sum = 0;
		for (int i = 0; i < states.length; i++)
		{
			sum += states[i];
		}
		return sum * sum * 10;
	}

	@Override
	public int getStackCount() {
		return 1;
	}

	@Override
	public int getCount() {
		return 1;
	}

	@Override
	public void setCount(int newCount) {
		//nothing to do here
	}

	@Override
	public int getId() {
		return -1;
	}

	@Override
	public String getItemName() {
		return name;
	}

	@Override
	public String getItemDesc() {
		String desc = "Requires level " + level;
		for (int i = 0; i < states.length; i++)
		{
			if (states[i] > 0)
				desc = desc + "\n" + stateNames[i] + ": " + states[i];
		}
		desc = desc + String.format("\n\nWeight: %d", weight);
		return desc;
	}

	@Override
	public int getItemIcon() {
		return itemIcon;
	}
	
	public int getStateById(int id)
	{
		return states[id];
	}

	@Override
	public Color getNameColor() {
		return gradeColor[grade];
	}
	
	public int getGrade() {
		return grade;
	}

	@Override
	public void toStream(DataOutputStream out) throws IOException {
		for (int i = 0; i < states.length; i++)
			out.writeInt(states[i]);
		out.writeInt(grade);
		out.writeInt(level);
		out.writeInt(slot);
	}
	
	public EquipItem(DataInputStream in) throws IOException
	{
		for (int i = 0; i < states.length; i++)
			states[i] = in.readInt();
		grade = in.readInt();
		level = in.readInt();
		slot = in.readInt();
		genName();
	}
}
