/*
 * 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;

import java.util.List;

import javolution.util.FastList;
import com.festina.gameserver.ai.CtrlIntention;
import com.festina.gameserver.SkillTable;
import com.festina.gameserver.instancemanager.GrandBossManager;
import com.festina.gameserver.model.L2Attackable;
import com.festina.gameserver.model.actor.instance.L2NpcInstance;
import com.festina.gameserver.model.actor.instance.L2GrandBossInstance;
import com.festina.gameserver.model.actor.instance.L2PcInstance;
import com.festina.gameserver.model.zone.type.L2BossZone;
import com.festina.gameserver.serverpackets.PlaySound;
import com.festina.gameserver.serverpackets.SocialAction;
import com.festina.gameserver.templates.StatsSet;
import com.festina.util.Rnd;
import ai.L2AttackableAIScript;

/**
 * Queen Ant AI
 * @author Emperorc
 *
 */
public class QueenAnt extends L2AttackableAIScript
{
	private static final int QUEEN = 12001;
	private static final int LARVA = 12002;
	private static final int NURSE = 12003;
	private static final int GUARD = 12004;
	private static final int ROYAL = 12005;

	//QUEEN Status Tracking :
	private static final byte ALIVE = 0;	//Queen Ant is spawned.
	private static final byte DEAD = 1;		//Queen Ant has been killed.

	private static L2BossZone _Zone;
	private static List<L2Attackable> _Minions = new FastList<L2Attackable>();

	public QueenAnt (int questId, String name, String descr)
	{
        super(questId,name,descr);
        int[] mobs = {QUEEN, LARVA, NURSE, GUARD, ROYAL};
        registerMobs(mobs);
        _Zone = GrandBossManager.getInstance().getZone(-21610,181594,-5734);

        StatsSet info = GrandBossManager.getInstance().getStatsSet(QUEEN);
        int status = GrandBossManager.getInstance().getBossStatus(QUEEN);
        if (status == DEAD)
        {
            // load the unlock date and time for queen ant from DB
            long temp = info.getLong("respawn_time") - System.currentTimeMillis();
            // if queen ant is locked until a certain time, mark it so and start the unlock timer
            // the unlock time has not yet expired.
            if (temp > 0)
                startQuestTimer("queen_unlock", temp, null, null);
            else
            {
                // the time has already expired while the server was offline. Immediately spawn queen ant.
                L2GrandBossInstance queen = (L2GrandBossInstance) addSpawn(QUEEN,-21610,181594,-5734,0,false,0);
                GrandBossManager.getInstance().setBossStatus(QUEEN,ALIVE);
                spawnBoss(queen);
            }
        }
        else
        {
            int loc_x = info.getInteger("loc_x");
            int loc_y = info.getInteger("loc_y");
            int loc_z = info.getInteger("loc_z");
            int heading = info.getInteger("heading");
            int hp = info.getInteger("currentHP");
            int mp = info.getInteger("currentMP");
            L2GrandBossInstance queen = (L2GrandBossInstance) addSpawn(QUEEN,loc_x,loc_y,loc_z,heading,false,0);
            queen.setCurrentHpMp(hp,mp);
            spawnBoss(queen);
        }
	}

    public void spawnBoss(L2GrandBossInstance npc)
    {
        GrandBossManager.getInstance().addBoss(npc);
        /*if (Rnd.get(100) < 33)
            _Zone.movePlayersTo(-19480,187344,-5600);
        else if (Rnd.get(100) < 50)
            _Zone.movePlayersTo(-17928,180912,-5520);
        else
            _Zone.movePlayersTo(-23808,182368,-5600);*/
        GrandBossManager.getInstance().addBoss(npc);
        startQuestTimer("action",10000, npc, null, true);
        npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
        //Spawn minions
        addSpawn(LARVA,-21600,179482,-5846,Rnd.get(360),false,0);//.setIsRaidMinion(true);
        addSpawn(NURSE,-22000,179482,-5846,0,false,0);//.setIsRaidMinion(true);
        addSpawn(NURSE,-21200,179482,-5846,0,false,0);//.setIsRaidMinion(true);
        int radius = 400;
        for (int i=0;i<6;i++)
        {
            int x = (int) (radius*Math.cos(i*1.407)); //1.407~2pi/6
            int y = (int) (radius*Math.sin(i*1.407));
            addSpawn(NURSE,npc.getX()+x,npc.getY()+y,npc.getZ(),0,false,0);//.setIsRaidMinion(true);
        }
        for (int i=0;i<8;i++)
        {
            int x = (int) (radius*Math.cos(i*.7854)); //.7854~2pi/8
            int y = (int) (radius*Math.sin(i*.7854));
            L2NpcInstance mob = addSpawn(ROYAL,npc.getX()+x,npc.getY()+y,npc.getZ(),0,false,0);
            //mob.setIsRaidMinion(true);
            _Minions.add((L2Attackable)mob);
        }
        startQuestTimer("check_royal__Zone",120000,npc,null,true);
    }

