/*
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package events.MasterOfEnchanting;

/**
 * Author JOJO
 *   l2j-free より拝借
 *   http://svn.l2jfree.com/svn/l2j-free/trunk/l2jfree-datapack/data/scripts/official_events/8021_MasterOfEnchanting/__init__.py
 *   r7350  2009/10/27 03:12:36
 *  
 * 関連: AbstractEnchantPacket.java
	Character.properties の EnchantSafeMax など
	エンチャント成功率を高レートに設定していると +23 まで失敗しないため、ゲームにならないので
	成功率を他のスクロールとは別個に決定する改造.
 */

/**
 * Author Psycho(killer1888) / L2jFree
 */

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;

import javolution.util.FastList;

import com.l2jserver.gameserver.model.L2ItemInstance;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.itemcontainer.Inventory;
import com.l2jserver.gameserver.model.quest.Quest;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.util.Rnd;
import com.l2jserver.util.Util;

class MasterOfEnchanting extends Quest
{
	//-------------------- TO MODIFY --------------------//
	
	// Start and End date of the event, end date included for the event (Format: yyyy/MM/dd )
	// Retail: 2009/04/14 - 2009/04/28
	private static final String DATE_FORMAT    = "yyyy/MM/dd";
	private static final String EVENTSTARTDATE = "2009/04/14";
	private static final String EVENTENDDATE   = "2009/04/28";
	
	// Despawn Yogi at end date? Will start a check every 30 minutes to check if event is over and in case unspawn every npc.
	// Usefull if you don't have a server reboot everyday.
	// Note that their is no auto start for the event. If the server loads the script on the day or after the start day but
	// before end date, the event will be considered as started and will automatically spawn Yogi. It won't spawn them
	// by itself on midnight the starting day.
	private static final boolean AUTODESPAWN = true;
	
	// Prevents player under that level to get scrolls, to block people creating accounts and accounts on private servers.
	// Retail = 0
	private static final int ALLOWEDLEVELS = 0;
	
	// Rate drop adena. This will influence the scroll/staff prices on Master Yogi.
	// If RATEADENA = 0 it will use your actual server config for adena drop rate
	// If higher, it will multiply the prices by your value
	// Ratail would then be 1
	private static final int RATEADENA = 1;
	
	// As it subsists and it's a known fact that enchant exploit still exists, the script will log user that bring
	// Yogi staffs with equal or higher enchant value than this option. (So if you see lots of times a player bringing
	// a +23 Staff, you might consider checking how he did it...)
	// 0 to disable
	private static final int LOGVALUE = 0;
	
	// This option permits you to forbid access to the event to the ACCOUNTS listed in it. Do not use capital letters.
	// Usefull if you have doubts about player accounts using exploits.
	private static final String[] FORBIDDEN_ACCOUNTS = {"test"};
	
	//-------------------- END USER MODIFICATIONS --------------------//
	
	private static final String qn = "MasterOfEnchanting";

	// NPC
	private static final int YOGI   = 32599;	//山奥の仙人 マスターヨギ

	// ITEM
	private static final int STAFF  = 13539;	//マスターヨギのスタッフ
	private static final int SCROLL = 13540;	//マスターヨギの武器強化スクロール
 //	private static final int BOX    = 13541;	//ヨギのエンチャント宝箱
 //	private static final int CUBE   = 13542;	//ヨギのエンチャント報賞キューブ
	private static final int ADENA  = 57;

