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


public class SimpleServer
{
    /** the runners */
    Listener[] m_listener = new Listener[1];

    public SimpleServer(int port1) throws IOException
    {
        m_listener[0] = new Listener(0, port1);
    }

    public void run() throws IOException
    {
        m_listener[0].start();

        System.out.println("servers running... now listening on keyboard");

        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        while(true)
        {
            String line = in.readLine();
            // stupid hack... make sure we hve newlines at the end of the string
            line = line + "\n";

            m_listener[0].push(line);
        }
    }




    class Listener extends Thread
    {
        final int m_id;
        final int m_port;
        ServerSocket m_server = null;
        Socket m_client = null;

        /** flag to determine whether or not to keep running */
        boolean m_sentry = true;

        public Listener(int id, int port) throws IOException
        {
            m_id = id;
            m_port = port;
            m_server = new ServerSocket(m_port);
        }

        /** extended run method which runs the server listen loop
         */
        public void run()
        {
            while(m_sentry)
            {
                m_client = null;
                try
                {
                    m_client = m_server.accept();
                    doconnection();
                }
                catch(SocketException e)
                {
                    // attempting to close a socket blocking in an accept
                    // will cause this exception.  Ignore it.
                    m_sentry = !m_sentry;
                    break;
                }
                catch(IOException e)
                {
                    System.out.println("crap");
                    System.out.println(e);
                    e.printStackTrace();
                }
            }
        }


        /** sets the flag indicating that the thread should stop */
        public void kill()
        {
            try
            {
                m_sentry = false;
                m_server.close();
            }
            catch(IOException e)
            {
                System.out.println("crap");
                System.out.println(e);
                e.printStackTrace();
            }
        }

        /** this gets called when a client connects.
         *  we stay in this method until the client connection closes
         */
        void doconnection() throws IOException
        {
            InputStream is = m_client.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));

            while(m_sentry)
            {
                String message = reader.readLine();
                if (message == null) break;
                System.out.println(message);
                handleEditorMessage(message);
            }
            m_client.close();
        }

        /** this is the hacky function that peeks at what the client sent,
         * and determines if some hacky announcement should be sent to others.
         */
        void handleEditorMessage(String message) throws IOException
        {
            // right now, do nothing
        }

        /** push text down to the client
         */
        void push(String string) throws IOException
        {
            if (m_client == null) return;
            OutputStream os = m_client.getOutputStream();
            os.write(string.getBytes());
            os.flush();
        }
    }

    /**
     */
    public static void main(String[] args)
    {
        if (args.length < 1)
        {
            System.out.println("need arguments:  port");
            return;
        }

        try
        {
            SimpleServer spot = new SimpleServer(Integer.parseInt(args[0]));
            spot.run();
        }
        catch(Exception e)
        {
            System.out.println("oh jeez... exception caught.");
            System.out.println(e);
            e.printStackTrace();
        }
        
    }
}

