package com.vaguehope.onosendai.provider.hosaka;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.AbstractHttpMessage;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import android.net.http.AndroidHttpClient;
import android.util.Base64;
import com.vaguehope.onosendai.config.Account;
import com.vaguehope.onosendai.util.HttpClientFactory;
import com.vaguehope.onosendai.util.IoHelper;
import com.vaguehope.onosendai.util.LogWrapper;
/**
* TODO refactor copypasta with Instapaper.
*/
public class Hosaka {
private static final String BASE_URL = "https://hosaka.herokuapp.com:443";
private static final String API_TEST_AUTH = "/me";
private static final String API_COLUMNS = "/me/columns";
static final LogWrapper LOG = new LogWrapper("HS");
private final Account account;
private final HttpClientFactory httpClientFactory;
public Hosaka (final Account account, final HttpClientFactory httpClientFactory) {
if (account == null) throw new IllegalArgumentException("account can not be null.");
if (httpClientFactory == null) throw new IllegalArgumentException("httpClientFactory can not be null.");
this.account = account;
this.httpClientFactory = httpClientFactory;
}
protected Account getAccount () {
return this.account;
}
protected HttpClientFactory getHttpClientFactory () {
return this.httpClientFactory;
}
protected HttpClient getHttpClient () throws IOException {
return this.httpClientFactory.getHttpClient();
}
public void testLogin () throws IOException {
final HttpGet get = new HttpGet(BASE_URL + API_TEST_AUTH);
addAuth(get);
getHttpClient().execute(get, new CheckStatusOnlyHandler());
}
public Map<String, HosakaColumn> sendColumns (final Map<String, HosakaColumn> columns) throws IOException, JSONException {
final HttpPost post = new HttpPost(BASE_URL + API_COLUMNS);
AndroidHttpClient.modifyRequestToAcceptGzipResponse(post);
addAuth(post);
final JSONObject columnsJson = new JSONObject();
for (final Entry<String, HosakaColumn> e : columns.entrySet()) {
columnsJson.put(e.getKey(), e.getValue().toJson());
}
post.setEntity(new StringEntity(columnsJson.toString(), "UTF-8"));
return getHttpClient().execute(post, new HosakaColumnsHandler());
}
private void addAuth (final AbstractHttpMessage req) {
try {
req.setHeader("Authorization", "Basic " + Base64.encodeToString(
(this.account.getAccessToken() + ":" + this.account.getAccessSecret()).getBytes("UTF-8"),
Base64.NO_WRAP));
}
catch (final UnsupportedEncodingException e) {
throw new IllegalStateException(e);
}
}
static void checkReponseCode (final StatusLine statusLine) throws IOException {
final int code = statusLine.getStatusCode();
if (code < 200 || code >= 300) { // NOSONAR not magic numbers.
throw new IOException("HTTP " + code + ": " + statusLine.getReasonPhrase());
}
}
private static class CheckStatusOnlyHandler implements ResponseHandler<Void> {
public CheckStatusOnlyHandler () {}
@Override
public Void handleResponse (final HttpResponse response) throws IOException {
checkReponseCode(response.getStatusLine());
return null;
}
}
private static class HosakaColumnsHandler implements ResponseHandler<Map<String, HosakaColumn>> {
public HosakaColumnsHandler () {}
@Override
public Map<String, HosakaColumn> handleResponse (final HttpResponse response) throws IOException {
checkReponseCode(response.getStatusLine());
try {
final String str = IoHelper.toString(AndroidHttpClient.getUngzippedContent(response.getEntity()));
final JSONObject o = (JSONObject) new JSONTokener(str).nextValue();
final Map<String, HosakaColumn> ret = new HashMap<String, HosakaColumn>();
final Iterator<String> keys = o.keys();
while (keys.hasNext()) {
final String key = keys.next();
ret.put(key, HosakaColumn.parseJson(o.getJSONObject(key)));
}
return ret;
}
catch (final JSONException e) {
throw new IOException(e); // FIXME
}
}
}
}