/***********************************************************************/
/**                               調整中                              **/
/***********************************************************************/

/*
 * 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 ai.fantasy_isle;

import java.text.SimpleDateFormat;
import java.util.Iterator;
import java.util.concurrent.ScheduledFuture;

import javolution.util.FastList;
import ai.group_template.L2AttackableAIScript;

import com.l2jserver.gameserver.GameTimeController;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.model.L2CharPosition;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.network.serverpackets.NpcSay;

/**
 * Fantasy Isle Parade
 * @author JOJO
 */
public class Parade extends L2AttackableAIScript
{
	private static final boolean DEBUG = true;
	private final int[] ACTORS = {
		32381, 32379, 32381,
		32382, 32383, 32384,
		32381, 32385, 32381,
		32384, 32383,32382,
		
		32386,
		32387,
		32388,
		32389,
		32390,
		
		32391,
		32392,
		32393,
		32394,
		32395,
		
		32396,
		32397,
		32398,
		32399,
		32400,
		
		32401,
		32402,
		32403,
		32404,
		
		32405,
		32406,
		32407,
		32408,
		
		32409,
		32411,
		32412,
		32413,
		32414,
		32415,
		
		32416,
		32417,
		32418,
		32419,
		32420,
		
		32421,
		32422,
		32423,
		32429,
		32430,
		
		32447,
		32448,
		32449,
		32450,
		
		32451,
		32452,
		32453,
		32454,
		32455,
		32456,
		
		0,0,0, 32415,
	};
	
	//ルート１ (270度 北行き)
	private final int[][] START1 = {{-54780, -56810, -2015, 49152},{-54860, -56810, -2015, 49152},{-54940, -56810, -2015, 49152}};
	private final int[][] GOAL1  = {{-54780, -57965, -2015, 49152},{-54860, -57965, -2015, 49152},{-54940, -57965, -2015, 49152}};
	//ルート２ (180度 西行き)
//	private final int[][] START2 = {{-55740, -58900, -2015, 32768},{-55740, -58820, -2015, 32768},{-55740, -58740, -2015, 32768}};//TODO
	private final int[][] START2 = {{-55715, -58900, -2015, 32768},{-55715, -58820, -2015, 32768},{-55715, -58740, -2015, 32768}};
	private final int[][] GOAL2  = {{-60850, -58900, -2015, 32768},{-60850, -58820, -2015, 32768},{-60850, -58740, -2015, 32768}};
	//ルート３ (90度 南行き)
	private final int[][] START3 = {{-61790, -57965, -2015, 16384},{-61710, -57965, -2015, 16384},{-61630, -57965, -2015, 16384}};
	private final int[][] GOAL3  = {{-61790, -53890, -2116, 16384},{-61710, -53890, -2116, 16384},{-61630, -53890, -2116, 16384}};
	//ルート４ (0度 東行き)
	private final int[][] START4 = {{-60840, -52990, -2108, 0},{-60840, -53070, -2108, 0},{-60840, -53150, -2108, 0}};
	private final int[][] GOAL4  = {{-58620, -52990, -2015, 0},{-58620, -53070, -2015, 0},{-58620, -53150, -2015, 0}};
	//ルート５ (315度 北東行き)
	private final int[][] START5 = {{-57233, -53554, -2015, 57344},{-57290, -53610, -2015, 57344},{-57346, -53667, -2015, 57344}};
	private final int[][] GOAL5  = {{-55338, -55435, -2015, 57344},{-55395, -55491, -2015, 57344},{-55451, -55547, -2015, 57344}};
	
	private final int[][][] START = { START1, START2, START3, START4, START5 };
	private final int[][][] GOAL  = { GOAL1, GOAL2, GOAL3, GOAL4, GOAL5 };
	
	private ScheduledFuture<?> spawnTask;
	private ScheduledFuture<?> deleteTask;
 /*	private ScheduledFuture<?> stopTask;	*/
	private ScheduledFuture<?> cleanTask;
	
	private int npcIndex;
	private FastList<L2Npc> spawns;
	
	private void load()
	{
		npcIndex = 0;
		spawns = new FastList<L2Npc>().shared();
	}
	
	private void clean()
	{
		for (Iterator<L2Npc> it = spawns.iterator(); it.hasNext(); )
		{
			L2Npc actor = it.next();
			actor.deleteMe();
			it.remove();
		}
		spawns = null;
	}
	
