import java.io.*;
import java.net.*;
import java.util.*;
import java.text.*;

public class SocketManager extends Thread {
	static int count = 0;
	
	Socket s;
	BufferedReader incoming;
	PrintWriter sending;
	int nr = 0;
	
	public SocketManager(Socket s) {
		try {
			this.s = s;
			incoming = new BufferedReader(
					new InputStreamReader(
							s.getInputStream()));
			sending = new PrintWriter(s.getOutputStream(), true);
			
			// Suche nach freien Userklassen
			for (int i = 0; i < 100; i++) {
				if (MultiUserServer.users[i] != null && MultiUserServer.users[i].inactive) {
					nr = i;
					MultiUserServer.users[nr].inactive = false;
				}
			}
			if (nr == 0) {
				if (count >= 99) { // Zu viele User
					sendData(sending, "BKZu viele verbindungen!");
					try {
						Thread.sleep(1000);
					}
					catch (InterruptedException ie) {
						System.out.println(ie);
					}
					s.close();
					return;
				} else { // Weise neue Userklasse zu
					nr = ++count;
					MultiUserServer.users[nr] = new Habbo();
				}
			}
			
			// Pruefe ob die IP des Users gebannt ist
			String hostAdress = s.getInetAddress().getHostAddress();
			if (ipBanned(hostAdress)) {
				String banReason = 
					MultiUserServer.database.dbFirstResult("banReason", "SELECT banReason FROM ipbans WHERE banIP = '" + hostAdress + "'");
				sendData(sending, "@c" + banReason);
				System.out.println("Eine Verbindung wurde abgewiesen, IP-Bann liegt vor.");
				s.close();
				return;
			}
			
			System.out.println("Neue Verbindung akzeptiert!");
			System.out.println("Der neuen Verbindung wurde die Nummer #" + nr + " zugewiesen.");
			sendData(sending, "@@");
		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void run() {
		try {
			while(true) {
				if (!s.isConnected())
					break;
				
				// .. Hier kommen die Packets an
				char[] packetBuffer = new char[1024];
				int bufferSize = incoming.read(packetBuffer);
				String packet = "";
				for (int i = 0; i < bufferSize; i++)
					packet = packet + (char)(int)packetBuffer[i];
				System.out.println("[" + nr + "] << " + packet);
				if (packet == null)
					break;
				if (packet.length() == 0)
					break;
				if (packet == ((char)10 + (char)13 + "")) // Client bricht die Verbindung ab
					break;

				// Laenge des Packets anhand des B64-Headers herausfinden
				int packetLength = MultiUserServer.encoding.b64_encode(packet.substring(1, 2));
				if (packetLength < 0 || packetLength > 1024) // Die Packetlaengenangabe ist ungueltig ..
					break;									 // .. also kann es sich nicht um eine original Clientnachricht handeln!
				
				// Nun bestimmen wir den Packetheader, daran erkennen wir, was der Client ueberhaupt will
				int packetHeader = MultiUserServer.encoding.b64_encode(packet.substring(3, 5));
				packet = packet.substring(5); // Die bereits verarbeitete Information abtrennen

				// Neuen Thread zur Packetverarbeitung erstellen
				new ProcessPacket(this, packet, packetHeader).start();
			}
			s.close();
		}
		catch (IOException e) {
			System.out.println("IO-Error bei Client #" + nr);
		}
		System.out.println("Protokoll beendet fuer Client #" + nr);
		MultiUserServer.users[nr].inactive = true;
	}
	
	public void sendData(PrintWriter out, String data) {
		out.print(data + (char)1);
		out.flush();
		System.out.println("[" + nr + "] >> " + data);
	}
	public void sendData(PrintWriter out, String data, boolean printConsole) {
		out.print(data + (char)1);
		out.flush();
		if (printConsole)
			System.out.println("[" + nr + "] >> " + data);
	}
	public boolean ipBanned(String ip) {
		if (MultiUserServer.database.dbExists(
				"SELECT id " +
				"FROM ipbans " +
				"WHERE banIP = '" + ip + "' " +
				"LIMIT 1"))
			return true;
		return false;
	}
}
