package com.samknows.measurement.storage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.json.JSONArray;
import org.json.JSONObject;
import android.util.Log;
import com.samknows.libcore.SKPorting;
import com.samknows.measurement.SK2AppSettings;
import com.samknows.measurement.environment.CellTowersData;
import com.samknows.measurement.environment.DCSData;
import com.samknows.measurement.environment.LocationData;
import com.samknows.measurement.environment.NetworkData;
import com.samknows.measurement.environment.PhoneIdentityData;
import com.samknows.measurement.environment.TrafficData;
import com.samknows.measurement.schedule.condition.ConditionResult;
import com.samknows.measurement.schedule.condition.CpuActivityCondition;
import com.samknows.measurement.schedule.condition.DatacapCondition;
import com.samknows.measurement.schedule.condition.NetActivityCondition;
import com.samknows.tests.ClosestTarget;
import com.samknows.tests.HttpTest;
import com.samknows.tests.JsonData;
import com.samknows.tests.LatencyTest;
public class ExportFile {
//csv file exports
private static final int ZIP_BUFFER_SIZE = 2048;
//public static final String ZIP_FILE = "extract.zip";
public static final String FILE_ENCODING = "UTF-8";
public static final String FIELD_DELIMITER = "\"";
public static final String FIELD_SEPARATOR = ",";
public static final String RECORD_SEPARATOR = "\r\n";
public static final String EMPTY_FIELD = "";
// public static final String TEST_RESULTS_JSON_FILE = "results.json";
// public static final String MAINSECTION_FILENAME = "app_metadata";
// public static final String CSV_FILEEXTENSION = ".csv";
// public static final long FILES_MAX_SIZE = 1024 * 1024;
private static File storage;
//main section data
public static final String[] MAIN_FIELDS = {SK2AppSettings.JSON_UNIT_ID, SK2AppSettings.JSON_APP_VERSION_CODE, SK2AppSettings.JSON_APP_VERSION_NAME, SK2AppSettings.JSON_SCHEDULE_CONFIG_VERSION, SK2AppSettings.JSON_TIMEZONE, SK2AppSettings.JSON_TIMESTAMP, SK2AppSettings.JSON_DATETIME, SK2AppSettings.JSON_ENTERPRISE_ID, SK2AppSettings.JSON_SIMOPERATORCODE};
//tests data
public static final String[] HTTP_FIELDS = {JsonData.JSON_TYPE, JsonData.JSON_TIMESTAMP, JsonData.JSON_DATETIME, JsonData.JSON_TARGET, JsonData.JSON_TARGET_IPADDRESS, JsonData.JSON_SUCCESS,
JsonData.JSON_TRANFERTIME, JsonData.JSON_TRANFERBYTES, JsonData.JSON_BYTES_SEC, JsonData.JSON_WARMUPTIME, JsonData.JSON_WARMUPBYTES, JsonData.JSON_NUMBER_OF_THREADS};
public static final String[] LATENCY_FIELDS = {JsonData.JSON_TYPE, JsonData.JSON_TIMESTAMP, JsonData.JSON_DATETIME, JsonData.JSON_TARGET, JsonData.JSON_TARGET_IPADDRESS, JsonData.JSON_SUCCESS,
LatencyTest.JSON_RTT_AVG, LatencyTest.JSON_RTT_MIN, LatencyTest.JSON_RTT_MAX, LatencyTest.JSON_RTT_STDDEV, LatencyTest.JSON_RECEIVED_PACKETS, LatencyTest.JSON_LOST_PACKETS};
public static final String[] CLOSESTTARGET_FIELDS = {JsonData.JSON_TYPE, JsonData.JSON_TIMESTAMP, JsonData.JSON_DATETIME, JsonData.JSON_SUCCESS, ClosestTarget.JSON_CLOSETTARGET, ClosestTarget.JSON_IPCLOSESTTARGET};
//metrics data
public static final String[] LOCATION_FIELDS = {DCSData.JSON_TYPE, DCSData.JSON_TIMESTAMP, DCSData.JSON_DATETIME, LocationData.JSON_LOCATION_TYPE, LocationData.JSON_LATITUDE, LocationData.JSON_LONGITUDE, LocationData.JSON_ACCURACY};
public static final String[] NETWORKDATA_FIELDS = {DCSData.JSON_TYPE, DCSData.JSON_TIMESTAMP, DCSData.JSON_DATETIME, NetworkData.JSON_TYPE_VALUE, NetworkData.JSON_PHONE_TYPE, NetworkData.JSON_PHONE_TYPE_CODE, NetworkData.JSON_NETWORK_TYPE, NetworkData.JSON_NETWORK_TYPE_CODE, NetworkData.JSON_ACTIVE_NETWORK_TYPE, NetworkData.JSON_ACTIVE_NETWORK_TYPE_CODE, NetworkData.JSON_CONNECTED, NetworkData.JSON_ROAMING, NetworkData.JSON_NETWORK_OPERATOR_CODE, NetworkData.JSON_NETWORK_OPERATOR_NAME, NetworkData.JSON_SIM_OPERATOR_CODE, NetworkData.JSON_SIM_OPERATOR_NAME};
public static final String[] PHONEIDENTITY_FIELDS = {DCSData.JSON_TYPE, DCSData.JSON_TIMESTAMP, DCSData.JSON_DATETIME, PhoneIdentityData.JSON_IMEI, PhoneIdentityData.JSON_IMSI, PhoneIdentityData.JSON_MANUFACTURER, PhoneIdentityData.JSON_MODEL, PhoneIdentityData.JSON_OSTYPE, PhoneIdentityData.JSON_OSVERSION};
public static final String[] TRAFFIC_FIELDS = {DCSData.JSON_TYPE, DCSData.JSON_TIMESTAMP, DCSData.JSON_DATETIME, TrafficData.JSON_MOBILERXBYTES, TrafficData.JSON_MOBILETXBYTES, TrafficData.JSON_TOTALRXBYTES, TrafficData.JSON_TOTALTXBYTES, TrafficData.JSON_APPRXBYTES, TrafficData.JSON_APPTXBYTES, TrafficData.JSON_DURATION};
public static final String[] GSMCELL_FIELDS = {DCSData.JSON_TYPE, DCSData.JSON_TIMESTAMP, DCSData.JSON_DATETIME, CellTowersData.JSON_CELL_TOWER_ID, CellTowersData.JSON_LOCATION_AREA_CODE, CellTowersData.JSON_UMTS_PSC, CellTowersData.JSON_SIGNAL_STRENGTH};
public static final String[] CDMACELL_FIELDS = {DCSData.JSON_TYPE, DCSData.JSON_TIMESTAMP, DCSData.JSON_DATETIME, CellTowersData.JSON_BASE_STATION_ID, CellTowersData.JSON_BASE_STATION_LATITUDE, CellTowersData.JSON_BASE_STATION_LONGITUDE, CellTowersData.JSON_SYSTEM_ID, CellTowersData.JSON_NETWORK_ID, CellTowersData.JSON_DBM, CellTowersData.JSON_ECIO};
public static final String[] NEIGHBOUR_FIELDS = {DCSData.JSON_TYPE, DCSData.JSON_TIMESTAMP, DCSData.JSON_DATETIME, CellTowersData.JSON_NETWORK_TYPE_CODE, CellTowersData.JSON_NETWORK_TYPE, CellTowersData.JSON_RSSI, CellTowersData.JSON_UMTS_PSC, CellTowersData.JSON_CELL_TOWER_ID, CellTowersData.JSON_LOCATION_AREA_CODE};
//condition data
public static final String[] NETACTIVITYCONDITION_FIELDS = {ConditionResult.JSON_TYPE, ConditionResult.JSON_TIMESTAMP, ConditionResult.JSON_DATETIME, ConditionResult.JSON_SUCCESS, NetActivityCondition.JSON_MAXBYTESIN, NetActivityCondition.JSON_MAXBYTESOUT, NetActivityCondition.JSON_BYTESIN, NetActivityCondition.JSON_BYTESOUT};
public static final String[] CPUACTIVITYCONDITION_FIELDS = {ConditionResult.JSON_TYPE, ConditionResult.JSON_TIMESTAMP, ConditionResult.JSON_DATETIME, ConditionResult.JSON_SUCCESS, CpuActivityCondition.JSON_MAX_AVG, CpuActivityCondition.JSON_READ_AVG};
public static final String[] DATACAPCONDITION_FIELDS = {ConditionResult.JSON_TYPE, ConditionResult.JSON_TIMESTAMP, ConditionResult.JSON_DATETIME, ConditionResult.JSON_SUCCESS};
private static final Map<String, String[]> convertor;
static {
Map<String, String[]> aMap = new HashMap<>();
aMap.put(HttpTest.DOWNSTREAMMULTI, HTTP_FIELDS);
aMap.put(HttpTest.DOWNSTREAMSINGLE, HTTP_FIELDS);
aMap.put(HttpTest.UPSTREAMMULTI, HTTP_FIELDS);
aMap.put(HttpTest.UPSTREAMSINGLE, HTTP_FIELDS);
aMap.put(LatencyTest.STRING_ID, LATENCY_FIELDS);
aMap.put(ClosestTarget.TESTSTRING, CLOSESTTARGET_FIELDS);
aMap.put(LocationData.JSON_LOCATION, LOCATION_FIELDS);
aMap.put(NetworkData.JSON_TYPE_VALUE, NETWORKDATA_FIELDS);
aMap.put(PhoneIdentityData.JSON_TYPE_PHONE_IDENTITY, PHONEIDENTITY_FIELDS);
aMap.put(TrafficData.JSON_TYPE_NETUSAGE, TRAFFIC_FIELDS);
aMap.put(CellTowersData.JSON_TYPE_GSM_CELL_LOCATION, GSMCELL_FIELDS);
aMap.put(CellTowersData.JSON_TYPE_CDMA_CELL_LOCATION, CDMACELL_FIELDS);
aMap.put(CellTowersData.JSON_TYPE_CELL_TOWER_NEIGHBOUR, NEIGHBOUR_FIELDS);
aMap.put(NetActivityCondition.TYPE_VALUE, NETACTIVITYCONDITION_FIELDS);
aMap.put(CpuActivityCondition.TYPE_VALUE, CPUACTIVITYCONDITION_FIELDS);
aMap.put(DatacapCondition.JSON_DATACAP, DATACAPCONDITION_FIELDS);
convertor = Collections.unmodifiableMap(aMap);
}
// This storage is PURELY for temporary folders for mail!
// It is NOT the cache folder.
public static void setStorage(File storage) {
ExportFile.storage = storage;
}
// public static File getStorage(){
// return ExportFile.storage;
// }
// The main entry point to save-off results json data.
// This data may be exported subsequently.
public static void saveResults(JSONObject resultToSave) {
// We could use this to purge, if we ran short of space?
//long totalSize = checkFileSize();
//Log.d(ExportFile.class.getName(), "totalSize of json results before = " + totalSize);
appendJSON(resultToSave);
//totalSize = checkFileSize();
//Log.d(ExportFile.class.getName(), "totalSize of json results after = " + totalSize);
// appendToCSVFiles(resultToSave);
}
// We need to do just one things:
// 1. write as new JSON file in new "JSONArchive" sub-folder (TBD)
final static String sJsonArchiveFolderName = "JSONArchive";
private static void appendJSON(JSONObject resultToSave) {
File jsonArchiveFolder = new File(storage, sJsonArchiveFolderName);
if (jsonArchiveFolder.exists() == false) {
boolean bResult = jsonArchiveFolder.mkdir();
if (bResult == false) {
SKPorting.sAssert(ExportFile.class, bResult);
return;
}
if (jsonArchiveFolder.exists() == false) {
SKPorting.sAssert(ExportFile.class, bResult);
return;
}
}
Date now = new Date();
File resultsJSONFile = new File(jsonArchiveFolder, "" + now.getTime() + ".json");
// Try to create the file...
try {
// Note that the file should not already exist(!)
SKPorting.sAssert(ExportFile.class, resultsJSONFile.exists() == false);
boolean bRes = resultsJSONFile.createNewFile();
SKPorting.sAssert(bRes);
} catch (IOException e) {
SKPorting.sAssertE(ExportFile.class, "Failed to create " + resultsJSONFile.getPath() + " to save results.", e);
SKPorting.sAssert(ExportFile.class, false);
return;
}
// Now save the JSON data to the file...
try {
FileOutputStream os = new FileOutputStream(resultsJSONFile, false);
JSONArray results = new JSONArray();
results.put(resultToSave);
String toFile = results.toString();
os.write(toFile.getBytes(FILE_ENCODING));
os.close();
os = null;
} catch (IOException e) {
SKPorting.sAssertE(ExportFile.class, "Unable to save json array to file" + resultsJSONFile.getPath(), e);
}
}
public static File getZipOfAllExportJsonFilesToThisFolderFile(File toThisFolder, String toZipFileName) {
if (zipFilesToThisFolder(toThisFolder, toZipFileName) == false) {
return null;
}
return new File(toThisFolder, toZipFileName);
}
public static File[] getAllFiles() {
File folder = new File(storage, sJsonArchiveFolderName);
File fileArray[] = folder.listFiles();
if (fileArray == null) {
fileArray = new File[0];
return fileArray;
}
Log.d("Files", "Size: " + fileArray.length);
for (File aFileArray : fileArray) {
Log.d("Files", "FileName:" + aFileArray.getName());
}
return fileArray;
}
private static long checkFileSize() {
long totalSize = 0;
File[] files = getAllFiles();
for (File currFile : files) {
totalSize += currFile.length();
}
// if(totalSize > FILES_MAX_SIZE){
// for(File currFile: files){
// currFile.delete();
// }
// }
return totalSize;
}
private static boolean zipFilesToThisFolder(File inStorageFolder, String toZipFileName) {
BufferedInputStream bis = null;
try {
FileOutputStream dest = new FileOutputStream(new File(inStorageFolder, toZipFileName));
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));
byte[] data = new byte[ZIP_BUFFER_SIZE];
for (File currFile : getAllFiles()) {
String currFileName = currFile.getName();
if (!currFile.exists()) continue;
FileInputStream fis = new FileInputStream(currFile);
bis = new BufferedInputStream(fis, ZIP_BUFFER_SIZE);
ZipEntry entry = new ZipEntry(currFileName);
out.putNextEntry(entry);
int count;
while ((count = bis.read(data, 0, ZIP_BUFFER_SIZE)) != -1) {
out.write(data, 0, count);
}
bis.close();
}
out.close();
return true;
} catch (IOException e) {
SKPorting.sAssertE(ExportFile.class, "Error in creating the zip file for the export", e);
return false;
} catch (Exception e) {
SKPorting.sAssertE(ExportFile.class, "Error in creating the zip file for the export", e);
return false;
}
}
}