/*
* Copyright (C) 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.apps.santatracker.service;
import android.os.Environment;
import android.util.Log;
import com.google.android.apps.santatracker.data.DestinationDbHelper;
import com.google.android.apps.santatracker.data.SantaPreferences;
import com.google.android.apps.santatracker.data.StreamDbHelper;
import com.google.android.apps.santatracker.data.Switches;
import com.google.android.apps.santatracker.util.SantaLog;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
/**
* ApiProcessor that loads data from a local file (/sdcard/santa.json).
*
* If the <code>now</code> parameter in the file is negative, the current system time is used
* instead.
*
* <b><NOTE: It is best to leave the "refresh" value high (days).
* If the fingerprint is unchanged and the file contains the same locations the next time it is
* read in (and data has not been cleared), the application will fail.
* </b> (The application expects correct behavior, ie. the API will return following locations if
* the fingerprint is unchanged.
*/
public class LocalApiProcessor extends APIProcessor {
private static final String FILENAME = "santa.json";
private static final String TAG = "SantaLocalApiProcessor";
protected final static String FIELD_CLIENT_SPECIFIC = "clientSpecific";
private File mFile;
private JSONObject mClientConfig;
public LocalApiProcessor(SantaPreferences mPreferences, DestinationDbHelper mDBHelper,
StreamDbHelper streamDBHelper, APICallback mCallback) {
super(mPreferences, mDBHelper, streamDBHelper, mCallback);
mFile = new File(Environment.getExternalStorageDirectory(), FILENAME);
Log.d(TAG, "Reading from file: " + mFile.getAbsolutePath());
}
@Override
public JSONObject loadApi(String url) {
SantaLog.d(TAG, "Loading local data.");
// read the santa json file from the SD card
String data = null;
try {
data = loadLocalFile();
} catch (IOException e) {
Log.d(TAG, "Communication Error 101");
return null;
}
if (data == null) {
Log.d(TAG, "Communication Error 102");
return null;
}
SantaLog.d(TAG, "Local File accessed, old data removed.");
// Parse data as JSON
try {
JSONObject result = parseData(data);
mClientConfig = result.getJSONObject(FIELD_CLIENT_SPECIFIC);
return result;
} catch (JSONException e) {
e.printStackTrace();
Log.d(TAG, "Communication Error 103");
}
return null;
}
@Override
protected Switches getSwitches() {
if (mClientConfig == null) {
throw new IllegalStateException("Can't call getSwitches() before successful loadApi()");
}
try {
Switches config = new Switches();
config.disableCastButton = mClientConfig.getBoolean(FIELD_DISABLE_CASTBUTTON);
config.disableDestinationPhoto = mClientConfig.getBoolean(FIELD_DISABLE_PHOTO);
config.gameState.disableGumballGame = mClientConfig.getBoolean(FIELD_DISABLE_GUMBALLGAME);
config.gameState.disableJetpackGame = mClientConfig.getBoolean(FIELD_DISABLE_JETPACKGAME);
config.gameState.disableMemoryGame = mClientConfig.getBoolean(FIELD_DISABLE_MEMORYGAME);
config.gameState.disableRocketGame = mClientConfig.getBoolean(FIELD_DISABLE_ROCKETGAME);
config.gameState.disableDancerGame = mClientConfig.getBoolean(FIELD_DISABLE_DANCERGAME);
config.gameState.disableSnowdownGame = mClientConfig.getBoolean(FIELD_DISABLE_SNOWDOWNGAME);
config.gameState.disableSwimmingGame = mClientConfig.getBoolean(FIELD_DISABLE_SWIMMINGGAME);
config.gameState.disableBmxGame = mClientConfig.getBoolean(FIELD_DISABLE_BMXGAME);
config.gameState.disableRunningGame = mClientConfig.getBoolean(FIELD_DISABLE_RUNNINGGAME);
config.gameState.disableTennisGame = mClientConfig.getBoolean(FIELD_DISABLE_TENNISGAME);
config.gameState.disableWaterpoloGame = mClientConfig.getBoolean(FIELD_DISABLE_WATERPOLOGAME);
config.video1 = mClientConfig.getString(FIELD_VIDEO_1);
config.video15 = mClientConfig.getString(FIELD_VIDEO_15);
config.video23 = mClientConfig.getString(FIELD_VIDEO_23);
return config;
} catch (JSONException e) {
Log.d(TAG, "Communication Error 104");
return null;
}
}
private JSONObject parseData(String data) throws JSONException {
JSONObject json = new JSONObject(data);
// Replace the offset with a hardcoded offset
// Set the current time to now if the now timestamp is negative
if (json.getLong(FIELD_NOW) < 0L) {
json.put(FIELD_NOW, System.currentTimeMillis());
}
// Reset the fingerprint with each request for testing
// json.put(FIELD_FINGERPRINT, Long.toString(System.currentTimeMillis()));
return json;
}
private String loadLocalFile() throws IOException {
if (!mFile.isFile() || !mFile.canRead()) {
// Could not open file for reading
return null;
}
FileInputStream fis = null;
try {
fis = new FileInputStream(mFile);
return read(fis).toString();
} finally {
if (fis != null) {
fis.close();
}
}
}
}