package handlers.admincommandhandlers;

import gnu.trove.TIntObjectHashMap;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;

import javolution.io.UTF8StreamWriter;

import com.l2jserver.Config;
import com.l2jserver.gameserver.datatables.ItemTable;
import com.l2jserver.gameserver.handler.IAdminCommandHandler;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.skills.SkillHolder;
import com.l2jserver.gameserver.templates.item.L2Armor;
import com.l2jserver.gameserver.templates.item.L2EtcItem;
import com.l2jserver.gameserver.templates.item.L2Item;
import com.l2jserver.gameserver.templates.item.L2Weapon;

public class AdminItemsToSQL implements IAdminCommandHandler
{
	private static final String TABLE_ARMOR = "armor";
	private static final String TABLE_ETCITEM = "etcitem";
	private static final String TABLE_WEAPON = "weapon";
	
	private static final String FILE_ARMOR = "log/armor.sql";
	private static final String FILE_ETCITEM = "log/etcitem.sql";
	private static final String FILE_WEAPON = "log/weapon.sql";
	private static final int SPLIT = 500;
	
	private static final String[] ADMIN_COMMANDS =
	{
		"admin_items_to_sql"
	};
	
	public boolean useAdminCommand(String command, L2PcInstance activeChar)
	{
		if (command.equals("admin_items_to_sql"))
		{
			TIntObjectHashMap<String> materials = new TIntObjectHashMap<String>();
			TIntObjectHashMap<String> crystalTypes = new TIntObjectHashMap<String>();
			TIntObjectHashMap<String> slots = new TIntObjectHashMap<String>();
			
			for (Map.Entry<String, Integer> e : ItemTable._materials.entrySet())
				materials.put(e.getValue(), e.getKey());
			for (Map.Entry<String, Integer> e : ItemTable._crystalTypes.entrySet())
				crystalTypes.put(e.getValue(), e.getKey());
			for (Map.Entry<String, Integer> e : ItemTable._slots.entrySet())
				slots.put(e.getValue(), e.getKey());
			
			try
			{
				UTF8StreamWriter out;
				int count;
				////////////////////////////////////////////////////
				// armor
				////////////////////////////////////////////////////
				activeChar.sendMessage(FILE_ARMOR);
				out = new UTF8StreamWriter().setOutput(new FileOutputStream(FILE_ARMOR));
				count = 0;
				for (int id : ItemTable.getInstance().getAllArmorsId())
				{
					if (count == 0)
						out.write("DROP TABLE IF EXISTS `" + TABLE_ARMOR + "`;\n"
								+ "CREATE TABLE IF NOT EXISTS `" + TABLE_ARMOR + "` (\n"
								+ "  `item_id` smallint(5) unsigned NOT NULL DEFAULT '0',\n"
								+ "  `name` varchar(120) NOT NULL DEFAULT '',\n"
								+ "  `additionalname` varchar(120) NOT NULL DEFAULT '',\n"
								+ "  `bodypart` varchar(15) NOT NULL DEFAULT 'none',\n"
								+ "  `crystallizable` enum('true','false') NOT NULL DEFAULT 'false',\n"
								+ "  `armor_type` enum('none','light','heavy','magic','sigil','pet') NOT NULL DEFAULT 'none',\n"
								+ "  `weight` smallint(4) NOT NULL DEFAULT '0',\n"
								+ "  `material` varchar(15) NOT NULL DEFAULT 'wood',\n"
								+ "  `crystal_type` enum('none','d','c','b','a','s','s80','s84') NOT NULL DEFAULT 'none',\n"
								+ "  `avoid_modify` tinyint(2) NOT NULL DEFAULT '0',\n"
								+ "  `duration` mediumint(5) NOT NULL DEFAULT '-1', -- duration in minutes for shadow items\n"
								+ "  `time` mediumint(5) NOT NULL DEFAULT '-1',     -- duration in minutes for time limited items\n"
								+ "  `p_def` smallint(3) NOT NULL DEFAULT '0',\n"
								+ "  `m_def` smallint(3) NOT NULL DEFAULT '0',\n"
								+ "  `mp_bonus` smallint(3) NOT NULL DEFAULT '0',\n"
								+ "  `price` int(10) unsigned NOT NULL DEFAULT '0',\n"
								+ "  `crystal_count` smallint(4) unsigned NOT NULL DEFAULT '0',\n"
								+ "  `sellable` enum('true','false') NOT NULL DEFAULT 'false',\n"
								+ "  `dropable` enum('true','false') NOT NULL DEFAULT 'false',\n"
								+ "  `destroyable` enum('true','false') NOT NULL DEFAULT 'false',\n"
								+ "  `tradeable` enum('true','false') NOT NULL DEFAULT 'false',\n"
								+ "  `depositable` enum('true','false') NOT NULL DEFAULT 'false',\n"
								+ "  `enchant4_skill` varchar(8) NOT NULL DEFAULT '0-0',\n"
								+ "  `skill` varchar(70) DEFAULT '0-0;',\n"
								+ "  PRIMARY KEY (`item_id`)\n"
								+ ") DEFAULT CHARSET=utf8;\n"
								+ "\n"
								+ "INSERT INTO `" + TABLE_ARMOR + "` VALUES\n");
					else if (count % SPLIT == 0)
						out.write(";\nINSERT INTO `" + TABLE_ARMOR + "` VALUES\n");
					else
						out.write(",\n");
					
					L2Armor armor = (L2Armor)ItemTable.getInstance().getTemplate(id);
					String sql = "(" + armor.getItemId()
						+ ",'" + escape(armor.getName()) + "'"
						+ ",''"				//TODO: `additionalname`
						+ ",'" + slots.get(armor.getBodyPart()) + "'"
						+ ",'" + armor.isCrystallizable() + "'"
						+ ",'" + armor.getItemType().toString() + "'"	//TODO: .toLowerCase() ??
						+ ","  + armor.getWeight()
						+ ",'" + materials.get(armor.getMaterialType()) + "'"
						+ ","  + crystalTypes.get(armor.getCrystalType()) + "'"
						+ ",0"
					//	+ ","  + armor.getAvoidModifier()
						+ ","  + armor.getDuration()
						+ ","  + armor.getTime()
						+ ",0"				//TODO: `p_def`
						+ ",0"				//TODO: `m_def`
						+ ",0"				//TODO: `mp_bonus`
						+ ","  + getPrice(armor)
						+ ","  + armor.getCrystalCount()
						+ ",'" + armor.isSellable() + "'"
						+ ",'" + armor.isDropable() + "'"
						+ ",'" + armor.isDestroyable() + "'"
						+ ",'" + armor.isTradeable() + "'"
						+ ",'" + armor.isDepositable() + "'"
						+ ",'" + armor.getEnchant4Skill().getId() + "-" + armor.getEnchant4Skill().getLevel() + "'"
						+ ",'" + skillsToString(armor.getSkills()) + "'"
						+ ")";
					out.write(sql);
					++count;
				}
				out.write(";\n");
				out.close();
				////////////////////////////////////////////////////
				// etcitem
				////////////////////////////////////////////////////
				activeChar.sendMessage(FILE_ETCITEM);
				out = new UTF8StreamWriter().setOutput(new FileOutputStream(FILE_ETCITEM));
				count = 0;
				for (int id : ItemTable.getInstance().getAllEtcId())
				{
					if (count == 0)
						out.write("DROP TABLE IF EXISTS `" + TABLE_ETCITEM + "`;\n"
								+ "CREATE TABLE IF NOT EXISTS `" + TABLE_ETCITEM + "` (\n"
								+ "  `item_id` smallint(5) unsigned NOT NULL DEFAULT '0',\n"
								+ "  `name` varchar(100) NOT NULL DEFAULT '',\n"
								+ "  `additionalname` varchar(100) NOT NULL DEFAULT '',\n"
								+ "  `crystallizable` enum('true','false') NOT NULL DEFAULT 'false',\n"
								+ "  `item_type` varchar(14) NOT NULL DEFAULT 'none',\n"
								+ "  `weight` smallint(4) NOT NULL DEFAULT '0',\n"
								+ "  `consume_type` enum('normal','stackable','asset') NOT NULL DEFAULT 'normal',\n"
								+ "  `material` varchar(11) NOT NULL DEFAULT 'wood',\n"
								+ "  `crystal_type` enum('none','d','c','b','a','s','s80','s84') NOT NULL DEFAULT 'none',\n"
								+ "  `duration` mediumint(5) NOT NULL DEFAULT '-1', -- duration in minutes for shadow items\n"
								+ "  `time` mediumint(5) NOT NULL DEFAULT '-1',     -- duration in minutes for time limited items\n"
								+ "  `price` int(10) unsigned NOT NULL DEFAULT '0',\n"
								+ "  `crystal_count` smallint(4) unsigned NOT NULL DEFAULT '0',\n"
								+ "  `sellable` enum('true','false') NOT NULL DEFAULT 'false',\n"
								+ "  `dropable` enum('true','false') NOT NULL DEFAULT 'false',\n"
								+ "  `destroyable` enum('true','false') NOT NULL DEFAULT 'false',\n"
								+ "  `tradeable` enum('true','false') NOT NULL DEFAULT 'false',\n"
								+ "  `depositable` enum('true','false') NOT NULL DEFAULT 'false',\n"
								+ "  `handler` varchar(70) NOT NULL DEFAULT 'none',\n"
								+ "  `skill` varchar(70) NOT NULL DEFAULT '0-0;',\n"
								+ "  PRIMARY KEY (`item_id`)\n"
								+ ") DEFAULT CHARSET=utf8;\n"
								+ "\n"
								+ "INSERT INTO `" + TABLE_ETCITEM + "` VALUES\n");
					else if (count % SPLIT == 0)
						out.write(";\nINSERT INTO `" + TABLE_ETCITEM + "` VALUES\n");
					else
						out.write(",\n");
					L2EtcItem etcitem = (L2EtcItem)ItemTable.getInstance().getTemplate(id);
					String sql = "(" + etcitem.getItemId()
						+ ",'" + escape(etcitem.getName()) + "'"
						+ ",''"				//TODO: `additionalname`
						+ ",'" + etcitem.isCrystallizable() + "'"
						+ ",'" + etcitem.getItemType().toString() + "'"	//TODO: .toLowerCase() ??
						+ ","  + etcitem.getWeight()
						+ ",'normal'"		//TODO: `consume_type`
						+ ",'" + materials.get(etcitem.getMaterialType()) + "'"
						+ ","  + crystalTypes.get(etcitem.getCrystalType()) + "'"
						+ ","  + etcitem.getDuration()
						+ ","  + etcitem.getTime()
						+ ","  + getPrice(etcitem)
						+ ","  + etcitem.getCrystalCount()
						+ ",'" + etcitem.isSellable() + "'"
						+ ",'" + etcitem.isDropable() + "'"
						+ ",'" + etcitem.isDestroyable() + "'"
						+ ",'" + etcitem.isTradeable() + "'"
						+ ",'" + etcitem.isDepositable() + "'"
						+ ",'" + etcitem.getHandlerName() + "'"
						+ ",'" + skillsToString(etcitem.getSkills()) + "'"
						+ ")";
					out.write(sql);
					++count;
				}
				out.write(";\n");
				out.close();
				////////////////////////////////////////////////////
				// weapon
				////////////////////////////////////////////////////
				activeChar.sendMessage(FILE_WEAPON);
				out = new UTF8StreamWriter().setOutput(new FileOutputStream(FILE_WEAPON));
				count = 0;
				for (int id : ItemTable.getInstance().getAllWeaponsId())
				{
					if (count == 0)
						out.write("DROP TABLE IF EXISTS `" + TABLE_WEAPON + "`;\n"
								+ "CREATE TABLE IF NOT EXISTS `" + TABLE_WEAPON + "` (\n"
								+ "  `item_id` smallint(5) unsigned NOT NULL DEFAULT '0',\n"
								+ "  `name` varchar(120) NOT NULL DEFAULT '0',\n"
								+ "  `additionalname` varchar(120) NOT NULL DEFAULT '',\n"
								+ "  `bodypart` varchar(15) NOT NULL DEFAULT 'none',\n"
								+ "  `crystallizable` enum('true','false') NOT NULL DEFAULT 'false',\n"
								+ "  `weight` smallint(4) NOT NULL DEFAULT '0',\n"
								+ "  `soulshots` tinyint(1) unsigned NOT NULL DEFAULT '0',\n"
								+ "  `spiritshots` tinyint(1) unsigned NOT NULL DEFAULT '0',\n"
								+ "  `material` varchar(11) NOT NULL DEFAULT 'wood',\n"
								+ "  `crystal_type` varchar(4) NOT NULL DEFAULT 'none',\n"
								+ "  `p_dam` smallint(4) NOT NULL DEFAULT '0',\n"
								+ "  `rnd_dam` smallint(3) NOT NULL DEFAULT '0',\n"
								+ "  `weaponType` varchar(10) NOT NULL DEFAULT 'none',\n"
								+ "  `critical` smallint(3) NOT NULL DEFAULT '0',\n"
								+ "  `hit_modify` tinyint(2) NOT NULL DEFAULT '0',\n"
								+ "  `avoid_modify` tinyint(2) NOT NULL DEFAULT '0',\n"
								+ "  `shield_def` smallint(4) NOT NULL DEFAULT '0',\n"
								+ "  `shield_def_rate` smallint(3) NOT NULL DEFAULT '0',\n"
								+ "  `atk_speed` smallint(4) NOT NULL DEFAULT '0',\n"
								+ "  `mp_consume` tinyint(1) NOT NULL DEFAULT '0',\n"
								+ "  `m_dam` smallint(4) NOT NULL DEFAULT '0',\n"
								+ "  `duration` mediumint(5) NOT NULL DEFAULT '-1', -- duration in minutes for shadow items\n"
								+ "  `time` mediumint(5) NOT NULL DEFAULT '-1',     -- duration in minutes for time limited items\n"
								+ "  `price` int(10) unsigned NOT NULL DEFAULT '0',\n"
								+ "  `crystal_count` smallint(4) unsigned NOT NULL DEFAULT '0',\n"
								+ "  `sellable` enum('true','false') NOT NULL DEFAULT 'false',\n"
								+ "  `dropable` enum('true','false') NOT NULL DEFAULT 'false',\n"
								+ "  `destroyable` enum('true','false') NOT NULL DEFAULT 'false',\n"
								+ "  `tradeable` enum('true','false') NOT NULL DEFAULT 'false',\n"
								+ "  `depositable` enum('true','false') NOT NULL DEFAULT 'false',\n"
								+ "  `enchant4_skill_id` smallint(5) unsigned NOT NULL DEFAULT '0',\n"
								+ "  `enchant4_skill_lvl` tinyint(2) unsigned NOT NULL DEFAULT '0',\n"
								+ "  `onCast_skill_id` smallint(5) unsigned NOT NULL DEFAULT '0',\n"
								+ "  `onCast_skill_lvl` tinyint(2) unsigned NOT NULL DEFAULT '0',\n"
								+ "  `onCast_skill_chance` smallint(3) NOT NULL DEFAULT '0',\n"
								+ "  `onCrit_skill_id` smallint(5) unsigned NOT NULL DEFAULT '0',\n"
								+ "  `onCrit_skill_lvl` tinyint(2) unsigned NOT NULL DEFAULT '0',\n"
								+ "  `onCrit_skill_chance` smallint(3) NOT NULL DEFAULT '0',\n"
								+ "  `change_weaponId` smallint(5) unsigned NOT NULL DEFAULT '0',\n"
								+ "  `skill` varchar(70) NOT NULL DEFAULT '0-0;',\n"
								+ "  PRIMARY KEY (`item_id`)\n"
								+ ") DEFAULT CHARSET=utf8;\n"
								+ "\n"
								+ "INSERT INTO `" + TABLE_WEAPON + "` VALUES\n");
					else if (count % SPLIT == 0)
						out.write(";\nINSERT INTO `" + TABLE_WEAPON + "` VALUES\n");
					else
						out.write(",\n");
					L2Weapon weapon = (L2Weapon)ItemTable.getInstance().getTemplate(id);
					String sql = "(" + weapon.getItemId()
						+ ",'" + escape(weapon.getName()) + "'"
						+ ",''"				//TODO: `additionalname`
						+ ",'" + slots.get(weapon.getBodyPart()) + "'"
						+ ",'" + weapon.isCrystallizable() + "'"
						+ ","  + weapon.getWeight()
						+ ","  + weapon.getSoulShotCount()
						+ ","  + weapon.getSpiritShotCount()
						+ ",'" + materials.get(weapon.getMaterialType()) + "'"
						+ ","  + crystalTypes.get(weapon.getCrystalType()) + "'"
						+ ",0"				//TODO: `p_dam`
						+ ","  + weapon.getRandomDamage()
						+ ",'" + weapon.getItemType().toString() + "'"	//TODO: .toLowerCase() ??
						+ ",0"				//TODO: `critical`
						+ ",0"				//TODO: `hit_modify`
						+ ",0"				//TODO: `avoid_modify`
						+ ",0"				//TODO: `shield_def`
						+ ",0"				//TODO: `shield_def_rate`
						+ ",0"				//TODO: `atk_speed`
						+ ","  + weapon.getMpConsume()
						+ ",0"				//TODO: `m_dam`
						+ ","  + weapon.getDuration()
						+ ","  + weapon.getTime()
						+ ","  + getPrice(weapon)
						+ ","  + weapon.getCrystalCount()
						+ ",'" + weapon.isSellable() + "'"
						+ ",'" + weapon.isDropable() + "'"
						+ ",'" + weapon.isDestroyable() + "'"
						+ ",'" + weapon.isTradeable() + "'"
						+ ",'" + weapon.isDepositable() + "'"
						+ ","  + weapon.getEnchant4Skill().getId()
						+ ","  + weapon.getEnchant4Skill().getLevel()
						+ ",0"				//TODO: `onCast_skill_id`
						+ ",0"				//TODO: `onCast_skill_lvl`
						+ ",0"				//TODO: `onCast_skill_chance`
						+ ",0"				//TODO: `onCrit_skill_id`
						+ ",0"				//TODO: `onCrit_skill_lvl`
						+ ",0"				//TODO: `onCrit_skill_chance`
						+ ","  + weapon.getChangeWeaponId()
						+ ",'" + skillsToString(weapon.getSkills()) + "'"
						+ ")";
					out.write(sql);
					++count;
				}
				out.write(";\n");
				out.close();
				activeChar.sendMessage("Done.");
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		return true;
	}
	
	private String escape(String s)
	{
		return s.replace("'", "\\'");
	}
	
	private float getPrice(L2Item item)
	{
		return item.isConsumable() ? item.getReferencePrice() / Config.RATE_CONSUMABLE_COST : item.getReferencePrice();
	}
	
	private String skillsToString(SkillHolder[] skills)
	{
		StringBuilder sb = new StringBuilder(70);
		for (SkillHolder s : skills)
			sb.append(s.getSkillId()).append('-').append(s.getSkillLvl()).append(';');
		return sb.length() > 0 ? sb.toString() : "0-0;";
	}
	
	public String[] getAdminCommandList()
	{
		return ADMIN_COMMANDS;
	}
}