	// REWARDS
	private static final int[] FIRECRACKER           = {6406};	//6406 花火
	private static final int[] LFIRECRACKER          = {6407};	//6407 大花火
	private static final int[] SHADOW_HAIR_ACCESSORY = {13074, 13075, 13076};
										//13074 幻影兵器：マジシャンズ ハット
										//13075 幻影兵器：謎のヒーローマスク
										//13076 幻影兵器：ジュブナイル ゴーグル
	private static final int[] EWD                   = {955};	//955 武器強化スクロール：Dグレード
	private static final int[] EAD                   = {956};	//956 防具強化スクロール：Dグレード
	private static final int[] EWC                   = {951};	//951 武器強化スクロール：Cグレード
	private static final int[] EAC                   = {952};	//952 防具強化スクロール：Cグレード
	private static final int[] EAB                   = {948};	//948 防具強化スクロール：Bグレード
	private static final int[] EWA                   = {729};	//729 武器強化スクロール：Aグレード
	private static final int[] HAIR_ACCESSORY        = {13518, 13519, 13522};
										//13518 マジシャンズ ハット：イベント
										//13519 謎のヒーローマスク：イベント
										//13522 ジュブナイル ゴーグル：イベント
	private static final int[] S_ACCESSORY           = {13992};	//13992 Sグレード アクセサリーの箱：イベント
	private static final int[] HIGH_LIFESTONE        = {8752};	// 8752 上級 生命の石：レベル76
	private static final int[] EWS                   = {959};	//  959 武器強化スクロール：Sグレード
	private static final int[] S_ARMOR               = {13991};	//13991 Sグレード 防具の箱：イベント
	private static final int[] S_WEAPON              = {13990};	//13990 Sグレード 武器の箱：イベント
	private static final int[] TOP_LIFESTONE         = {8762};	// 8762 最上級生命の石：レベル76
	private static final int[] SOULCRY               = {9570, 9571, 9572};
										//9570 レッド ソウル ストーン：ステップ14
										//9571 ブルー ソウル ストーン：ステップ14
										//9572 グリーン ソウル ストーン：ステップ14
	private static final int[] S80_ARMOR             = {13989};	//13989 S80グレード防具の箱：イベント
	private static final int[] S80_WEAPON            = {13988};	//13988 S80グレード武器の箱：イベント
	
	private static final int[] a1 = {1}, a2 = {2}, a3 = {3};	//amount
	
	private static final int[][][][] REWARDS = {
	{{FIRECRACKER, a1}},						//+4:小花火 1個
	{{FIRECRACKER, a2}, {LFIRECRACKER, a1}},	//+5:小花火 2個、大花火 1個
	{{FIRECRACKER, a3}, {LFIRECRACKER, a2}},	//+6:小花火 3個、大花火 2個
	{{SHADOW_HAIR_ACCESSORY, a1}},				//+7:幻影ヘアアクセサリー 1個
	{{EWD, a1}},								//+8:武器強化スクロール：Dグレード1枚
	{{EWD, a1}, {EAD, a1}},						//+9:武器・防具強化スクロール：Dグレード 各１枚ずつ
	{{EWC, a1}},								//+10:武器強化スクロール：Cグレード1枚
	{{EWC, a1}, {EAC, a1}},						//+11:武器・防具強化スクロール：Cグレード 各1枚ずつ
	{{EAB, a1}},								//+12:武器強化スクロール：Bグレード1枚
	{{EWA, a1}},								//+13:武器強化スクロール：Aグレード1枚
	{{HAIR_ACCESSORY, a1}},						//+14:ヘアアクセサリー 1個
	{{S_ACCESSORY, a1}},						//+15:Sグレード アクセサリーの箱：イベント用 1個
	{{HIGH_LIFESTONE, a1}},						//+16:最上級 生命の石：76レベル 1個
	{{EWS, a1}},								//+17:武器強化スクロール：Sグレード1枚
	{{S_ARMOR, a1}},							//+18:Sグレード 防具の箱：イベント用 1個
	{{S_WEAPON, a1}},							//+19:Sグレード 武器の箱：イベント用 1個
	{{SOULCRY, a1}},							//+20:ソウル ストーン：ステップ14レッド・グリーン・ブルーのいずれか1個
	{{{8762, 8752, 9570, 9571, 9572}, a1}},		//+21:最上級、上級生命の石：76レベル、ソウルストーン：ステップ14 レッド・グリーン・ブルー いずれか1個
	{{S80_ARMOR, a1}},							//+22:S80グレード 防具の箱 1個
	{{S80_WEAPON, a1}},							//+23:S80グレード 武器の箱 1個
	};
	//TODO: 2010年版 - マスター ヨギと交換せずにイベント終了の定期メンテナンス時まで所持しておくともらえる
	// +24 ザケン イヤリング 1個
	// +25 クイーン アント リング 1個
	// +26 バイウム リング 1個
	
	private static final int[] TEXTS = {1600024, 1600023};
 //	private static final String[] TEXTS = {"Don't pass up the chance to win an S80 Weapon.", "Care to challenge fate and test your luck?"};
	
	private static final int RATE = RATEADENA != 0 ? RATEADENA : 1/*Config.RATE_DROP_ADENA*/;
	
	private long _EVENTSTARTDATE, _EVENTENDDATE;
	private List<L2Npc> _yogiSpawnList;

