package com.zhihu.stp;


import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;


public class StpClient {

    private String host;
    private int port, connectTimeout, timeout;
    private SocketAddress socketAddress;
    private Socket socket = new Socket();
    private BufferedReader reader;
    private BufferedWriter writer;

    public StpClient(String host, int port) {
        this.init(host, port, 1000, 1000);
    }

    public StpClient(String host, int port, int connectTimeout, int timeout) {
        this.init(host, port, connectTimeout, timeout);
    }

    private void init(String host, int port, int connectTimeout, int timeout) {
        this.host = host;
        this.port = port;
        this.connectTimeout = connectTimeout;
        this.timeout = timeout;
        this.socketAddress = new InetSocketAddress(this.host, this.port);

    }

    public void connect() throws IOException {
        this.socket.connect(this.socketAddress, this.connectTimeout);
        this.socket.setSoTimeout(this.timeout);
        this.reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
        this.writer = new BufferedWriter(new OutputStreamWriter(this.socket.getOutputStream()));
    }

    public void close() throws IOException {
        this.reader.close();
        this.writer.close();
        if (!this.socket.isClosed()) {
            this.socket.close();
        }
    }

    public boolean available() {
        return this.socket.isConnected();
    }

    private StpResponse receive() throws IOException {
        StringBuffer buf = new StringBuffer();
        StpResponse stpResponse = new StpResponse();
        while(true) {
            // Receive Length
            while (buf.indexOf("\r\n") == -1) {
                buf.append(this.reader.readLine() + "\r\n");
            }

            if(buf.indexOf("\r\n") == 0) {
                buf.delete(0, "\r\n".length());
                return stpResponse;
            }

            int length = Integer.parseInt(buf.substring(0, buf.indexOf("\r\n")));
            buf = buf.delete(0, buf.indexOf("\r\n") + "\r\n".length());

            while (buf.length() <= length + "\r\n".length()) {
                buf.append(this.reader.readLine() + "\r\n");
            }

            String data = buf.substring(0, length);
            buf = buf.delete(0, length + "\r\n".length());

            stpResponse.append(data);
        }
    }

    public StpResponse call(StpRequest stpRequest) throws IOException {

        if (!this.socket.isConnected()) {
            try {
                this.connect();
            } catch (IOException e) {
                System.err.println("Connect " + e);
            }
        }

        this.writer.write(stpRequest.serialize());
        this.writer.flush();

        return this.receive();
    }

    public static void main(String[] args) {
        StpClient stpClient = new StpClient("localhost", 50001, 10000, 10000);
        StpRequest stpRequest = new StpRequest();
        stpRequest.append("add");
        stpRequest.append("1");
        stpRequest.append("2");
        try {
            StpResponse stpResponse = stpClient.call(stpRequest);
        } catch (IOException e) {

        }
    }
}
@@ -378,16 +378,49 @@
  writer;
+%0A    private String EOL = %22%5Cr%5Cn%22;
 %0A%0A    pu
@@ -1652,18 +1652,19 @@
 StringBu
-ff
+ild
 er buf =
@@ -1676,18 +1676,19 @@
 StringBu
-ff
+ild
 er();%0A  
@@ -1734,24 +1734,86 @@
 Response();%0A
+        char%5B%5D cbuf = new char%5B1500%5D;%0A        int cbufLength;%0A
         whil
@@ -1813,16 +1813,17 @@
    while
+ 
 (true) %7B
@@ -1880,30 +1880,32 @@
 buf.indexOf(
-%22%5Cr%5Cn%22
+this.EOL
 ) == -1) %7B%0A 
@@ -1915,35 +1915,37 @@
             
+c
 buf
-.append(
+Length = 
 this.reader.
@@ -1944,39 +1944,94 @@
 .reader.read
-Line() + %22%5Cr%5Cn%22
+(cbuf, 0, cbuf.length);%0A                buf.append(cbuf, 0, cbufLength
 );%0A         
@@ -2050,16 +2050,17 @@
       if
+ 
 (buf.ind
@@ -2064,22 +2064,24 @@
 indexOf(
-%22%5Cr%5Cn%22
+this.EOL
 ) == 0) 
@@ -2112,22 +2112,24 @@
 lete(0, 
-%22%5Cr%5Cn%22
+this.EOL
 .length(
@@ -2254,22 +2254,24 @@
 indexOf(
-%22%5Cr%5Cn%22
+this.EOL
 )));%0A   
@@ -2315,24 +2315,28 @@
 xOf(
-%22%5Cr%5Cn%22) + %22%5Cr%5Cn%22
+this.EOL) + this.EOL
 .len
@@ -2380,38 +2380,40 @@
 h() %3C= length + 
-%22%5Cr%5Cn%22
+this.EOL
 .length()) %7B%0A   
@@ -2425,27 +2425,29 @@
         
+c
 buf
-.append(
+Length = 
 this.rea
@@ -2458,23 +2458,78 @@
 read
-Line() + %22%5Cr%5Cn%22
+(cbuf, 0, cbuf.length);%0A                buf.append(cbuf, 0, cbufLength
 );%0A 
@@ -2635,22 +2635,24 @@
 ength + 
-%22%5Cr%5Cn%22
+this.EOL
 .length(
@@ -3114,408 +3114,5 @@
  %7D%0A%0A
-    public static void main(String%5B%5D args) %7B%0A        StpClient stpClient = new StpClient(%22localhost%22, 50001, 10000, 10000);%0A        StpRequest stpRequest = new StpRequest();%0A        stpRequest.append(%22add%22);%0A        stpRequest.append(%221%22);%0A        stpRequest.append(%222%22);%0A        try %7B%0A            StpResponse stpResponse = stpClient.call(stpRequest);%0A        %7D catch (IOException e) %7B%0A%0A        %7D%0A    %7D%0A
 %7D

use StringBuilder