content: package com.alecgorge.minecraft.jsonapi.adminium;
  
  import java.net.URL;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.Date;
  import java.util.List;
  import java.util.logging.Handler;
  import java.util.logging.Level;
  import java.util.logging.LogRecord;
  import java.util.logging.Logger;
  
  import org.bukkit.command.CommandSender;
  import org.bukkit.event.EventHandler;
  import org.bukkit.event.Listener;
  import org.bukkit.event.player.AsyncPlayerChatEvent;
  
  import com.alecgorge.java.http.MutableHttpRequest;
  import com.alecgorge.minecraft.jsonapi.JSONAPI;
  import com.alecgorge.minecraft.jsonapi.api.JSONAPIStream;
  import com.alecgorge.minecraft.jsonapi.api.JSONAPIStreamListener;
  import com.alecgorge.minecraft.jsonapi.api.JSONAPIStreamMessage;
  import com.alecgorge.minecraft.jsonapi.streams.ConnectionMessage;
  import com.alecgorge.minecraft.jsonapi.util.FixedSizeArrayList;
  
  public class Adminium3 implements JSONAPIStreamListener {
  	public static List<String>	pushTypes				= Arrays.asList(new String[] { "calladmin","player_join","player_quit","severe","taboo" });
  	public static List<String>	pushTypeDescriptions	= Arrays.asList(new String[] { "On /calladmin","On player join","On player quit","On SEVERE logs","Chat notifications" });
  
  	public Adminium3(JSONAPI jsonapi) {
  		api = jsonapi;
  		config = Adminium3Config.config();
  
  		api.getServer().getPluginManager().registerEvents(new AdminiumChatListener(this), api);
  		mcLog.addHandler(new ConsoleHandler(this));
  
  		api.registerMethods(new Adminium3Methods(this));
  		api.getStreamManager().getStream("connections").registerListener(this, false);
  	}
  
  	List<AdminiumPushNotification>	notifications		= Collections.synchronizedList(new FixedSizeArrayList<AdminiumPushNotification>(200));
  
  	final String					APNS_PUSH_ENDPOINT	= "http://push.adminiumapp.com/push-message";
  
  	JSONAPI							api;
  	Adminium3Config					config;
  
  	public final boolean			doTrace				= false;
  
  	Logger							mcLog				= Logger.getLogger("Minecraft");
  
  	public void pushNotification(String message, String push_type) {
  		List<String> devices = new ArrayList<String>();
  
  		for (String device : config.devices.keySet()) {
  			Boolean should_recieve = config.devices.get(device).get(push_type);
  
  			if (should_recieve != null && should_recieve) {
  				devices.add(device);
  			}
  		}
  
  		AdminiumPushNotification not = new AdminiumPushNotification(new Date(), message);
  		sendNotification(devices, not);
  	}
  	
  	public boolean shouldSendNotifications() {
  		return JSONAPI.instance.adminiumEnabled && config.devices.keySet().size() > 0;
  	}
  
  	@Override
  	public void onMessage(JSONAPIStreamMessage message, JSONAPIStream sender) {
  		if (message instanceof ConnectionMessage) {
  			ConnectionMessage c = (ConnectionMessage) message;
  			if (c.TrueIsConnectedFalseIsDisconnected) {
  				pushNotification(c.player + " joined!", "player_join");
  			}
  			else {
  				pushNotification(c.player + " quit!", "player_quit");
  			}
  		}
  	}
  
  	public boolean calladmin(CommandSender from, String message) {
  		if (api.anyoneCanUseCallAdmin || from.hasPermission("jsonapi.calladmin")) {
  			String push = "Admin request from " + from.getName() + ": " + message;
  
  			pushNotification(push, "calladmin");
  			from.sendMessage("A message was sent to the admin(s).");
  		}
  		else if (!from.hasPermission("jsonapi.calladmin")) {
  			from.sendMessage("You don't have the jsonapi.calladmin permission to call for an admin.");
  		}
  
  		return true;
  	}
  
  	protected void sendNotification(final List<String> devices, final AdminiumPushNotification not) {
  		notifications.add(not);
  		
  		if(!shouldSendNotifications()) {
  			return;
  		}
  
  		api.getServer().getScheduler().runTaskAsynchronously(api, new Runnable() {
  			@Override
  			public void run() {
  				String msg = not.getPushNotification();
  				MutableHttpRequest r = null;
  				try {
  					r = new MutableHttpRequest(new URL(APNS_PUSH_ENDPOINT));
  					for (String d : devices) {
  						r.addPostValue("devices[]", d);
  					}
  					r.addPostValue("message", msg);
  
  					r.post();
  
  					JSONAPI.dbug("Sending to " + APNS_PUSH_ENDPOINT + ": " + r.getPostKeys() + " -- " + r.getPostValues());
  
  					// System.out.println(String.format("Sending %s to %d (%s) devices.",
  					// msg, devices.size(), devices.get(0)));
  				}
  				catch (Exception e) {
  					mcLog.warning("The Adminium push notification server seems to be down...push notifications will not go through at this time.");
  				}
  				finally {
  					if (r != null)
  						r.close();
  				}
  			}
  		});
  	}
  
  	public class AdminiumChatListener implements Listener {
  		Adminium3		adminium;
  		Adminium3Config	config	= Adminium3Config.config();
  
  		public AdminiumChatListener(Adminium3 ad) {
  			adminium = ad;
  		}
  
  		@EventHandler
  		public void onPlayerChat(AsyncPlayerChatEvent event) {
  			String player = event.getPlayer().getName();
  			String message = event.getMessage();
  			String lowerMessage = message.toLowerCase();
  
  			for (String device : config.devices.keySet()) {
  				if (config.taboo.containsKey(device)) {
  					for (String taboo : config.taboo.get(device)) {
  						if (lowerMessage.indexOf(taboo.toLowerCase()) > -1) {
  							String pmessage = String.format("%s mentioned %s: %s", player, taboo, message);
  							AdminiumPushNotification not = new AdminiumPushNotification(new Date(), pmessage);
  
  							List<String> devices = new ArrayList<String>();
  							devices.add(device);
  							adminium.sendNotification(devices, not);
  						}
  					}
  				}
  			}
  		}
  	}
  
  	public class ConsoleHandler extends Handler {
  		Adminium3	adminium;
  		long		lastNotification;
  
  		public ConsoleHandler(Adminium3 d) {
  			adminium = d;
  			lastNotification = 0;
  		}
  
  		@Override
  		public void close() throws SecurityException {
  		}
  
  		@Override
  		public void flush() {
  		}
  
  		@Override
  		public void publish(LogRecord arg0) {
  			if (arg0 != null && arg0.getLevel().equals(Level.SEVERE)) {
  				String message = "SEVERE message: " + arg0.getMessage();
  
  				long time = (new Date()).getTime();
  				if (time - lastNotification > 60 * 1000) {
  					lastNotification = time;
  
  					adminium.pushNotification(message, "severe_log");
  				}
  			}
  		}
  	}
  
  	public class AdminiumPushNotification {
  		Date	dateSent;
  		String	notification;
  
  		public AdminiumPushNotification(Date d, String message) {
  			dateSent = d;
  			notification = message;
  		}
  
  		public Date getDateSent() {
  			return dateSent;
  		}
  
  		public void setDateSent(Date dateSent) {
  			this.dateSent = dateSent;
  		}
  
  		public String getMessage() {
  			return notification;
  		}
  
  		public void setMessage(String notification) {
  			this.notification = notification;
  		}
  
  		public String getPushNotification() {
  			JSONAPI api = JSONAPI.instance;
  
  			String messager = getMessage();
  			if (api.serverName != null && !api.serverName.isEmpty()) {
  				messager = (api.serverName.equals("default") ? api.getServer().getServerName() : api.serverName) + ": " + messager;
  			}
  
  			return messager.length() > 210 ? messager.substring(0, 208) + "\u2026" : messager;
  		}
  	}
  }
  