	private long checkRemainingTime(L2PcInstance player)
	{
		long currentTime = System.currentTimeMillis() / 1000;
		String account = player.getAccountName();
		String state = loadGlobalQuestVar(account);
		if (state.length() > 0) {
			long remainingTime = Long.valueOf(state) + 21600/*6H*/ - currentTime;
			if (remainingTime > 0)
				return remainingTime;
		}
		saveGlobalQuestVar(account, String.valueOf(currentTime));
		return 0;
	}
	
	private void rewardPlayer(QuestState st, int enchant)
	{
		st.takeItems(STAFF, -1);
		if (enchant > 23)
			enchant = 23;
		int[][][] rewardList = REWARDS[enchant-4];
		for (int[][] reward : rewardList) {
			int[] itemList = reward[0];
			int amount = reward[1][0];
			int item = itemList[Rnd.get(itemList.length)];
			st.giveItems(item, amount);
		}
		return;
	}

	public MasterOfEnchanting(int questId, String name, String descr)
	{
		super(questId, name, descr);

		addStartNpc(YOGI);
		addTalkId(YOGI);
		addSpawnId(YOGI);

		SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT);
		try
		{
			_EVENTSTARTDATE = format.parse(EVENTSTARTDATE).getTime();
			_EVENTENDDATE = format.parse(EVENTENDDATE).getTime();
			System.out.println("MasterOfEnchanting:210: " + Util.dateFormat(_EVENTSTARTDATE) + " - " + Util.dateFormat(_EVENTENDDATE)); // verify
		}
		catch (ParseException e)
		{
			e.printStackTrace();
		}