	public String onAdvEvent(String event, L2NpcInstance npc, L2PcInstance player)
	{
        if (event.equalsIgnoreCase("action") && npc != null)
        {
            if (Rnd.get(3)==0)
            {
                if (Rnd.get(2)==0)           
                    npc.broadcastPacket(new SocialAction(npc.getObjectId(),3));
                else
                    npc.broadcastPacket(new SocialAction(npc.getObjectId(),4));
            }
        }
        else if (event.equalsIgnoreCase("queen_unlock"))
        {
            L2GrandBossInstance queen = (L2GrandBossInstance) addSpawn(QUEEN,-21610,181594,-5734,0,false,0);
            GrandBossManager.getInstance().setBossStatus(QUEEN,ALIVE);
            spawnBoss(queen);
        }
        else if (event.equalsIgnoreCase("check_royal__Zone") && npc != null)
        {
            for (int i=0;i<_Minions.size();i++)
            {
            	L2Attackable mob = _Minions.get(i);
                if (mob != null && !_Zone.isInsideZone(mob))
                {
                    mob.teleToLocation(npc.getX(),npc.getY(),npc.getZ());
                }
            }
        }
        else if (event.equalsIgnoreCase("despawn_royals"))
        {
            for (int i=0;i<_Minions.size();i++)
            {
            	L2Attackable mob = _Minions.get(i);
                if (mob != null)
                {
                	mob.decayMe();
                }
            }
            _Minions.clear();
        }
        else if (event.equalsIgnoreCase("spawn_royal"))
        {
            L2NpcInstance mob = addSpawn(ROYAL,npc.getX(),npc.getY(),npc.getZ(),0,false,0);
            //mob.setIsRaidMinion(true);
            _Minions.add((L2Attackable)mob);
        }
        else if (event.equalsIgnoreCase("spawn_nurse"))
        {
            addSpawn(NURSE,npc.getX(),npc.getY(),npc.getZ(),0,false,0);//.setIsRaidMinion(true);
        }
        return super.onAdvEvent(event, npc, player);
	}

    public String onFactionCall(L2NpcInstance npc, L2NpcInstance caller, L2PcInstance attacker, boolean isPet)
    {
        if (caller == null || npc == null)
	{
		System.out.println("LOOOOOOOOOOOOOOOOOOOOOOOOOL");
        	return super.onFactionCall(npc, caller, attacker, isPet);
	}
        npc.setTarget(caller);
        npc.doCast(SkillTable.getInstance().getInfo(1015,15));
	//TODO: пока используем батл хил, внизу скилы нужно реализовать в ядре (не кастуется на таргет).
        //npc.doCast(SkillTable.getInstance().getInfo(4020,1));
        //npc.doCast(SkillTable.getInstance().getInfo(4024,1));
        return super.onFactionCall(npc, caller, attacker, isPet);
    }

    public String onAttack(L2NpcInstance npc, L2PcInstance attacker, int damage, boolean isPet)
    {
        int npcId = npc.getNpcId();
        if (npcId == NURSE)
        {
            npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null, null);
            return null;
        }
        return super.onAttack(npc, attacker, damage, isPet);
    }

    public String onKill(L2NpcInstance npc, L2PcInstance killer, boolean isPet)
    {
        int npcId = npc.getNpcId();
        if (npcId == QUEEN)
        {
            npc.broadcastPacket(new PlaySound(1, "BS02_D", 1, npc.getObjectId(), npc.getX(), npc.getY(), npc.getZ()));
            GrandBossManager.getInstance().setBossStatus(QUEEN,DEAD);
            //time is 36hour	+/- 17hour
            long respawnTime = (20 + Rnd.get(-8, 8)) * 3600000;
            startQuestTimer("queen_unlock", respawnTime, null, null);
            cancelQuestTimer("action", npc, null);
            // also save the respawn time so that the info is maintained past reboots
            StatsSet info = GrandBossManager.getInstance().getStatsSet(QUEEN);
            info.set("respawn_time",System.currentTimeMillis() + respawnTime);
            GrandBossManager.getInstance().setStatsSet(QUEEN,info);
            startQuestTimer("despawn_royals",20000,null,null);
            this.cancelQuestTimers("spawn_minion");
        }
        else if (GrandBossManager.getInstance().getBossStatus(QUEEN) == ALIVE)
        {
            if (npcId == ROYAL)
            {
                _Minions.remove(npc);
                this.startQuestTimer("spawn_royal", (120 + Rnd.get(40)) * 1000, npc, null);
            }
            else if (npcId == NURSE)
            {
                startQuestTimer("spawn_nurse", 60 * 1000, npc, null);
            }
        }
        return super.onKill(npc,killer,isPet);
    }

    public static void main(String[] args)
    {
    	// now call the constructor (starts up the ai)
    	new QueenAnt(-1,"queen_ant","ai");
    }
}