package au.com.newint.newinternationalist;
import android.os.AsyncTask;
import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import com.google.gson.stream.MalformedJsonException;
import org.apache.http.HttpResponse;
import org.apache.http.impl.client.BasicCookieStore;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamCorruptedException;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.TimeZone;
/**
* Created by New Internationalist on 9/01/15.
*/
public enum Publisher {
INSTANCE;
final CacheStreamFactory issuesJSONCacheStreamFactory;
ArrayList<Issue> issuesList;
ArrayList <UpdateListener> listeners = new ArrayList <UpdateListener> ();
ArrayList <LoginListener> loginListeners = new ArrayList<>();
ArrayList <SubscriptionListener> subscriptionListeners = new ArrayList<>();
boolean loggedIn;
boolean hasValidSubscription;
BasicCookieStore cookieStore;
Publisher() {
setupCookieStore();
// Get SITE_URL from config variables
String siteURLString = Helpers.getSiteURL();
Helpers.debugLog("SITE_URL", siteURLString);
// Get issues.json and save/update our cache
URL issuesURL = null;
try {
issuesURL = new URL(siteURLString + "issues.json");
} catch (MalformedURLException e) {
e.printStackTrace();
}
File cacheDir = Helpers.getStorageDirectory();
File cacheFile = new File(cacheDir,"issues.json");
issuesJSONCacheStreamFactory = FileCacheStreamFactory.createIfNecessary(cacheFile, new URLCacheStreamFactory(issuesURL));
}
public void setupCookieStore() {
if (cookieStore == null) {
cookieStore = new BasicCookieStore();
}
}
public void deleteCookieStore() {
cookieStore = new BasicCookieStore();
}
public interface UpdateListener {
void onUpdate(Object object);
}
public interface LoginListener {
void onUpdate(Object object);
}
public interface SubscriptionListener {
void onUpdate(Object object);
}
//TODO: shouldn't this be in Issue?
// public interface ArticlesDownloadCompleteListener {
// void onArticlesDownloadComplete(JsonArray articles);
// }
public interface ArticleBodyDownloadCompleteListener {
void onArticleBodyDownloadComplete(ArrayList responseList);
}
public interface IssueZipDownloadCompleteListener {
void onIssueZipDownloadComplete(ArrayList responseList);
}
public void setOnDownloadCompleteListener(UpdateListener listener) {
// Store the listener object
listeners.add(listener);
}
public void removeDownloadCompleteListener(UpdateListener listener) {
// Remove the listener object
listeners.remove(listener);
}
public void removeArticleBodyDownloadCompleteListener(ArticleBodyDownloadCompleteListener listener) {
listeners.remove(listener);
}
public void removeIssueZipDownloadCompleteListener(IssueZipDownloadCompleteListener zipListener) {
listeners.remove(zipListener);
}
public void setLoggedInListener(LoginListener listener) {
// Store the listener object
loginListeners.add(listener);
}
public void setSubscriptionListener(SubscriptionListener listener) {
// Store the listener object
subscriptionListeners.add(listener);
}
// Done using preloadArticles now.. no listeners needed
// static ArrayList <ArticlesDownloadCompleteListener> articleListeners = new ArrayList <ArticlesDownloadCompleteListener> ();
//
// public void setOnArticlesDownloadCompleteListener(ArticlesDownloadCompleteListener listener) {
// // Store the listener object
// articleListeners.add(listener);
// }
ArticleBodyDownloadCompleteListener articleBodyDownloadCompleteListener;
IssueZipDownloadCompleteListener issueZipDownloadCompleteListener;
public void setOnArticleBodyDownloadCompleteListener(ArticleBodyDownloadCompleteListener listener) {
// Store the listener object
articleBodyDownloadCompleteListener = listener;
}
public void setOnIssueZipDownloadCompleteListener(IssueZipDownloadCompleteListener listener) {
// Store the listener object
issueZipDownloadCompleteListener = listener;
}
public int numberOfIssues() {
// Count the number of instances of issue.json
return getIssuesFromFilesystem().size();
}
public ArrayList<Issue> getIssuesFromFilesystem() {
if (issuesList == null) {
File dir = Helpers.getStorageDirectory();
issuesList = buildIssuesFromDir(dir);
Collections.sort(issuesList, new Comparator<Issue>() {
@Override
public int compare(Issue lhs, Issue rhs) {
return rhs.getRelease().compareTo(lhs.getRelease());
}
});
}
return issuesList;
}
public static ArrayList<Issue> buildIssuesFromDir (File dir) {
ArrayList<Issue> issuesArray = new ArrayList<Issue>();
if (dir.exists()) {
File[] files = dir.listFiles();
for (File file : files) {
if (file.isDirectory()) {
issuesArray.addAll(buildIssuesFromDir(file));
} else {
// do something here with the file
if (file.getName().equals("issue.json")) {
// Add to array
try {
issuesArray.add(new Issue(file));
} catch (StreamCorruptedException e) {
e.printStackTrace();
// don't add it
}
}
}
}
}
return issuesArray;
}
public Issue getIssueForId(int id) {
return new Issue(id);
}
public static JsonObject getIssueJsonForId(int id) {
// Return issue.json for id handed in
File issueJson;
File dir = new File(Helpers.getStorageDirectory(), Integer.toString(id));
issueJson = new File(dir,"issue.json");
if (issueJson.exists()) {
// Return parsed issue.json as JsonObject
try {
return parseJsonFile(issueJson);
} catch (StreamCorruptedException e) {
e.printStackTrace();
return null;
}
} else {
// We don't have the issue.json, something went wrong with the initial download. HELP!
// TODO: Download issues.json and re-save to filesystem
return null;
}
}
public void recreateIssueJsonForId(final int id) {
// Recreates a magazine's issue.json file from issues.json
// Updates editor's letter too.
issuesJSONCacheStreamFactory.preload(null, null, new CacheStreamFactory.CachePreloadCallback() {
@Override
public void onLoad(byte[] payload) {
Helpers.debugLog("Recreate issue.json", "onLoad");
}
@Override
public void onLoadBackground(byte[] payload) {
Helpers.debugLog("Recreate issue.json", "onLoadBackground");
JsonArray magazines = null;
if (payload.length > 0) {
JsonElement root = new JsonParser().parse(new String(payload));
//TODO: throws an exception (which one?) if the payload is empty instead of returning null
// IllegalStateException
magazines = root.getAsJsonArray();
}
if (magazines != null) {
for (JsonElement magazine : magazines) {
if (magazine.getAsJsonObject().get("id").getAsInt() == id) {
JsonObject jsonObject = magazine.getAsJsonObject();
// Write issue.json
File dir = new File(Helpers.getStorageDirectory(), Integer.toString(id));
dir.mkdirs();
File file = new File(dir, "issue.json");
try {
Writer w = new FileWriter(file);
new Gson().toJson(jsonObject, w);
w.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
});
}
public Issue latestIssue() {
// assuming this array is sorted
ArrayList<Issue> issuesArray = getIssuesFromFilesystem();
Issue newestIssue = issuesArray.isEmpty()?null:issuesArray.get(0);;
if (newestIssue != null) {
Helpers.debugLog("LatestIssue", String.format("ID: %1$s, Title: %2$s", newestIssue.getID(), newestIssue.getTitle()));
}
return newestIssue;
}
public static JsonObject parseJsonFile(File jsonFile) throws StreamCorruptedException {
JsonElement root = null;
try {
root = new JsonParser().parse(new FileReader((File) jsonFile));
} catch (FileNotFoundException|JsonSyntaxException e) {
e.printStackTrace();
}
if (root == null || root.isJsonNull()) {
jsonFile.delete();
throw new StreamCorruptedException(jsonFile.toString() + " was badly formed json");
}
return root.getAsJsonObject();
}
public static Date parseDateFromString(String inputString) {
Date releaseDate = null;
DateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
inputFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
try {
releaseDate = inputFormat.parse(inputString);
} catch (ParseException e) {
e.printStackTrace();
}
return releaseDate;
}
// DEBUG FUNCTIONS
public boolean deleteDirectory(Issue issue) {
File dir = new File(Helpers.getStorageDirectory().getPath() + "/" + issue.getID());
boolean success = false;
if (dir.isDirectory()) {
String[] children = dir.list();
for (String aChildren : children) {
success = new File(dir, aChildren).delete();
}
}
return success;
}
}