package com.vaguehope.onosendai.provider.bufferapp;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import com.vaguehope.onosendai.config.Account;
import com.vaguehope.onosendai.provider.ServiceRef;
import com.vaguehope.onosendai.util.HttpClientFactory;
import com.vaguehope.onosendai.util.LogWrapper;
public class BufferApp {
private static final String BASE_URL = "https://api.bufferapp.com:443";
private static final String API_PROFILES = "/1/profiles.json";
private static final String API_UPDATES_CREATE = "/1/updates/create.json";
static final LogWrapper LOG = new LogWrapper("BF");
private final Account account;
private final HttpClientFactory httpClientFactory;
public BufferApp (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;
}
private HttpClient getHttpClient () throws IOException {
return this.httpClientFactory.getHttpClient();
}
Account getAccount () {
return this.account;
}
private interface BufferCall<T> {
T invoke (HttpClient client) throws BufferAppException, IOException;
String describeFailure (Exception e);
}
private <T> T authenticated (final BufferCall<T> call) throws BufferAppException {
try {
return call.invoke(getHttpClient());
}
catch (final IOException e) {
throw new BufferAppException(call.describeFailure(e), e);
}
}
public void testLogin () throws BufferAppException {
getPostToAccounts();
}
public List<ServiceRef> getPostToAccounts () throws BufferAppException {
return authenticated(new BufferCall<List<ServiceRef>>() {
@Override
public List<ServiceRef> invoke (final HttpClient client) throws BufferAppException, IOException {
return client.execute(new HttpGet(makeAuthedUrl(API_PROFILES)), new ProfilesHandler());
}
@Override
public String describeFailure (final Exception e) {
return "Failed to fetch post to accounts: " + e.toString();
}
});
}
public void post (final Set<ServiceRef> postToSvc, final String body) throws BufferAppException {
authenticated(new BufferCall<Void>() {
@Override
public Void invoke (final HttpClient client) throws BufferAppException, IOException {
attemptPost(postToSvc, body, client);
return null;
}
@Override
public String describeFailure (final Exception e) {
return e.toString();
}
});
}
protected void attemptPost (final Set<ServiceRef> postToSvc, final String body, final HttpClient client) throws IOException {
final HttpPost post = new HttpPost(BASE_URL + API_UPDATES_CREATE);
final List<NameValuePair> params = new ArrayList<NameValuePair>(4);
addAuthParams(params);
params.add(new BasicNameValuePair("text", body));
for (final ServiceRef svc : postToSvc) {
params.add(new BasicNameValuePair("profile_ids[]", svc.getId()));
}
post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
client.execute(post, new CheckStatusOnlyHandler());
}
String makeAuthedUrl (final String api, final String... params) throws IOException {
final StringBuilder u = new StringBuilder().append(BASE_URL).append(api).append("?")
.append("&access_token=").append(URLEncoder.encode(getAccount().getAccessToken(), "UTF-8"));
if (params != null) {
for (final String param : params) {
u.append(param);
}
}
return u.toString();
}
void addAuthParams (final List<NameValuePair> params) {
params.add(new BasicNameValuePair("access_token", getAccount().getAccessToken()));
}
static void checkReponseCode (final StatusLine statusLine) throws IOException {
final int code = statusLine.getStatusCode();
if (code < 200 || code >= 300) { // NOSONAR not a magic number.
throw new IOException("HTTP " + code + ": " + statusLine.getReasonPhrase());
}
}
private static class ProfilesHandler implements ResponseHandler<List<ServiceRef>> {
public ProfilesHandler () {}
@Override
public List<ServiceRef> handleResponse (final HttpResponse response) throws IOException {
checkReponseCode(response.getStatusLine());
try {
final List<ServiceRef> accounts = new ArrayList<ServiceRef>();
final JSONArray arr = (JSONArray) new JSONTokener(EntityUtils.toString(response.getEntity())).nextValue();
for (int i = 0; i < arr.length(); i++) {
final JSONObject prof = arr.getJSONObject(i);
final String id = prof.getString("id");
final String service = prof.getString("service");
final String uid = prof.getString("service_id");
final String username = prof.getString("service_username");
final boolean enabled = prof.getBoolean("default");
accounts.add(new ServiceRef(id, service, uid, username, enabled));
}
return accounts;
}
catch (final JSONException e) {
throw new IOException("Failed to parse response: " + e.toString(), e);
}
}
}
private static class CheckStatusOnlyHandler implements ResponseHandler<Void> {
public CheckStatusOnlyHandler () {}
@Override
public Void handleResponse (final HttpResponse response) throws IOException {
checkReponseCode(response.getStatusLine());
return null;
}
}
}