/*
 * Copyright (c) 2016 MCPhoton <http://mcphoton.org> and contributors.
 *
 * This file is part of the Photon Server Implementation <https://github.com/mcphoton/Photon-Server>.
 *
 * The Photon Server Implementation is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * The Photon Server Implementation 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.mcphoton.impl.server;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentSkipListSet;
import org.mcphoton.Photon;
import org.mcphoton.server.WhitelistManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author TheElectronWill
 */
public final class WhitelistManagerImpl implements WhitelistManager {

	private static final Logger log = LoggerFactory.getLogger(WhitelistManagerImpl.class);
	private static final WhitelistManagerImpl INSTANCE = new WhitelistManagerImpl();
	private static final File FILE = new File(Photon.MAIN_DIR, "whitelist.txt");

	public static WhitelistManagerImpl getInstance() {
		return INSTANCE;
	}

	private WhitelistManagerImpl() {
	}

	private final Set<UUID> whitelist = new ConcurrentSkipListSet<>();
	private volatile boolean enabled;

	@Override
	public boolean isEnabled() {
		return enabled;
	}

	@Override
	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}

	@Override
	public void allow(UUID accountId) {
		whitelist.add(accountId);
	}

	@Override
	public void deny(UUID accountId) {
		whitelist.remove(accountId);
	}

	@Override
	public boolean isAllowed(UUID accountId) {
		return whitelist.contains(accountId);
	}

	public void load() throws IOException {
		if (!FILE.exists()) {
			FILE.createNewFile();
			return;
		}
		try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(FILE), StandardCharsets.UTF_8))) {
			String line;
			while ((line = reader.readLine()) != null) {
				try {
					UUID playerId = UUID.fromString(line);
					whitelist.add(playerId);
				} catch (IllegalArgumentException ex) {
					log.error("Invalid UUID in whitelist.", ex);
				}
			}
		}
		log.info("Whitelist loaded.");
	}

	public void save() throws IOException {
		try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(FILE), StandardCharsets.UTF_8))) {
			for (UUID uuid : whitelist) {
				writer.write(uuid.toString());
				writer.newLine();
			}
		}
		log.info("Whitelist saved.");
	}

}

@@ -1156,32 +1156,61 @@
 utStreamWriter;%0A
+import java.net.InetAddress;%0A
 import java.nio.
@@ -1466,19 +1466,16 @@
 y;%0A%0A/**%0A
- *%0A
  * @auth
@@ -1567,17 +1567,16 @@
 nager %7B%0A
-%0A
 %09private
@@ -1798,25 +1798,26 @@
 N_DIR, %22
-whitelist
+accountIds
 .txt%22);%0A
@@ -1925,18 +1925,16 @@
 Impl() %7B
-%0A%09
 %7D%0A%0A%09priv
@@ -1953,25 +1953,103 @@
 t%3CUUID%3E 
-whitelist
+accountIds = new ConcurrentSkipListSet%3C%3E();%0A%09private final Set%3CInetAddress%3E ipAddresses
  = new C
@@ -2282,20 +2282,18 @@
 c void a
-llow
+dd
 (UUID ac
@@ -2305,25 +2305,26 @@
 Id) %7B%0A%09%09
-whitelist
+accountIds
 .add(acc
@@ -2364,12 +2364,87 @@
 oid 
-deny
+add(InetAddress ip) %7B%0A%09%09ipAddresses.add(ip);%0A%09%7D%0A%0A%09@Override%0A%09public void remove
 (UUI
@@ -2460,25 +2460,26 @@
 Id) %7B%0A%09%09
-whitelist
+accountIds
 .remove(
@@ -2517,25 +2517,108 @@
 lic 
-boolean isAllowed
+void remove(InetAddress ip) %7B%0A%09%09ipAddresses.remove(ip);%0A%09%7D%0A%0A%09@Override%0A%09public boolean isInWhitelist
 (UUI
@@ -2641,25 +2641,26 @@
 %09return 
-whitelist
+accountIds
 .contain
@@ -2673,24 +2673,122 @@
 untId);%0A%09%7D%0A%0A
+%09@Override%0A%09public boolean isInWhitelist(InetAddress ip) %7B%0A%09%09return ipAddresses.contains(ip);%0A%09%7D%0A%0A
 %09public void
@@ -2926,24 +2926,29 @@
 feredReader(
+%0A%09%09%09%09
 new InputStr
@@ -3135,25 +3135,26 @@
 );%0A%09%09%09%09%09
-whitelist
+accountIds
 .add(pla
@@ -3237,25 +3237,26 @@
 UUID in 
-whitelist
+accountIds
 .%22, ex);
@@ -3395,24 +3395,29 @@
 feredWriter(
+%0A%09%09%09%09
 new OutputSt
@@ -3507,17 +3507,18 @@
 d : 
-whitelist
+accountIds
 ) %7B%0A
@@ -3622,7 +3622,5 @@
 %0A%09%7D%0A
-%0A%7D%0A
+%7D

Complete WhitelistManagerImpl