		long DATE = System.currentTimeMillis();
		if (DATE >= _EVENTSTARTDATE && DATE <=_EVENTENDDATE) {
			startQuestTimer("SpawnYogi", 30000, null, null);
			System.out.println("Master of Enchanting event is ON");
		} else {
			System.out.println("Master of Enchanting event is OFF");
		}
	}
	
	@SuppressWarnings("unused")
	@Override
	public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
	{
		if (event == "Autochat") {
			npc.broadcastPacket(new NpcSay(npc.getObjectId(), 0, npc.getNpcId(), TEXTS[Rnd.get(TEXTS.length)]));
			return null;
		} else if (event == "SpawnYogi") {
			_yogiSpawnList = new FastList<L2Npc>();
			_yogiSpawnList.add(addSpawn(YOGI, 82941, 149318, -3473, 39138, false, 0, false, 0));
			_yogiSpawnList.add(addSpawn(YOGI, 148022, -55481, -2738, 34214, false, 0, false, 0));
			_yogiSpawnList.add(addSpawn(YOGI, 15776, 142872, -2710, 17423, false, 0, false, 0));
			_yogiSpawnList.add(addSpawn(YOGI, -14067, 123290, -3121, 18774, false, 0, false, 0));
			_yogiSpawnList.add(addSpawn(YOGI, 87015, -143229, -1296, 4092, false, 0, false, 0));
			_yogiSpawnList.add(addSpawn(YOGI, 117104, 77017, -2699, 32767, false, 0, false, 0));
			_yogiSpawnList.add(addSpawn(YOGI, 146772, 25906, -2017, 57344, false, 0, false, 0));
			_yogiSpawnList.add(addSpawn(YOGI, 43984, -47713, -801, 47497, false, 0, false, 0));
			_yogiSpawnList.add(addSpawn(YOGI, 82882, 53098, -1500, 17351, false, 0, false, 0));
			_yogiSpawnList.add(addSpawn(YOGI, -83127, 150941, -3133, 0, false, 0, false, 0));
			_yogiSpawnList.add(addSpawn(YOGI, 111333, 219424, -3550, 48247, false, 0, false, 0));
			if (AUTODESPAWN)
				startQuestTimer("DespawnYogi", 1800000, null, null);
			return null;
		} else if (event == "DespawnYogi") {
			long DATE = System.currentTimeMillis();
			if (DATE <= _EVENTENDDATE) {
				startQuestTimer("DespawnYogi", 1800000, null, null);
			} else {
				for (L2Npc yogi : _yogiSpawnList)
					yogi.decayMe();
				System.out.println("Master of Enchanting event is finished");
			}
			return null;
		}
		QuestState st = player.getQuestState(qn);
		if (st == null) st = newQuestState(player);
		String htmltext = event;
		int npcId = npc.getNpcId();
		if (npcId == YOGI) {
			if (event.equals("32599.htm")) {
				htmltext = st.showHtmlFile("32599.htm")
							.replace("Adena1", String.valueOf(1000 * RATE))
							.replace("Adena2", String.valueOf(6000 * RATE))
							.replace("Adena3", String.valueOf(77777 * RATE))
							.replace("Adena4", String.valueOf(777770 * RATE));
			} else if (event.equals("32599-01.htm")) {
				if (st.getQuestItemsCount(STAFF) >= 1 || st.getQuestItemsCount(ADENA) < 1000 * RATE) {
					htmltext = "32599-02.htm";
				} else {
					st.takeItems(ADENA, 1000 * RATE);
					st.giveItems(STAFF, 1);
				}
			} else if (event.equals("32599-03.htm")) {
				long remainingTime;
				if (st.getQuestItemsCount(ADENA) < 6000 * RATE) {
					htmltext = "32599-02.htm";
				} else if ((remainingTime = this.checkRemainingTime(player)) > 0) {
					htmltext = "32599-02.htm";
					player.sendPacket(SystemMessage.sendString("Remaining time: " + remainingTime + " seconds"));
				} else {
					st.takeItems(ADENA, 6000 * RATE);
					st.giveItems(SCROLL, 24);
				}
			} else if (event.equals("32599-05.htm")) {
				if (st.getQuestItemsCount(ADENA) < 77777 * RATE) {
					htmltext = "32599-02.htm";
				} else {
					st.takeItems(ADENA, 77777 * RATE);
					st.giveItems(SCROLL, 1);
				}
			} else if (event.equals("32599-06.htm")) {
				if (st.getQuestItemsCount(ADENA) < 777770 * RATE) {
					htmltext = "32599-02.htm";
				} else {
					st.takeItems(ADENA, 777770 * RATE);
					st.giveItems(SCROLL, 10);
				}
			} else if (event.equals("Rewards")) {
				String account = player.getAccountName();
				if (contains(FORBIDDEN_ACCOUNTS, account)) {
					player.sendPacket(SystemMessage.sendString("Your account is not allowed to participate in the event. Contact a GameMaster if you need explanations."));
					return "";
				}
				L2ItemInstance weapon = player.getInventory().getPaperdollItem(Inventory.PAPERDOLL_LRHAND);
				if (weapon != null) {
					int weaponId = weapon.getItemId();
					if (weaponId == STAFF && weapon.getEnchantLevel() > 3) {
						int enchant = weapon.getEnchantLevel();
						if (LOGVALUE > 0 && enchant >= LOGVALUE) {
							System.out.println("Master of Enchanting event: Player " + player.getName() + " brought a +" + enchant + " weapon");
						}
						this.rewardPlayer(st, enchant);
						htmltext = "32599-08.htm";
					} else {
						htmltext = "32599-07.htm";
					}
				} else {
					htmltext = "32599-07.htm";
				}
			}
		}
		return htmltext;
	}

	@SuppressWarnings("unused")
	@Override
	public String onTalk(L2Npc npc, L2PcInstance player)
	{
		String htmltext = "<html><body>You are either not on a quest that involves this NPC, or you don't meet this NPC's minimum quest requirements.</body></html>";
		QuestState st = player.getQuestState(qn);
		if (st == null) return htmltext;
		int npcId = npc.getNpcId();
		if (npcId == YOGI) {
			String account = player.getAccountName();
			if (contains(FORBIDDEN_ACCOUNTS, account)) {
				player.sendPacket(SystemMessage.sendString("Your account is not allowed to participate in the event. Contact a GameMaster if you need explanations."));
				return "";
			}
			if (ALLOWEDLEVELS > 0 && player.getLevel() < ALLOWEDLEVELS) {
				player.sendPacket(SystemMessage.sendString("Sorry, you may only take part of this event once you reached level " + ALLOWEDLEVELS));
				return "";
			}
			htmltext = st.showHtmlFile("32599.htm")
				.replace("Adena1", String.valueOf(1000 * RATE))
				.replace("Adena2", String.valueOf(6000 * RATE))
				.replace("Adena3", String.valueOf(77777 * RATE))
				.replace("Adena4", String.valueOf(777770 * RATE));
		}
		return htmltext;
	}
	
	@Override
	public String onSpawn(L2Npc npc)
	{
	    startQuestTimer("Autochat", 60000, npc, null, true);
	    return null;
	}

	private static boolean contains(String[] array, String obj)
	{
		for (String f : array)
			if (f.equals(obj)) return true;
		return false;
	}

	public static void main(String[] args)
	{
		new MasterOfEnchanting(-1, qn, "events");
	}
}