import java.io.IOException;
import java.util.Properties;
import java.util.TimerTask;

import javax.swing.JComponent;
import javax.swing.JCheckBox;

import callback_interfaces.PluginCallbackRegister;
import callback_interfaces.PublicExposedFunctions;
import callback_interfaces.StaticExposedFunctions;
import plugin_interfaces.GenericPluginInterface;
import plugin_interfaces.PacketCallback;
import util.BNetPacket;

/*
 * Created on Dec 10, 2004
 * By iago
 */

/** This just returns pings sent from the server.  I couldn't think of where else to fit it in, so I made it its own plugin.
 * @author iago
 *
 */
public class PluginMain extends GenericPluginInterface implements PacketCallback 
{
    private PublicExposedFunctions out;
    private KeepaliveCallback callback;
    
    public void load(StaticExposedFunctions staticFuncs)
    {
    }

    public void activate(PublicExposedFunctions out, PluginCallbackRegister register)
    {
        this.out = out;
        register.registerIncomingPacketPlugin(this, SID_NULL, null);
        register.registerIncomingPacketPlugin(this, SID_PING, null);
        register.registerIncomingPacketPlugin(this, SID_AUTH_CHECK, null);
        register.registerIncomingPacketPlugin(this, SID_EXTRAWORK, null);
        try
        {
            if(out.getLocalSetting(getName(), "Send keepalive").equalsIgnoreCase("true"))
            {
                out.systemMessage(DEBUG, "Beginning keepalive timer (every 20 seconds, a SID_NULL is sent)");
                
                if(callback != null)
                    out.unschedule(callback);
                out.schedule(callback = new KeepaliveCallback(), 20000);
            }
        }
        catch(Exception e)
        {
            out.systemMessage(ERROR, "Unable to start keepalive thread (in ping plugin): " + e);
        }
    }


    public void deactivate(PluginCallbackRegister register)
    {
    }

    public BNetPacket processingPacket(BNetPacket buf, Object data)
    {
        return buf;
    }

    public void processedPacket(BNetPacket buf, Object data) throws IOException
    {
        if(buf.getCode() == SID_PING)
        {
	        // Returning a ping is very simple -- just echo back the exact packet
            out.setTCPNoDelay(true);
	        out.sendPacket(buf);
	        out.setTCPNoDelay(false);
        }
        else if(buf.getCode() == SID_AUTH_CHECK)
        {
            // added by maddox UDP ping ( so we don't get that lag plug )
            // iago edit: only do this if we passed
            if(buf.removeDWord() == 0)
            {
	            BNetPacket udpPing = new BNetPacket();
	            udpPing.setCode(SID_UDPPINGRESPONSE);
	            udpPing.addDWord(0x626E6574); // 'bnet' "tenb"
	            out.sendPacket(udpPing);
            }
        }
        else if(buf.getCode() == SID_NULL)
        {
            // Cuz some one has to do it
        }
        else if(buf.getCode() == SID_EXTRAWORK)
        {
           // 05-07-2005. Added by Joe[x86]
           out.systemMessage(DEBUG, "Recieved SID_EXTRAWORK. Ignoring.");
        }
    }

    public String getName()
    {
        return "Ping Plugin";
    }

    public String getVersion()
    {
        return "1.0";
    }

    public String getAuthorName()
    {
        return "iago";
    }

    public String getAuthorWebsite()
    {
        return "http://www.javaop.com";
    }

    public String getAuthorEmail()
    {
        return "iago@valhallalegends.com";
    }

    public String getShortDescription()
    {
        return "Looks after ping and other keepalive messages, as well as extra work.";
    }

    public String getLongDescription()
    {
        return "Returns a ping message (if set to) when SID_PING is received.  Also sends back the UDP Ping probe at the " + 
        	"appropriate time.  Either of these can be disabled to get either \"unplugged\" icon, or -1ms ping. This "+
                "also handles displaying of the SID_EXTRAWORK packet.";
        	
    }

    public Properties getDefaultSettingValues()
    {
        Properties p = new Properties();
        p.setProperty("Return Ping", "true");
        p.setProperty("Return UDP Ping", "true");
        p.setProperty("Send keepalive", "true");
        
        return p;
    }
    public Properties getSettingsDescription()
    {
        Properties p = new Properties();
        p.setProperty("Return Ping", "Turn this off to get \"unplugged\" icon.");
        p.setProperty("Return UDP Ping", "Turn this off to get -1ms ping.");
        p.setProperty("Send keepalive", "Sends out SID_NULL every 20 seconds to detect a lost connection (must reload bot to change this)");
        
        return p;
    }
	public JComponent getComponent(String settingName, String value)
	{
		return new JCheckBox("", value.equalsIgnoreCase("true"));
	}

    
    public Properties getGlobalDefaultSettingValues()
    {
        Properties p = new Properties();
        return p;
    }
    public Properties getGlobalSettingsDescription()
    {
        Properties p = new Properties();
        return p;
    }
    public JComponent getGlobalComponent(String settingName, String value)
    {
        return null;
    }
    
    

    public boolean isRequiredPlugin()
    {
        return true;
    }
    
    private class KeepaliveCallback extends TimerTask
    {
        
        public void run()
        {
            try
            {
                out.sendPacket(new BNetPacket(SID_NULL));
            }
            catch(Exception e)
            {
                out.systemMessage(WARNING, "Keepalive failed to send: " + e);
            }
        }
    }
}
