//hahaID.java -- by tsaiwn@csie.nctu.edu.tw
//javac hahaID.java
//java hahaID
//then you can use "telnet hostName 5678" to connect this program
import java.io.*;
import java.net.*;
import java.util.*;
import java.lang.*;  // NOT necessary
class hahaID  {  // should be same as the File name, 建議該用大寫開頭 hahaID
    ServerSocket ssk;   //  用來等待連線
    Socket ccc;  // 有client連線進來可生出 Socket 小洞
    int portNumber = 5678;   // Listening TCP port
    PrintStream cout = System.out;    // 取個與 C++ 同名的物件變數
    PrintStream cerr = System.err;
    public static void main(String[ ]  xxx) throws Exception {
                                            // ^^^ 宣稱若出問題會報告馬政府 !
        new hahaID( );    // 要求升出 hahaID 物件並立刻執行 hahaID( ) 建構子
    }
    hahaID( ) {  // 這就是 class hahaID 的 constructor 建構子
       cout.println("Server started ... at port "+ portNumber);
       try {
           ssk = new ServerSocket( portNumber );
           while(38 == 38) { // true
               ccc = ssk.accept( );  // 等待連線後取得連線暫稱 ccc
               Brother b = new Brother(ccc); // 請一個小弟, 並把連線交給小弟 
               b.start( );  // 叫小弟開始處理該連線
           }
       } catch(Exception e) {
           cerr.println("Cannot startup ChatServer at port "+ portNumber+"!");
           cerr.println("Maybe port "+portNumber+" has been used?\nByebye.");
       }
  
    } // hahaID( )
} // class hahaID
////////
class Brother extends Thread {   // 表示這 class Brother 是一個 Thread 執行緒 
    Socket mySock;    // 用來記住"老大"傳來的資料, 方便這class內其他 function 用 
    Date now;
    private String myName;
    private String remoteAddr;   // 連著我的對方 IP address
    private BufferedReader in;
    private PrintStream out;    // PrintStream 也可以 
    private PrintStream cout = System.out;   // cout 只是簡寫而已
    Brother(Socket x) { 
        mySock = x; 
        now = new Date( );
        try {
            remoteAddr = mySock.getInetAddress().getHostAddress();
              // 然後取得InputStream並包成 BufferedReader 方便 readLine()
            in = new BufferedReader(
                    new InputStreamReader(mySock.getInputStream()) );
              // 再取得 OutputStream 並包成 PrintWriter
            out =  //new PrintWriter( new OutputStreamWriter
                    new PrintStream(  (mySock.getOutputStream()), true );
            cout.println("Friend from " + remoteAddr + " at " + now);
        } catch(Exception e) {
          // say something
        }
    }
    public void run() {   // 規定 Thread 內一定要這樣寫才有用
           // 接著, 可以 與 連線者對話
        try {
            while(true) {
               new id(in, out);  /////////////////////////////////////<<<<<<<<<
               out.print("Say: "); out.flush( );
               String s = in.readLine( );
               if(s.equals("/quit")) break;
               int k = (int) (5*Math.random( ));
               if(k < 1 ) out.println(" You said " + s);
               else if(k < 3 )out.println(" Really?");
               else out.println("  Ohh .. my God !");
            }
            out.println("Bye!"); 
            try { mySock.close( ); }catch(Exception e) {  } 
        }catch(Exception e) {  }
        cout.println("leaving ... " + remoteAddr);
    } // run( )
} // class Brother
