package com.integreight.onesheeld.model;
import android.os.Parcel;
import android.os.Parcelable;
import com.integreight.onesheeld.sdk.ShieldFrame;
import com.integreight.onesheeld.shields.controller.utils.InternetManager;
import com.integreight.onesheeld.utils.BitsUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Hashtable;
/**
* Created by Saad on 1/26/15.
*/
public class InternetResponse implements Parcelable, Serializable {
private byte[] responseBody;
private int currentBound = 0;
private int statusCode = -1;
private RESPONSE_STATUS status;
private Hashtable<String, String> headers;
private Object jsonResponse;
private RESPONSE_TYPE responseType;
public InternetResponse() {
status = RESPONSE_STATUS.IN_QUEUE;
currentBound = 0;
statusCode = -1;
responseBody = null;
headers = null;
}
public InternetResponse(byte[] responseBody, int statusCode, RESPONSE_STATUS status, cz.msebera.android.httpclient.Header[] headers) {
this();
this.responseBody = responseBody != null ? responseBody : new byte[0];
this.statusCode = statusCode;
this.status = status;
this.setHeaders(headers);
}
public byte[] next() {
return next(InternetManager.getInstance().getMaxSentBytes());
}
public byte[] next(int targetBound) {
if (responseBody == null || status == RESPONSE_STATUS.DONE)
return null;
targetBound = responseBody.length - currentBound >= targetBound ? targetBound : responseBody.length - currentBound;
byte[] response = new byte[targetBound];
for (int i = 0; i < response.length; i++)
response[i] = responseBody[currentBound + i];
currentBound = currentBound + targetBound;
if (currentBound >= responseBody.length)
status = RESPONSE_STATUS.DONE;
return response;
}
public ResponseBodyBytes getBytes(int index, int count) {
ResponseBodyBytes res = new ResponseBodyBytes();
if (index > responseBody.length)
return new ResponseBodyBytes(null, RESPONSE_BODY_BYTES.INDEX_GREATER_THAN_LENGTH);
if (index < 0)
return new ResponseBodyBytes(null, RESPONSE_BODY_BYTES.INDEX_LESS_THAN_0);
if (count <= 0)
return new ResponseBodyBytes(new byte[0], RESPONSE_BODY_BYTES.COUNT_LESS_THAN_0);
count = count > 255 ? 255 : count;
res.setBytes_status(RESPONSE_BODY_BYTES.SUCCESS);
int targetBound = index + count;
if (responseBody.length < targetBound)
res.setBytes_status(RESPONSE_BODY_BYTES.NOT_ENOUGH_BYTES);
targetBound = responseBody.length >= targetBound ? count : responseBody.length - index;
byte[] response = new byte[targetBound];
for (int i = 0; i < response.length; i++)
response[i] = responseBody[index + i];
res.setArray(response);
return res;
}
public ArrayList<JsonNode> getNodes(ShieldFrame frame) {
ArrayList<JsonNode> nodes = new ArrayList<>();
int dataType = frame.getArgumentAsInteger(1);
for (int i = 2; i < frame.getArguments().size(); i++) {
JsonNode node = new JsonNode();
if (BitsUtils.isBitSet(dataType, i - 2)) {
node.setDataType(JsonNode.NODE_DATA_TYPE.OBJECT);
node.setKey(frame.getArgumentAsString(i));
} else {
node.setDataType(JsonNode.NODE_DATA_TYPE.ARRAY);
node.setIndex(frame.getArgumentAsInteger(i));
}
nodes.add(node);
}
return nodes;
}
public String getValueOf(Object object, ArrayList<JsonNode> tree) throws JSONException, ClassCastException {
final JsonNode node = tree.get(0);
if (node != null && object != null) {
if (node.getDataType() == JsonNode.NODE_DATA_TYPE.OBJECT) {
JSONObject jsonObject = (JSONObject) object;
if (tree.size() == 1)
return jsonObject.getString(node.getKey());
else {
tree.remove(0);
return getValueOf(jsonObject.get(node.getKey()), tree);
}
} else if (node.getDataType() == JsonNode.NODE_DATA_TYPE.ARRAY) {
JSONArray jsonArray = (JSONArray) object;
if (tree.size() == 1)
return jsonArray.getString(node.getIndex());
else {
tree.remove(0);
return getValueOf(jsonArray.get(node.getIndex()), tree);
}
}
}
return null;
}
public int getJSONArrayLength(Object object, ArrayList<JsonNode> tree) throws JSONException, ClassCastException {
final JsonNode node = tree.get(0);
if (node.getDataType() == JsonNode.NODE_DATA_TYPE.OBJECT) {
JSONObject jsonObject = (JSONObject) object;
if (tree.size() == 1)
return jsonObject.getJSONArray(node.getKey()).length();
else {
tree.remove(0);
return getJSONArrayLength(jsonObject.get(node.getKey()), tree);
}
} else if (node.getDataType() == JsonNode.NODE_DATA_TYPE.ARRAY)
{
JSONArray jsonArray = (JSONArray) object;
if (tree.size() == 1)
return jsonArray.length();
else {
tree.remove(0);
return getJSONArrayLength(jsonArray.get(node.getIndex()), tree);
}
}
return -1;
}
public byte[] getResponseBody() {
return responseBody == null ? new byte[]{} : responseBody;
}
public void setResponseBody(byte[] responseBody) {
this.responseBody = responseBody != null ? responseBody : new byte[0];
}
public int getCurrentBound() {
return currentBound;
}
public void setCurrentBound(int currentBound) {
this.currentBound = currentBound;
}
public int getStatusCode() {
return statusCode;
}
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
public RESPONSE_STATUS getStatus() {
return status;
}
public void setStatus(RESPONSE_STATUS status) {
this.status = status;
}
public Hashtable<String, String> getHeaders() {
return headers;
}
public void setHeaders(cz.msebera.android.httpclient.Header[] headers1) {
this.headers = new Hashtable<>();
if (headers1 != null) {
for (cz.msebera.android.httpclient.Header header : headers1) {
headers.put(header.getName(), header.getValue());
}
}
}
public RESPONSE_TYPE getResponseType() {
return responseType;
}
public void setResponseType(RESPONSE_TYPE responseType) {
this.responseType = responseType;
}
protected InternetResponse(Parcel in) {
currentBound = in.readInt();
statusCode = in.readInt();
status = (RESPONSE_STATUS) in.readValue(RESPONSE_STATUS.class.getClassLoader());
headers = (Hashtable) in.readValue(Hashtable.class.getClassLoader());
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(currentBound);
dest.writeInt(statusCode);
dest.writeValue(status);
dest.writeValue(headers);
}
@SuppressWarnings("unused")
public static final Parcelable.Creator<InternetResponse> CREATOR = new Parcelable.Creator<InternetResponse>() {
@Override
public InternetResponse createFromParcel(Parcel in) {
return new InternetResponse(in);
}
@Override
public InternetResponse[] newArray(int size) {
return new InternetResponse[size];
}
};
public enum RESPONSE_STATUS implements Serializable {
SUCCESSFUL, FAILURE, IN_QUEUE, DONE;
}
public class ResponseBodyBytes {
private byte[] array;
RESPONSE_BODY_BYTES bytes_status;
public ResponseBodyBytes() {
}
public ResponseBodyBytes(byte[] array, RESPONSE_BODY_BYTES bytes_status) {
this.array = array;
this.bytes_status = bytes_status;
}
public byte[] getArray() {
return array;
}
public void setArray(byte[] array) {
this.array = array;
}
public RESPONSE_BODY_BYTES getBytes_status() {
return bytes_status;
}
public void setBytes_status(RESPONSE_BODY_BYTES bytes_status) {
this.bytes_status = bytes_status;
}
}
public enum RESPONSE_BODY_BYTES {
SUCCESS(-1), NOT_ENOUGH_BYTES(3), INDEX_LESS_THAN_0(0), INDEX_GREATER_THAN_LENGTH(0), COUNT_LESS_THAN_0(4);
public int value = -1;
private RESPONSE_BODY_BYTES(int value) {
this.value = value;
}
}
public enum RESPONSE_TYPE {
HTML, JSON
}
public static class JsonNode {
private NODE_DATA_TYPE nodeDataType;
private String key;
private int index = -1;
public JsonNode(NODE_DATA_TYPE nodeDataType, String key) {
this.nodeDataType = nodeDataType;
this.key = key;
}
public JsonNode(NODE_DATA_TYPE nodeDataType, int index) {
this.nodeDataType = nodeDataType;
this.index = index;
}
public JsonNode() {
}
public NODE_DATA_TYPE getDataType() {
return nodeDataType;
}
public void setDataType(NODE_DATA_TYPE nodeDataType) {
this.nodeDataType = nodeDataType;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public static enum NODE_DATA_TYPE {
OBJECT, ARRAY
}
}
}