package me.ccrama.redditslide;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Environment;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import net.dean.jraw.models.CommentSort;
import net.dean.jraw.models.Submission;
import net.dean.jraw.models.meta.SubmissionSerializer;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by carlo_000 on 11/19/2015.
*/
public class OfflineSubreddit {
public static Long currentid = 0L;
private static String savedSubmissionsSubreddit = "";
public long time;
public ArrayList<Submission> submissions;
public String subreddit;
public boolean base;
public static void writeSubmission(JsonNode node, Submission s, Context c) {
writeSubmissionToStorage(s, node, c);
}
static File cacheDirectory;
public static File getCacheDirectory(Context context) {
if (cacheDirectory == null && context != null) {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
&& context.getExternalCacheDir() != null) {
cacheDirectory = context.getExternalCacheDir();
}
cacheDirectory = context.getCacheDir();
}
return cacheDirectory;
}
public OfflineSubreddit overwriteSubmissions(List<Submission> data) {
submissions = new ArrayList<>(data);
return this;
}
public static void writeSubmissionToStorage(Submission s, JsonNode node, Context c) {
File toStore = new File(getCacheDirectory(c) + File.separator + s.getFullName());
try {
FileWriter writer = new FileWriter(toStore);
writer.append(node.toString());
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public boolean isStored(String name, Context c) {
return new File(getCacheDirectory(c) + File.separator + name).exists();
}
public void writeToMemory(Context c) {
if (cache == null) cache = new HashMap<>();
if (subreddit != null) {
String title = subreddit.toLowerCase() + "," + (base ? 0 : time);
String fullNames = "";
cache.put(title, this);
for (Submission sub : new ArrayList<>(submissions)) {
fullNames += sub.getFullName() + ",";
if (!isStored(sub.getFullName(), c)) {
writeSubmissionToStorage(sub, sub.getDataNode(), c);
}
}
if (fullNames.length() > 0) {
Reddit.cachedData.edit()
.putString(title, fullNames.substring(0, fullNames.length() - 1))
.apply();
}
cache.put(title, this);
}
}
public void writeToMemoryNoStorage() {
if (cache == null) cache = new HashMap<>();
if (subreddit != null) {
String title = subreddit.toLowerCase() + "," + (base ? 0 : time);
String fullNames = "";
for (Submission sub : submissions) {
fullNames += sub.getFullName() + ",";
}
if (fullNames.length() > 0) {
Reddit.cachedData.edit()
.putString(title, fullNames.substring(0, fullNames.length() - 1))
.apply();
}
cache.put(title, this);
}
}
public void writeToMemoryAsync(final Context c) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
writeToMemory(c);
return null;
}
}.execute();
}
public void writeToMemory(ArrayList<String> names) {
if (subreddit != null && !names.isEmpty()) {
String title = subreddit.toLowerCase() + "," + (time);
String fullNames = "";
for (String sub : names) {
fullNames += sub + ",";
}
if (subreddit.equals(CommentCacheAsync.SAVED_SUBMISSIONS)) {
Map<String, ?> offlineSubs = Reddit.cachedData.getAll();
for (String offlineSub : offlineSubs.keySet()) {
if (offlineSub.contains(CommentCacheAsync.SAVED_SUBMISSIONS)) {
savedSubmissionsSubreddit = offlineSub;
break;
}
}
String savedSubmissions =
Reddit.cachedData.getString(OfflineSubreddit.savedSubmissionsSubreddit,
fullNames);
Reddit.cachedData.edit().remove(savedSubmissionsSubreddit).apply();
if (!savedSubmissions.equals(fullNames)) {
savedSubmissions = fullNames.concat(savedSubmissions);
}
saveToCache(title, savedSubmissions);
} else {
saveToCache(title, fullNames);
}
}
}
public void deleteFromMemory(String name) {
if (subreddit != null) {
String title = subreddit.toLowerCase() + "," + (time);
if (subreddit.equals(CommentCacheAsync.SAVED_SUBMISSIONS)) {
Map<String, ?> offlineSubs = Reddit.cachedData.getAll();
for (String offlineSub : offlineSubs.keySet()) {
if (offlineSub.contains(CommentCacheAsync.SAVED_SUBMISSIONS)) {
savedSubmissionsSubreddit = offlineSub;
break;
}
}
String savedSubmissions =
Reddit.cachedData.getString(OfflineSubreddit.savedSubmissionsSubreddit,
name);
if (!savedSubmissions.equals(name)) {
Reddit.cachedData.edit().remove(savedSubmissionsSubreddit).apply();
String modifiedSavedSubmissions = savedSubmissions.replace(name + ",", "");
saveToCache(title, modifiedSavedSubmissions);
}
}
}
}
private void saveToCache(String title, String submissions) {
Reddit.cachedData.edit().putString(title, submissions).apply();
}
public static OfflineSubreddit getSubreddit(String subreddit, boolean offline, Context c) {
return getSubreddit(subreddit, 0L, offline, c);
}
public static OfflineSubreddit getSubNoLoad(String s) {
s = s.toLowerCase();
OfflineSubreddit o = new OfflineSubreddit();
o.subreddit = s.toLowerCase();
o.base = true;
o.time = 0;
o.submissions = new ArrayList<>();
return o;
}
private static HashMap<String, OfflineSubreddit> cache;
public static OfflineSubreddit getSubreddit(String subreddit, Long time, boolean offline,
Context c) {
if (cache == null) cache = new HashMap<>();
String title;
if (subreddit != null) {
title = subreddit.toLowerCase() + "," + time;
} else {
title = "";
subreddit = "";
}
if (cache.containsKey(title)) {
return cache.get(title);
} else {
subreddit = subreddit.toLowerCase();
OfflineSubreddit o = new OfflineSubreddit();
o.subreddit = subreddit.toLowerCase();
if (time == 0) {
o.base = true;
}
o.time = time;
String[] split = Reddit.cachedData.getString(subreddit.toLowerCase() + "," + time, "")
.split(",");
if (split.length > 0) {
o.time = time;
o.submissions = new ArrayList<>();
ObjectMapper mapperBase = new ObjectMapper();
ObjectReader reader = mapperBase.reader();
for (String s : split) {
if (!s.contains("_")) s = "t3_" + s;
if (!s.isEmpty()) {
try {
Submission sub = getSubmissionFromStorage(s, c, offline, reader);
if (sub != null) {
o.submissions.add(sub);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
} else {
o.submissions = new ArrayList<>();
}
cache.put(title, o);
return o;
}
}
public static Submission getSubmissionFromStorage(String fullName, Context c, boolean offline,
ObjectReader reader) throws IOException {
String gotten = getStringFromFile(fullName, c);
if (!gotten.isEmpty()) {
if (gotten.startsWith("[") && offline) {
return (SubmissionSerializer.withComments(reader.readTree(gotten),
CommentSort.CONFIDENCE));
} else if (gotten.startsWith("[")) {
JsonNode elem = reader.readTree(gotten);
return (new Submission(elem.get(0).get("data").get("children").get(0).get("data")));
} else {
return (new Submission(reader.readTree(gotten)));
}
}
return null;
}
public static String getStringFromFile(String name, Context c) {
File f = new File(getCacheDirectory(c) + File.separator + name);
if (f.exists()) {
try {
BufferedReader reader = new BufferedReader(new FileReader(f));
char[] chars = new char[(int) f.length()];
reader.read(chars);
reader.close();
return new String(chars);
} catch (IOException e) {
e.printStackTrace();
}
} else {
return "";
}
return "";
}
public static OfflineSubreddit newSubreddit(String subreddit) {
subreddit = subreddit.toLowerCase();
OfflineSubreddit o = new OfflineSubreddit();
o.subreddit = subreddit.toLowerCase();
o.base = false;
o.time = System.currentTimeMillis();
o.submissions = new ArrayList<>();
return o;
}
public void clearPost(Submission s) {
if (submissions != null) {
Submission toRemove = null;
for (Submission s2 : submissions) {
if (s.getFullName().equals(s2.getFullName())) {
toRemove = s2;
}
}
if (toRemove != null) {
submissions.remove(toRemove);
}
}
}
int savedIndex;
Submission savedSubmission;
public void hide(int index) {
hide(index, true);
}
public void hideMulti(int index) {
if (submissions != null) {
submissions.remove(index);
}
}
public void hide(int index, boolean save) {
if (submissions != null) {
savedSubmission = submissions.get(index);
submissions.remove(index);
savedIndex = index;
writeToMemoryNoStorage();
}
}
public void unhideLast() {
if (submissions != null && savedSubmission != null) {
submissions.add(savedIndex, savedSubmission);
writeToMemoryNoStorage();
}
}
public static ArrayList<String> getAll(String subreddit) {
subreddit = subreddit.toLowerCase();
ArrayList<String> base = new ArrayList<>();
for (String s : Reddit.cachedData.getAll().keySet()) {
if (s.startsWith(subreddit) && s.contains(",")) {
base.add(s);
}
}
Collections.sort(base, new MultiComparator());
return base;
}
public static class MultiComparator<T> implements Comparator<T> {
public int compare(T o1, T o2) {
double first = Double.valueOf(((String) o1).split(",")[1]);
double second = Double.valueOf(((String) o2).split(",")[1]);
int comparison = first >= second ? first == second ? 0 : -1 : 1;
if (comparison != 0) return comparison;
return 0;
}
}
public static ArrayList<String> getAll() {
ArrayList<String> keys = new ArrayList<>();
for (String s : Reddit.cachedData.getAll().keySet()) {
if (s.contains(",") && !s.startsWith("multi")) {
keys.add(s);
}
}
return keys;
}
public static ArrayList<String> getAllFormatted() {
ArrayList<String> keys = new ArrayList<>();
for (String s : Reddit.cachedData.getAll().keySet()) {
if (s.contains(",") && !keys.contains(s.substring(0, s.indexOf(","))) && !s.startsWith(
"multi")) {
keys.add(s.substring(0, s.indexOf(",")));
}
}
return keys;
}
}