import java.io.*;
import java.net.*;

/**
 *
 * CSClient
 * <BR><BR>
 * Klient obiektu CommServer.
 *
 * @author  Derek Clayton   derek_clayton@iceinc.com
 * @version 1.0.2
 */

public class CSClient extends Thread {
    private Thread thrThis;         // watek klienta
    private Socket socket;          // gniado polaczenia
    private CommServer server;      // serwer, do ktorego jest podlaczony klient
    private String ip;              // numer IP tego klienta
    protected BufferedReader in;    // przechwytuje przychodzace wiadomosci
    protected PrintWriter out;      // wysyla wyjsciowe wiadomosci

    /**
     * Konstruktor obiektu CSClient.  Inicjalizuje wlasciwosci obiektu CSClient.
     * @param   server    Serwer, do ktorego jest podlaczony klient.
     * @param   socket    Gniazdo, za pomoca ktorego klient jest podlaczony.
    */
    public CSClient(CommServer server, Socket socket) {
        this.server = server;
        this.socket = socket;
        this.ip = socket.getInetAddress().getHostAddress();

        // --- inicjalizuj odbiornik i nadajnij
        try {
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new PrintWriter(socket.getOutputStream(), true);
        } catch(IOException ioe) {
            server.writeActivity("Client IP: " + ip + " could not be "
            + "initialized and has been disconnected.");
            killClient();
        }
    }

    /**
     * Metoda uruchamiajaca watek. Monitoruje przychodzace wiadomosci.
    */
    public void run() {
        try {
            char charBuffer[] = new char[1];

            // --- dopoki odbierany strumien wejsciowy
            while(in.read(charBuffer,0,1) != -1) {

                // --- tworz bufer dla ciagu, ktory przechowa przychodzace dane
                StringBuffer stringBuffer = new StringBuffer(8192);

                // --- dopoki strumien sie nie zakonczy
                while(charBuffer[0] != '\0') {
                    // --- dodaj znaj do bufora
                    stringBuffer.append(charBuffer[0]);
                    in.read(charBuffer, 0 ,1);
                }

                // --- rozezlij wiadomosc
                server.broadcastMessage(stringBuffer.toString());
            }
        } catch(IOException ioe) {
            server.writeActivity("Client IP: " + ip + " caused a read error "
            + ioe + " : " + ioe.getMessage() + "and has been disconnected.");
        } finally {
            killClient();
        }
    }

    /**
     * Odczytuje numer IP klienta.
     * @return   ip    numer IP tego klienta
    */
    public String getIP() {
        return ip;
    }

    /**
     * Przesylanie wiadomosci do tego klienta. Wywolywana przez metode broadcast (rozsylajaca wiadomosci) serwera.
     * @param   message    Wiadomosc przeznaczona do rozeslania.
    */
    public void send(String message) {
        // --- umiesc wiadomosc w buforze
        out.print(message);

        // --- oczysc bufor i sprawdz, czy nie ma bledow
        // --- w razie wystapienia bledu wylacz tego klienta
        if(out.checkError()) {
            server.writeActivity("Client IP: " + ip + " caused a write error "
            + "and has been disconnected.");
            killClient();
        }
    }

    /**
     * Wylaczanie klienta.
    */
    private void killClient() {
        // --- zlec serwerowi usuniecie tego klienta z listy klientow
        server.removeClient(this);

        // --- zamknij otwarte polaczenia i odnosniki
        try {
            in.close();
            out.close();
            socket.close();
            thrThis = null;
        } catch (IOException ioe) {
            server.writeActivity("Client IP: " + ip + " caused an error "
            + "while disconnecting.");
        }
    }
}