package in.sahildave.gazetti.util;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import com.crashlytics.android.Crashlytics;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.*;
import java.util.*;
/**
* Created by sahil on 8/11/14.
*/
public class NewsCatFileUtil {
private static final String NEWS_CAT_FILE = "newsCat.json";
private static final String NEW_DATA_FILE = "newData.json";
private static String LOG_TAG = NewsCatFileUtil.class.getName();
private static NewsCatFileUtil _instance = null;
private Context context;
public Map<String, Object> fullJsonMap;
public Map<String, List<String>> userSelectionMap;
private boolean UserPrefChanged = false;
private NewsCatFileUtil(Context parentContext) {
context = parentContext;
initUserSelectionMap();
}
public static synchronized NewsCatFileUtil getInstance(Context context){
if (_instance == null) {
_instance = new NewsCatFileUtil(context.getApplicationContext());
}
return _instance;
}
public void destroyUtil(){
_instance = null;
fullJsonMap = null;
userSelectionMap = null;
context = null;
}
private void initUserSelectionMap() {
try {
String jsonString = readFromFile(NEWS_CAT_FILE);
Crashlytics.log(Log.INFO, LOG_TAG, "jsonString - "+jsonString);
fullJsonMap = JsonHelper.toMap(new JSONObject(jsonString));
Crashlytics.log(Log.INFO, LOG_TAG, "fullJsonMap - " + fullJsonMap.toString());
userSelectionMap = getUserFeedMapFromJsonMap(fullJsonMap);
Crashlytics.log(Log.INFO, LOG_TAG, "UserSelectionMap - " + userSelectionMap.toString());
} catch (JSONException e) {
Crashlytics.logException(e);
}
}
public boolean isNewsCatSelected(String newspaper, String category){
return isNewsCatSelected(newspaper, category, fullJsonMap);
}
public boolean isNewsCatSelected(String newspaper, String category, Map<String, Object> map){
boolean selected;
if(map.containsKey(newspaper)){
Map <String, Boolean> categories = getAllCategoriesFromJsonMap(newspaper, map);
selected = getValueOfKey(categories, category);
} else {
Crashlytics.log(Log.ERROR, LOG_TAG, "Key: " + newspaper + " not found..returning false");
selected = false;
}
return selected;
}
public Map<String, List<String>> getUserSelectionMap() {
return userSelectionMap;
}
public void setUserSelectionMap(Map<String, List<String>> userSelectionMap) {
this.userSelectionMap = userSelectionMap;
}
public void selectNewsCat(String newspaper, String category, Map<String, Object> map){
if(map.containsKey(newspaper)){
Map <String, Boolean> categories = getAllCategoriesFromJsonMap(newspaper, map);
setValueOfKey(categories, category, true);
} else {
Crashlytics.log(Log.ERROR, LOG_TAG, "Key: " + newspaper + " not found..returning false");
throw new RuntimeException("Key: " + newspaper + " not found");
}
}
public void deselectNewsCat(String newspaper, String category, Map<String, Object> map){
if(map.containsKey(newspaper)){
Map <String, Boolean> categories = getAllCategoriesFromJsonMap(newspaper, map);
setValueOfKey(categories, category, false);
} else {
Crashlytics.log(Log.ERROR, LOG_TAG, "Key: " + newspaper + " not found..returning false");
throw new RuntimeException("Key: " + newspaper + " not found");
}
}
//TODO: make it private
public void saveUserSelectionToJsonFile(Map<String, Object> newFullJsonMap){
try {
fullJsonMap = newFullJsonMap;
Object jsonString = JsonHelper.toJSON(newFullJsonMap);
Crashlytics.log(Log.INFO, LOG_TAG, "Updating fullJson - "+jsonString.toString());
userSelectionMap = getUserFeedMapFromJsonMap(fullJsonMap);
Crashlytics.log(Log.INFO, LOG_TAG, "Updated UserSelectionMap - " + userSelectionMap.toString());
writeToInternalStorage(jsonString.toString(), NEWS_CAT_FILE);
} catch (JSONException e) {
e.printStackTrace();
}
}
private Map<String, Boolean> getAllCategoriesFromJsonMap(String newspaper, Map<String, Object> map) {
return (Map<String, Boolean>) map.get(newspaper);
}
public Map<String, Object> getFullJsonMap(){
return fullJsonMap;
}
private Map<String, List<String>> getUserFeedMapFromJsonMap(Map<String, Object> map){
Map<String, List<String>> returnMap = new HashMap<String, List<String>>();
for (String newspaper : map.keySet()) {
Map<String, Boolean> categories = getAllCategoriesFromJsonMap(newspaper, map);
Iterator<String> catIterator = categories.keySet().iterator();
List<String> selectedCategories = new ArrayList<String>();
while (catIterator.hasNext()) {
String category = catIterator.next();
if (isNewsCatSelected(newspaper, category, map)) {
//Log.d(LOG_TAG, "ADDING - " + newspaper + ", " + category);
selectedCategories.add(category);
}
}
if (selectedCategories.size() > 0) {
returnMap.put(newspaper, selectedCategories);
}
}
//Log.d(LOG_TAG, "USER FEED - "+returnMap);
return returnMap;
}
public void convertUserFeedMapToJsonMap(){
convertUserFeedMapToJsonMap(fullJsonMap);
}
public void convertUserFeedMapToJsonMap(Map<String, Object> map){
for (String newspaper : map.keySet()) {
Map<String, Boolean> allCategories = getAllCategoriesFromJsonMap(newspaper, map);
List<String> selectedCatForNewspaper = userSelectionMap.get(newspaper);
for (String category : allCategories.keySet()) {
if (selectedCatForNewspaper != null && selectedCatForNewspaper.contains(category)) {
selectNewsCat(newspaper, category, map);
} else {
deselectNewsCat(newspaper, category, map);
}
}
}
setUserPrefChanged(true);
saveUserSelectionToJsonFile(map);
}
public boolean isUserPrefChanged() {
return UserPrefChanged;
}
public void setUserPrefChanged(boolean userPrefChanged) {
// Log.d(LOG_TAG, "Setting UserPrefChanged to "+userPrefChanged);
UserPrefChanged = userPrefChanged;
}
private boolean getValueOfKey(Map<String, Boolean> map, String key) {
if (isKeyPresent(map, key)) {
return map.get(key);
} else {
Crashlytics.log(Log.ERROR, LOG_TAG, "Key: " + key + " not found..returning false");
}
return false;
}
private void setValueOfKey(Map<String, Boolean> map, String key, Boolean value){
if (isKeyPresent(map, key)) {
map.put(key, value);
} else {
Crashlytics.log(Log.ERROR, LOG_TAG, "Key: " + key + " not found..returning false");
}
}
private boolean isKeyPresent(Map<String, Boolean> map, String key) {
return map.containsKey(key);
}
public void updateNewsCatFileWithNewAssets() {
try {
String jsonString = readFromFile(NEWS_CAT_FILE, true);
Crashlytics.log(Log.INFO, LOG_TAG, "newJsonString - "+jsonString);
Map<String, Object> newFullJsonMap = JsonHelper.toMap(new JSONObject(jsonString));
Crashlytics.log(Log.INFO, LOG_TAG, "newFullJsonMap - " + newFullJsonMap.toString());
convertUserFeedMapToJsonMap(newFullJsonMap);
Map<String, List<String>> newUserSelectionMap = getUserFeedMapFromJsonMap(newFullJsonMap);
Crashlytics.log(Log.INFO, LOG_TAG, "newUserSelectionMap - "+newUserSelectionMap);
setUserSelectionMap(newUserSelectionMap);
} catch (JSONException e) {
e.printStackTrace();
}
}
public void updateSelectionWithNewAssets(Map<String, Object> map){
Crashlytics.log(Log.INFO, LOG_TAG, "Received map - "+map);
Map<String, List<String>> selected = getUserFeedMapFromJsonMap(map);
Crashlytics.log(Log.INFO, LOG_TAG, "New selected - "+selected);
for (String newspaper : selected.keySet()) {
List<String> categories;
if (userSelectionMap.containsKey(newspaper)) {
categories = userSelectionMap.get(newspaper);
categories.addAll(selected.get(newspaper));
} else {
categories = selected.get(newspaper);
}
userSelectionMap.put(newspaper, categories);
Crashlytics.log(Log.INFO, LOG_TAG, "New selection for "+newspaper+ " is "+categories);
}
Crashlytics.log(Log.INFO, LOG_TAG, "newUserSelectionMap - "+userSelectionMap);
setUserPrefChanged(true);
convertUserFeedMapToJsonMap();
}
public String readFromFile(String fileName){
File file = new File(context.getCacheDir(), fileName);
boolean readFromAsset = !file.exists();
return readFromFile(fileName, readFromAsset);
}
public String readFromFile(String fileName, boolean readFromAsset) {
StringBuilder returnString = new StringBuilder();
InputStreamReader isr = null;
BufferedReader input = null;
FileInputStream fis = null;
InputStream is = null;
try {
File file = new File(context.getCacheDir(), fileName);
if(readFromAsset) {
//Reading from Assets
Crashlytics.log(Log.INFO, LOG_TAG, "Reading from Assets");
is = context.getAssets().open(fileName);
isr = new InputStreamReader(is);
} else {
//Reading from Internal
Crashlytics.log(Log.INFO, LOG_TAG, "Reading from Internal");
fis = new FileInputStream(file);
isr = new InputStreamReader(fis);
}
input = new BufferedReader(isr);
String line;
while ((line = input.readLine()) != null) {
returnString.append(line);
returnString.append("\n");
}
if(readFromAsset){
writeToInternalStorage(returnString.toString(), fileName);
}
} catch (FileNotFoundException e){
Crashlytics.logException(e);
}catch (Exception e) {
Crashlytics.logException(e);
} finally {
try {
if (isr != null)
isr.close();
if (fis != null)
fis.close();
if (is != null)
is.close();
if (input != null)
input.close();
} catch (Exception e2) {
Crashlytics.logException(e2);
}
}
return returnString.toString();
}
private void writeToInternalStorage(final String content, final String fileName){
new AsyncTask<Void, Void, Void>(){
@Override
protected Void doInBackground(Void... params) {
FileOutputStream fos;
try {
File file = new File(context.getCacheDir(), fileName);
fos = new FileOutputStream(file);
fos.write(content.getBytes());
fos.close();
} catch (FileNotFoundException e) {
Crashlytics.logException(e);
} catch (IOException e) {
Crashlytics.logException(e);
} catch (Exception e) {
Crashlytics.logException(e);
}
Crashlytics.log(Log.INFO, LOG_TAG, "File written to internal storage!");
return null;
}
}.execute();
}
}