package com.integreight.onesheeld.shields.controller.utils;
import android.content.Context;
import android.util.Pair;
import com.integreight.onesheeld.model.InternetRequest;
import com.integreight.onesheeld.shields.controller.InternetShield;
import com.integreight.onesheeld.utils.BitsUtils;
import com.integreight.onesheeld.utils.ConnectionDetector;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.snappydb.DB;
import com.snappydb.DBFactory;
import com.snappydb.SnappydbException;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.Hashtable;
import cz.msebera.android.httpclient.client.params.ClientPNames;
/**
* Created by Saad on 1/26/15.
* <p/>
* SingleTone class for Internet Shield, has most of the logic for internet
*/
public class InternetManager {
private static InternetManager ourInstance;
private AsyncHttpClient httpClient;
private Hashtable<Integer, InternetRequest> requests;
private DB cachDB;
private Context context;
private AsyncHttpResponseHandler uiCallback;
private int maxSentBytes = 64;
private Pair<String, String> basicAuth;
private InternetManager() {
httpClient = new AsyncHttpClient(true, 80, 443);
requests = new Hashtable<>();
basicAuth = null;
}
public static synchronized InternetManager getInstance() {
if (ourInstance == null) {
ourInstance = new InternetManager();
}
return ourInstance;
}
public static InternetManager resetInstance() {
try {
getInstance().close();
} catch (Exception e) {
}
ourInstance = new InternetManager();
return ourInstance;
}
public void init(Context context) throws SnappydbException {
this.context = context;
cachDB = DBFactory.open(context);
}
public void setContext(Context context) {
this.context = context;
}
public void close() throws SnappydbException {
if (httpClient != null)
httpClient.cancelRequests(context, true);
if (requests != null)
requests.clear();
if (cachDB != null && cachDB.isOpen()) {
cachDB.close();
cachDB.destroy();
}
context = null;
}
public void cancelAllRequests() {
if (requests != null && requests.size() > 0) {
Enumeration e = requests.keys();
while (e.hasMoreElements()) {
Integer i = (Integer) e.nextElement();
requests.get(i).setCancelled();
}
}
if (httpClient != null)
httpClient.cancelRequests(context, true);
}
public AsyncHttpClient getHttpClient() {
if (httpClient == null)
httpClient = new AsyncHttpClient(true, 80, 443);
httpClient.getHttpClient().getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
return httpClient;
}
public Hashtable<Integer, InternetRequest> getRequests() {
return requests;
}
public synchronized InternetRequest getRequest(int id) {
InternetRequest request = requests.get(id);
if (request != null)
return request;
else {
return null;
}
}
public synchronized void putRequest(int id, final InternetRequest request) {
requests.put(id, request);
if (uiCallback != null)
uiCallback.onStart();
}
public AsyncHttpResponseHandler getUiCallback() {
return uiCallback;
}
public void setUiCallback(AsyncHttpResponseHandler uiCallback) {
this.uiCallback = uiCallback;
}
public EXECUTION_TYPE execute(int id, REQUEST_TYPE type, byte callbacks) throws UnsupportedEncodingException {
final InternetRequest request = requests.get(id);
if (request == null)
return EXECUTION_TYPE.REQUEST_NOT_FOUND;
if (!ConnectionDetector.isConnectingToInternet(context))
return EXECUTION_TYPE.NO_INTERNET;
if (request.getStatus() == InternetRequest.REQUEST_STATUS.SENT || request.getStatus() == InternetRequest.REQUEST_STATUS.CALLED)
return EXECUTION_TYPE.ALREADY_EXECUTING;
if (request.getUrl() == null || request.getUrl().trim().length() == 0)
return EXECUTION_TYPE.NO_URL;
if (request.getUrl().contains(" "))
return EXECUTION_TYPE.URL_IS_WRONG;
// if (request.getRegisteredCallbacks() == null || request.getRegisteredCallbacks().size() == 0)
// return EXECUTION_TYPE.NO_CALLBACKS;
// registering callback according excution request parameter
if (InternetManager.getInstance().getRequest(id) != null) {
int j = 0;
for (InternetRequest.CALLBACK callback : InternetRequest.CALLBACK.values()) {
if (BitsUtils.isBitSet(callbacks, j))
request.addRegisteredCallbacks(callback);
j++;
}
}
//update request after registering callback
InternetManager.getInstance().putRequest(id, request);
// using given callback for UI updates
final AsyncHttpResponseHandler withUiCallBack = new AsyncHttpResponseHandler() {
@Override
public void onStart() {
if (request.getCallback() != null)
request.getCallback().onStart();
if (getUiCallback() != null)
getUiCallback().onStart();
super.onStart();
}
@Override
public void onFinish() {
if (request.getCallback() != null)
request.getCallback().onFinish();
if (getUiCallback() != null)
getUiCallback().onFinish();
super.onFinish();
}
@Override
public void onFailure(int statusCode, cz.msebera.android.httpclient.Header[] headers, byte[] responseBody, Throwable error) {
if (request.getCallback() != null)
request.getCallback().onFailure(statusCode, headers, responseBody, error);
}
@Override
public void onSuccess(int statusCode, cz.msebera.android.httpclient.Header[] headers, byte[] responseBody) {
if (request.getCallback() != null)
request.getCallback().onSuccess(statusCode, headers, responseBody);
}
};
if (InternetManager.getInstance().getBasicAuth() != null && InternetManager.getInstance().getBasicAuth().first != null && InternetManager.getInstance().getBasicAuth().first.trim().length() > 0)
getHttpClient().setBasicAuth(InternetManager.getInstance().getBasicAuth().first, InternetManager.getInstance().getBasicAuth().second);
switch (type) {
case GET:
getHttpClient().get(context, request.getUrl(), request.getHeaders(), request.getParams(), withUiCallBack);
break;
case POST:
if (request.getEntity() != null)
getHttpClient().post(context, request.getUrl(), request.getHeaders(), new cz.msebera.android.httpclient.entity.StringEntity(request.getEntity()), request.getContentType(), withUiCallBack);
else if (request.getFileEntity() != null) {
try {
getHttpClient().post(context, request.getUrl(), request.getHeaders(), new cz.msebera.android.httpclient.entity.ByteArrayEntity(FileUtils.readFileToByteArray(new File(request.getFileEntity()))), request.getContentType(), withUiCallBack);
} catch (IOException e) {
e.printStackTrace();
}
} else
getHttpClient().post(context, request.getUrl(), request.getHeaders(), request.getParams(), request.getContentType(), withUiCallBack);
break;
case PUT:
if (request.getEntity() != null)
getHttpClient().put(context, request.getUrl(), request.getHeaders(), new cz.msebera.android.httpclient.entity.StringEntity(request.getEntity()), request.getContentType(), withUiCallBack);
else if (request.getFileEntity() != null) {
try {
getHttpClient().post(context, request.getUrl(), request.getHeaders(), new cz.msebera.android.httpclient.entity.ByteArrayEntity(FileUtils.readFileToByteArray(new File(request.getFileEntity()))), request.getContentType(), withUiCallBack);
} catch (IOException e) {
e.printStackTrace();
}
} else
getHttpClient().put(context, request.getUrl(), request.getParams(), withUiCallBack);
break;
case DELETE:
getHttpClient().delete(context, request.getUrl(), request.getHeaders(), request.getParams(), withUiCallBack);
break;
}
getRequest(id).setStatus(InternetRequest.REQUEST_STATUS.CALLED);
return EXECUTION_TYPE.SUCCESSFUL;
}
public DB getCachDB() {
return cachDB;
}
public void disponseResponse(int id) {
try {
cachDB.del(id + "");
} catch (SnappydbException e) {
e.printStackTrace();
}
if (uiCallback != null)
uiCallback.onStart();
}
public int getMaxSentBytes() {
return maxSentBytes;
}
public void setMaxSentBytes(int maxSentBytes) {
this.maxSentBytes = maxSentBytes > 255 ? 255 : maxSentBytes;
}
public Pair<String, String> getBasicAuth() {
return basicAuth;
}
public void setBasicAuth(Pair<String, String> basicAuth) {
if (basicAuth != null && basicAuth.first != null && basicAuth.first.trim().length() > 0 && basicAuth.second != null && basicAuth.second.trim().length() > 0)
this.basicAuth = new Pair<>(basicAuth.first, basicAuth.second);
else
this.basicAuth = null;
}
public void clearBasicAuth() {
this.basicAuth = null;
}
public enum EXECUTION_TYPE {
NO_INTERNET(InternetShield.INTERNET.NOT_CONNECTED_TO_NETWORK), SUCCESSFUL(-1), REQUEST_NOT_FOUND(InternetShield.INTERNET.REQUEST_CAN_NOT_BE_FOUND), ALREADY_EXECUTING(InternetShield.INTERNET.ALREADY_EXECUTING_REQUEST), NO_URL(InternetShield.INTERNET.URL_IS_NOT_FOUND), URL_IS_WRONG(InternetShield.INTERNET.URL_IS_WRONG);
public int value = -1;
private EXECUTION_TYPE(int value) {
this.value = value;
}
}
public enum REQUEST_TYPE {
GET, POST, DELETE, PUT
}
}