package com.qiniu.auth;

import android.os.AsyncTask;
import com.qiniu.conf.Conf;
import com.qiniu.utils.ICancel;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

public class Client {

	protected HttpClient mClient;

	public Client(HttpClient client) {
		mClient = client;
	}

	public static ClientExecutor get(String url, CallRet ret) {
		Client client = Client.defaultClient();
		return client.get(client.makeClientExecutor(), url, ret);
	}

	public ClientExecutor call(ClientExecutor client, String url, HttpEntity entity, CallRet ret) {
		Header header = entity.getContentType();
		String contentType = "application/octet-stream";
		if (header != null) {
			contentType = header.getValue();
		}
		return call(client, url, contentType, entity, ret);
	}

	public ClientExecutor call(ClientExecutor client, String url, String contentType, HttpEntity entity, CallRet ret) {
		HttpPost httppost = new HttpPost(url);
		httppost.setEntity(entity);

		if (contentType != null) {
			httppost.setHeader("Content-Type", contentType);
		}
		return execute(client, httppost, ret);
	}

	public ClientExecutor get(ClientExecutor client, String url, CallRet ret) {
		return execute(client, new HttpGet(url), ret);
	}

	public ClientExecutor makeClientExecutor() {
		return new ClientExecutor();
	}

	protected ClientExecutor execute(ClientExecutor client, HttpRequestBase httpRequest, final CallRet ret) {
		client.setup(httpRequest, ret);
		client.execute();
		return client;
	}

	protected HttpResponse roundtrip(HttpRequestBase httpRequest) throws IOException {
		httpRequest.setHeader("User-Agent", Conf.USER_AGENT);
		return mClient.execute(httpRequest);
	}

	public class ClientExecutor extends AsyncTask<Object, Object, Object> implements ICancel {
		HttpRequestBase mHttpRequest;
		CallRet mRet;
		public void setup(HttpRequestBase httpRequest, CallRet ret) {
			mHttpRequest = httpRequest;
			mRet = ret;
		}
		public void upload(long current, long total) {
			publishProgress(current, total);
		}
		
		@Override
		protected Object doInBackground(Object... objects) {
			try {
				HttpResponse resp = roundtrip(mHttpRequest);
				int statusCode = resp.getStatusLine().getStatusCode();
				if (statusCode == 401) { // android 2.3 will not response
					return new Exception("unauthorized!");
				}
				byte[] data = EntityUtils.toByteArray(resp.getEntity());

				if (statusCode / 100 != 2) {
					if (data.length == 0) {
						String xlog = resp.getFirstHeader("X-Log").getValue();
						if (xlog.length() > 0) {
							return new Exception(xlog);
						}
						return new Exception(resp.getStatusLine().getReasonPhrase());
					}
					return new Exception(new String(data));
				}
				return data;
			} catch (IOException e) {
				e.printStackTrace();
				return e;
			}
		}

		@Override
		protected void onProgressUpdate(Object... values) {
			mRet.onProcess((Long) values[0], (Long) values[1]);
		}

		@Override
		protected void onPostExecute(Object o) {
			mClient.getConnectionManager().closeIdleConnections(30, TimeUnit.SECONDS);
			if (o instanceof Exception) {
				mRet.onFailure((Exception) o);
				return;
			}
			mRet.onSuccess((byte[]) o);
		}
	};

	public static Client defaultClient() {
		return new Client(getMultithreadClient());
	}

	public static HttpClient getMultithreadClient() {
		HttpClient client = new DefaultHttpClient();
		ClientConnectionManager mgr = client.getConnectionManager();
		HttpParams params = client.getParams();
		client = new DefaultHttpClient(new ThreadSafeClientConnManager(params, mgr.getSchemeRegistry()), params);
		return client;
	}
}

@@ -3022,115 +3022,228 @@
 %09%09%09%09
-if (statusCode == 401) %7B // android 2.3 will not response%0A%09%09%09%09%09return new Exception(%22unauthorized!%22);%0A%09%09%09%09%7D
+String xl = resp.getFirstHeader(%22X-Log%22).getValue();%0A%0A%09%09%09%09if (statusCode == 401) return new Exception(%22unauthorized!%22); // android 2.3 will not response%0A%09%09%09%09if (xl.contains(%22invalid BlockCtx%22)) return new Exception(xl);%0A
 %0A%09%09%09
@@ -3300,17 +3300,16 @@
 ity());%0A
-%0A
 %09%09%09%09if (
@@ -3329,17 +3329,27 @@
 100 
-!
+=
 = 2) 
-%7B%0A%09
+return data;%0A
 %09%09%09%09
@@ -3368,79 +3368,53 @@
 gth 
-==
+%3E
  0) 
-%7B%0A%09%09%09%09%09%09String xlog = resp.getFirstHeader(%22X-Log%22).getValue(
+return new Exception(new String(data)
 );%0A
-%09%09
 %09%09%09%09
@@ -3419,18 +3419,16 @@
 %09%09if (xl
-og
 .length(
@@ -3438,17 +3438,8 @@
  0) 
-%7B%0A%09%09%09%09%09%09%09
 retu
@@ -3461,23 +3461,11 @@
 n(xl
-og
 );%0A
-%09%09%09%09%09%09%7D%0A%09%09
 %09%09%09%09
@@ -3513,98 +3513,68 @@
 .get
-ReasonPhrase());%0A%09%09%09%09%09%7D%0A%09%09%09%09%09return new Exception(new String(data));%0A%09%09%09%09%7D%0A%09%09%09%09return data
+StatusCode() + %22:%22 + resp.getStatusLine().getReasonPhrase())
 ;%0A%09%09

fix client output info