package com.l2jfrozen.gameserver.model.entity.tops;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Logger;

import com.l2jfrozen.Config;
import com.l2jfrozen.gameserver.model.actor.instance.L2PcInstance;
import com.l2jfrozen.gameserver.powerpak.L2Utils;
import com.l2jfrozen.gameserver.thread.ThreadPoolManager;
import com.l2jfrozen.gameserver.util.sql.SQLQuery;
import com.l2jfrozen.gameserver.util.sql.SQLQueue;
import com.l2jfrozen.util.CloseUtil;
import com.l2jfrozen.util.database.L2DatabaseFactory;
import com.l2jfrozen.util.random.Rnd;

public class L2Top implements Runnable
{
	private static L2Top _instance = null;
	public static L2Top getInstance()
	{
		if(_instance == null)
			_instance = new L2Top();
		return _instance;
	}
	private static final Logger _log = Logger.getLogger(L2Top.class.getName());
    private ScheduledFuture<?> _task;
	private Timestamp _lastVote;
	private boolean _firstRun = false;

	private class Terminator extends Thread
	{
		@Override
		public void run()
		{
			System.out.println("L2Top: stopped");
			try
			{
				if(L2Top.getInstance()._task!=null)
				{
					L2Top.getInstance()._task.cancel(true);
				}
			}
			catch(Exception e)
			{
				if(Config.ENABLE_ALL_EXCEPTIONS)
					e.printStackTrace();
				
			}
		}
	}
	private L2Top()
	{
		_lastVote = null;
		if(Config.L2TOPDEMON_ENABLED)
		{
			Connection con = null;
			try
			{
				con = L2DatabaseFactory.getInstance().getConnection(false);
				PreparedStatement stm = con.prepareStatement("select max(votedate) from l2top_votes");
				ResultSet r = stm.executeQuery();
				if(r.next())
					_lastVote = r.getTimestamp(1);
				if(_lastVote == null)
				{
					_firstRun = true;
					_lastVote = new Timestamp(0);
				}
				r.close();
				stm.close();
				
				_task = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(this, 60000, Config.L2TOPDEMON_POLLINTERVAL * 60000);
				Runtime.getRuntime().addShutdownHook(new Terminator());
				_log.info("L2Top: Started with poll interval " + Config.L2TOPDEMON_POLLINTERVAL + " minute(s)");
			}
			catch(SQLException e)
			{
				if(Config.ENABLE_ALL_EXCEPTIONS)
					e.printStackTrace();

				_log.info("L2Top: Error connection to database: " + e.getMessage());
			}
			finally
			{
				CloseUtil.close(con);
				con = null;
			}
		}
	}
	private class VotesUpdate implements SQLQuery
	{
		private Timestamp _votedate; 
		private String _charName;
		private boolean _fr;
		public VotesUpdate(Timestamp votedate, String charName, boolean fr)
		{
			_votedate = votedate;
			_charName = charName;
			_fr = fr;
		}
		@Override
		public void execute(Connection con)
		{
			try
			{
				PreparedStatement stm = con.prepareStatement("insert into l2top_votes select ?,? from characters where not exists(select * from l2top_votes where votedate=? and charName =?) limit 1");
				stm.setTimestamp(1, _votedate);
				stm.setTimestamp(3, _votedate);
				stm.setString(2, _charName);
				stm.setString(4, _charName);
				boolean sendPrize  = stm.executeUpdate()>0; 
				stm.close();
				if(_fr && Config.L2TOPDEMON_IGNOREFIRST)
					sendPrize = false;
				if(sendPrize)
				{
					L2PcInstance player = L2Utils.loadPlayer(_charName);
					if(player!=null)
					{
						int numItems = Config.L2TOPDEMON_MIN;
						if(Config.L2TOPDEMON_MAX > Config.L2TOPDEMON_MIN )
							numItems += Rnd.get(Config.L2TOPDEMON_MAX-Config.L2TOPDEMON_MIN);
						player.addItem("l2top", Config.L2TOPDEMON_ITEM, numItems, null, true);
						if(player.isOnline()!=0 && Config.L2TOPDEMON_MESSAGE != null && Config.L2TOPDEMON_MESSAGE.length() >0)
							player.sendMessage(Config.L2TOPDEMON_MESSAGE);
						player.store();
					}
				}
			}
			catch(SQLException e)
			{
				e.printStackTrace();
			}
		}
	}

	private boolean checkVotes()
	{
		try
		{
			_log.info("L2Top: Checking l2top.ru....");
			int nVotes = 0;
			URL url = new URL(Config.L2TOPDEMON_URL);
			BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
			if(reader!=null)
			{
				String line;
				Timestamp last = _lastVote;
				while((line= reader.readLine())!=null)
				{
					if(line.indexOf("\t")!=-1)
					{
						Timestamp voteDate = Timestamp.valueOf(line.substring(0,line.indexOf("\t")).trim());
						if(voteDate.after(_lastVote))
						{
							if(voteDate.after(last))
								last = voteDate;
							String charName = line.substring(line.indexOf("\t")+1).toLowerCase();
							if(Config.L2TOPDEMON_PREFIX!=null && Config.L2TOPDEMON_PREFIX.length()>0)
								if(charName.startsWith(Config.L2TOPDEMON_PREFIX)) {
									charName = charName.substring(Config.L2TOPDEMON_PREFIX.length());
								}
								else
									continue;
							SQLQueue.getInstance().add(new VotesUpdate(voteDate,charName,_firstRun));
							nVotes++;
						}
					}
				}
				_lastVote = last;
				_log.info("L2Top: "+nVotes+" vote(s) parsed");
				return true;
			}
		} catch(Exception e)
		{
			if(Config.ENABLE_ALL_EXCEPTIONS)
				e.printStackTrace();
			
			_log.info("L2Top: Error while reading data"+ e);
		}
		return false;
	}
	@Override
	public void run()
	{
		checkVotes();
		_firstRun = false;
		
	}
}
