package com.uservoice.uservoicesdk.model;
import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.text.Html;
import com.uservoice.uservoicesdk.Config;
import com.uservoice.uservoicesdk.Session;
import com.uservoice.uservoicesdk.rest.RestMethod;
import com.uservoice.uservoicesdk.rest.RestTask;
import com.uservoice.uservoicesdk.rest.RestTaskCallback;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
public class BaseModel {
protected int id;
public static <T extends BaseModel> T load(SharedPreferences prefs, String prefsKey, String rootKey, Class<T> modelClass) {
try {
JSONObject container = new JSONObject(prefs.getString(prefsKey, "{}"));
return deserializeObject(container, rootKey, modelClass);
} catch (JSONException e) {
return null;
}
}
protected static Session getSession() {
return Session.getInstance();
}
protected static Config getConfig() {
return getSession().getConfig();
}
protected static ClientConfig getClientConfig() {
return getSession().getClientConfig();
}
protected static String apiPath(String path, Object... args) {
return "/api/v1" + String.format(path, args);
}
protected static RestTask doGet(String path, RestTaskCallback callback) {
return doGet(path, null, callback);
}
protected static RestTask doPost(String path, RestTaskCallback callback) {
return doPost(path, null, callback);
}
protected static RestTask doDelete(String path, RestTaskCallback callback) {
return doDelete(path, null, callback);
}
protected static RestTask doPut(String path, RestTaskCallback callback) {
return doPut(path, null, callback);
}
protected static RestTask doGet(String path, Map<String, String> params, RestTaskCallback callback) {
RestTask task = new RestTask(RestMethod.GET, path, params, callback);
task.execute();
return task;
}
protected static RestTask doPost(String path, Map<String, String> params, RestTaskCallback callback) {
RestTask task = new RestTask(RestMethod.POST, path, params, callback);
task.execute();
return task;
}
protected static RestTask doDelete(String path, Map<String, String> params, RestTaskCallback callback) {
RestTask task = new RestTask(RestMethod.DELETE, path, params, callback);
task.execute();
return task;
}
protected static RestTask doPut(String path, Map<String, String> params, RestTaskCallback callback) {
RestTask task = new RestTask(RestMethod.PUT, path, params, callback);
task.execute();
return task;
}
protected static <T extends BaseModel> List<T> deserializeList(JSONObject object, String rootKey, Class<T> modelClass) throws JSONException {
if (!object.has(rootKey))
return null;
try {
JSONArray array = object.getJSONArray(rootKey);
List<T> list = new ArrayList<T>(array.length());
for (int i = 0; i < array.length(); i++) {
T model = modelClass.newInstance();
model.load(array.getJSONObject(i));
list.add(model);
}
return list;
} catch (IllegalArgumentException e) {
throw new JSONException("Reflection failed trying to call load on " + modelClass + " " + e.getMessage());
} catch (IllegalAccessException e) {
throw new JSONException("Reflection failed trying to call load on " + modelClass + " " + e.getMessage());
} catch (InstantiationException e) {
throw new JSONException("Reflection failed trying to instantiate " + modelClass + " " + e.getMessage());
}
}
protected static <T extends BaseModel> T deserializeObject(JSONObject object, String rootKey, Class<T> modelClass) throws JSONException {
if (!object.has(rootKey))
return null;
try {
JSONObject singleObject = object.getJSONObject(rootKey);
T model = modelClass.newInstance();
model.load(singleObject);
return modelClass.cast(model);
} catch (JSONException e) {
throw new JSONException("JSON deserialization failure for " + modelClass + " " + e.getMessage() + " JSON: " + object.toString());
} catch (IllegalArgumentException e) {
throw new JSONException("Reflection failed trying to call load on " + modelClass + " " + e.getMessage());
} catch (IllegalAccessException e) {
throw new JSONException("Reflection failed trying to call load on " + modelClass + " " + e.getMessage());
} catch (InstantiationException e) {
throw new JSONException("Reflection failed trying to instantiate " + modelClass + " " + e.getMessage());
}
}
protected static List<BaseModel> deserializeHeterogenousList(JSONObject object, String rootKey) throws JSONException {
if (!object.has(rootKey))
return null;
JSONArray array = object.getJSONArray(rootKey);
List<BaseModel> list = new ArrayList<BaseModel>(array.length());
for (int i = 0; i < array.length(); i++) {
JSONObject o = array.getJSONObject(i);
String type = o.getString("type");
BaseModel model;
if (type.equals("suggestion"))
model = new Suggestion();
else if (type.equals("article"))
model = new Article();
else
continue;
model.load(o);
list.add(model);
}
return list;
}
public void load(JSONObject object) throws JSONException {
id = object.getInt("id");
}
public int getId() {
return id;
}
public boolean persist(SharedPreferences prefs, String prefsKey, String rootKey) {
JSONObject object = new JSONObject();
JSONObject container = new JSONObject();
try {
save(object);
container.put(rootKey, object);
} catch (JSONException e) {
return false;
}
Editor edit = prefs.edit();
edit.putString(prefsKey, container.toString());
return edit.commit();
}
public void save(JSONObject object) throws JSONException {
object.put("id", id);
}
protected String getString(JSONObject object, String key) throws JSONException {
return object.isNull(key) ? null : Html.fromHtml(object.getString(key)).toString().trim();
}
protected String getHtml(JSONObject object, String key) throws JSONException {
return object.isNull(key) ? null : object.getString(key);
}
@SuppressLint("SimpleDateFormat")
protected Date getDate(JSONObject object, String key) throws JSONException {
String dateString = getString(object, key);
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss Z");
try {
return format.parse(dateString);
} catch (ParseException e1) {
throw new JSONException("Could not parse date: " + dateString);
}
}
}