	public Parade(int id, String name, String descr)
	{
		super(id, name, descr);
		
		final long diff = timeLeftMilli(8, 0, 0), cycle = 3600000L; // リネ時間で8時00分開始、6時間ごと繰り返し
		if (DEBUG)
		{
			SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm");
			_log.info("Fantasy Isle: Parade script starting at " + format.format(System.currentTimeMillis() + diff) + " and is scheduled each next " + (cycle / 3600000) + " hours.");
		}
		ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new Start(), diff, cycle);
	}
	
	private long timeLeftMilli(int hh, int mm, int ss)
	{
		int now = GameTimeController.getGameTicks() * 60 / 100;
		int dd = (hh * 3600 + mm * 60 + ss) - (now % 86400);
		if (dd < 0)
			dd += 86400;
		
		return dd * 1000L / 6L;
	}
	
	private class Start implements Runnable
	{
		@Override
		public void run()
		{
			load();
			spawnTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new Spawn(), 0, 5000);
			deleteTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new Delete(), 10000, 1000);
		/*	stopTask = ThreadPoolManager.getInstance().scheduleGeneral(new Stop(), 300000);	*/
			cleanTask = ThreadPoolManager.getInstance().scheduleGeneral(new Clean(), 420000);
		}
	}
	
/*	private class Stop implements Runnable
	{
		@Override
		public void run()
		{
			spawnTask.cancel(false);
		}
	}	*/
	
	private class Spawn implements Runnable
	{
		@Override
		public void run()
		{
			for (int i = 0; i < 3; ++i) {
				if (npcIndex >= ACTORS.length) { spawnTask.cancel(false); break; }
				int npcId = ACTORS[npcIndex++];
				if (npcId == 0) continue;
				for (int route = 0; route < 5; ++route) {	//TODO:仮
					int[] start = START[route][i];
					int[] goal = GOAL[route][i];
					L2Npc actor = addSpawn(npcId, start[0], start[1], start[2], start[3], false, 0);
					actor.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new L2CharPosition(goal[0], goal[1], goal[2], goal[3]));
					spawns.add(actor);
				}
			}
		}
	}
	
	private class Delete implements Runnable
	{
		@Override
		public void run()
		{
			if (spawns.size() > 0)
			{
				for (Iterator<L2Npc> it = spawns.iterator(); it.hasNext(); )
				{
					L2Npc actor = it.next();
					if (actor.getPlanDistanceSq(actor.getXdestination(), actor.getYdestination()) < (100 * 100))
					{
						actor.deleteMe();
						it.remove();
					}
					else if (!actor.isMoving())
					{
						actor.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new L2CharPosition(actor.getXdestination(), actor.getYdestination(), actor.getZdestination(), actor.getHeading()));
System.out.println("Parade:238: "+actor.getNpcId()+" "+actor.getX()+","+actor.getY()+","+actor.getZ()+","+actor.getHeading()+" -> "+actor.getXdestination()+","+actor.getYdestination()+","+actor.getZdestination()+" "+(actor.hasAI() ? actor.getAI().getIntention().name() : "NOAI"));
actor.broadcastPacket(new NpcSay(actor.getObjectId(), 0, actor.getNpcId(), actor.getNpcId()+"/"+actor.getXdestination()+","+actor.getYdestination()+","+actor.getZdestination()));
					}
				//	else
				//		actor.broadcastPacket(new NpcSay(actor.getObjectId(), 0, actor.getNpcId(), "" + actor.getNpcId() + (actor.isMoving() ? "*" : "")));
				}
				if (spawns.size() == 0)
					deleteTask.cancel(false);
			}
		}
	}
	
	private class Clean implements Runnable
	{
		@Override
		public void run()
		{
			spawnTask.cancel(false); spawnTask = null;
			deleteTask.cancel(false); deleteTask = null;
		/*	stopTask.cancel(false); stopTask = null;	*/
			cleanTask.cancel(false); cleanTask = null;
			clean();
		}
	}
	
	public static void main(String[] args)
	{
		new Parade(-1, "Parade", "fantasy_isle");
	}
}

/**
  メモ：
    ゲーム時間での"24時間"は、現実で４時間。つまり６倍速。
    サーバ起動時は "6時"に設定される。
    ステージがはじまる"20時30分"は、サーバ起動してから"14時間30分後"なので、
    現実に換算すると(６で割ると)２時間２５分後。

    パレードはゲーム時間で
      2:00、8:00、14:00、20:00 の１日４回、６時間ごとにおこなわれる。
    ステージは
      20:30 の１回のみ。
*/
