//haBull.java -- by tsaiwn@csie.nctu.edu.tw
//javac haBull.java
//java haBull
//then you can use "telnet hostName 3388" to connect this program
import java.io.*;
import java.net.*;
import java.util.*;
import java.lang.*;  // NOT necessary
class haBull  {  // should be same as the File name, 建議該用大寫開頭 haBull
    ServerSocket ssk;   //  用來等待連線
    Socket ccc;  // 有client連線進來可生出 Socket 小洞
    int portNumber = 3388;   // Listening TCP port
    PrintStream cout = System.out;    // 取個與 C++ 同名的物件變數
    PrintStream cerr = System.err;
    public static void main(String[ ]  xxx) throws Exception {
                                            // ^^^ 宣稱若出問題會報告馬政府 !
        new haBull( );    // 要求升出 haBull 物件並立刻執行 haBull( ) 建構子
    }
    haBull( ) {  // 這就是 class haBull 的 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.");
       }
  
    } // haBull( )
} // class haBull
////////
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;
    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 PrintStream(
                    (mySock.getOutputStream()), true );
            cout.println("Friend from " + remoteAddr + " at " + now);
        } catch(Exception e) {
          // say something
        }
    }
    public void run() {   // 規定 Thread 內一定要這樣寫才有用
           String s="???";// 接著, 可以 與 連線者對話
        try { 
               out.print("Welcome to the BullCow Land.\n\r"); out.flush( );
               out.print("Give me your 學號與姓名: ");
               s = in.readLine( );
               out.println("歡迎 " + s + " 開始玩, 公牛是位置對數字也對!\n\r");
               cout.println(s + " from " + remoteAddr + " start to play...");
               CowBull cb = new CowBull(in, out);
              /// cb.play( );  // auto play in constructor 
            out.println("\n\rBye bye " + s + "!"); 
            try { mySock.close( ); }catch(Exception e) {  } 
        }catch(Exception e) {  }
        cout.println(s + " leaving ... " + remoteAddr);
    } // run( )
} // class Brother
