package de.tum.in.tumcampusapp.managers;
import android.content.Context;
import android.database.Cursor;
import com.google.common.base.Optional;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import de.tum.in.tumcampusapp.auxiliary.NetUtils;
import de.tum.in.tumcampusapp.auxiliary.Utils;
import de.tum.in.tumcampusapp.models.tumcabe.StudyRoom;
import de.tum.in.tumcampusapp.models.tumcabe.StudyRoomGroup;
/**
* Handles content for the study room feature, fetches external data.
*/
public class StudyRoomGroupManager extends AbstractManager {
public static final String STUDYROOM_HOST = "www.devapp.it.tum.de";
public static final String STUDYROOM_URL = "https://" + STUDYROOM_HOST + "/iris/ris_api.php?format=json";
public static final String DATEFORMAT = "yyyy-MM-dd HH:mm:ss";
public StudyRoomGroupManager(Context context) {
super(context);
createStudyRoomGroupTable();
createStudyRoomTable();
}
private final void createStudyRoomGroupTable() {
db.execSQL("CREATE TABLE IF NOT EXISTS study_room_groups " +
"(id INTEGER PRIMARY KEY, name VARCHAR, details VARCHAR)");
}
private final void createStudyRoomTable() {
db.execSQL("CREATE TABLE IF NOT EXISTS study_rooms " +
"(id INTEGER PRIMARY KEY, code VARCHAR, name VARCHAR, location VARCHAR, " +
"occupied_till VARCHAR, " +
"group_id INTEGER)");
}
public void downloadFromExternal() throws JSONException {
Optional<JSONObject> jsonObject = new NetUtils(mContext).downloadJsonObject(STUDYROOM_URL, CacheManager.VALIDITY_DO_NOT_CACHE, true);
if (!jsonObject.isPresent()) {
return;
}
removeCache();
db.beginTransaction();
try {
List<StudyRoomGroup> groups = getAllFromJson(jsonObject.get());
for (StudyRoomGroup group : groups) {
replaceIntoDb(group);
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
new SyncManager(mContext).replaceIntoDb(this);
}
/**
* Replaces/Inserts both study room group and its studyrooms into db.
*
* @param studyRoomGroup the study room group that should be saved/updated.
*/
private void replaceIntoDb(StudyRoomGroup studyRoomGroup) {
db.execSQL("REPLACE INTO study_room_groups(id, name, details) VALUES" +
" (?, ?, ?)",
new String[]{String.valueOf(studyRoomGroup.id), studyRoomGroup.name,
studyRoomGroup.details});
SimpleDateFormat dateFormatter = new SimpleDateFormat(DATEFORMAT, Locale.US);
for (StudyRoom studyRoom : studyRoomGroup.rooms) {
db.execSQL("REPLACE INTO study_rooms(id, code, name, location, occupied_till, " +
"group_id) VALUES " +
"(?, ?, ?, ?, ?, ?)",
new String[]{String.valueOf(studyRoom.id), studyRoom.code, studyRoom.name,
studyRoom.location,
dateFormatter.format(studyRoom.occupiedTill), String.valueOf
(studyRoomGroup.id)});
}
}
public static List<StudyRoomGroup> getAllFromJson(JSONObject jsonObject) throws JSONException {
JSONArray groupsJsonArray = jsonObject.getJSONArray("gruppen");
JSONArray roomsJsonArray = jsonObject.getJSONArray("raeume");
List<StudyRoomGroup> studyRoomGroups = new ArrayList<>();
for (int i = 0; i < groupsJsonArray.length(); i++) {
JSONObject groupJsonObject = groupsJsonArray.getJSONObject(i);
List<StudyRoom> studyRoomList = getStudyRoomsFromJson(groupJsonObject.getJSONArray
("raeume"), roomsJsonArray);
studyRoomGroups.add(new StudyRoomGroup(
groupJsonObject.getInt("nr"),
groupJsonObject.getString("name"),
groupJsonObject.getString("detail"),
studyRoomList
));
}
return studyRoomGroups;
}
private static List<StudyRoom> getStudyRoomsFromJson(JSONArray groupRoomList, JSONArray allRooms)
throws JSONException {
List<StudyRoom> studyRooms = new ArrayList<>();
for (int i = 0; i < allRooms.length(); i++) {
int roomNumber = allRooms.getJSONObject(i).getInt("raum_nr");
for (int j = 0; j < groupRoomList.length(); j++) {
if (groupRoomList.getInt(j) == roomNumber) {
StudyRoom studyRoom;
try {
studyRoom = new StudyRoom(
roomNumber,
allRooms.getJSONObject(i).getString("raum_code"),
allRooms.getJSONObject(i).getString("raum_name"),
allRooms.getJSONObject(i).getString("gebaeude_name"),
new SimpleDateFormat(DATEFORMAT, Locale.US).parse(allRooms
.getJSONObject(i)
.getString("belegung_bis"))
);
} catch (ParseException e) {
//Room is not occupied
studyRoom = new StudyRoom(
roomNumber,
allRooms.getJSONObject(i).getString("raum_code"),
allRooms.getJSONObject(i).getString("raum_name"),
allRooms.getJSONObject(i).getString("gebaeude_name"),
new Date()
);
}
studyRooms.add(studyRoom);
}
}
}
return studyRooms;
}
private void removeCache() {
db.execSQL("DELETE FROM study_room_groups");
db.execSQL("DELETE FROM study_rooms");
}
/**
* Returns all study room groups
*
* @return Database cursor (id, name, details)
*/
public Cursor getAllFromDb() {
return db.query("study_room_groups", null, null, null, null, null, null);
}
/**
* Retrieves all study room groups from a cursor, ordered by name.
*/
public List<StudyRoomGroup> getStudyRoomGroupsFromCursor(Cursor cursor) {
List<StudyRoomGroup> studyRoomGroups = new ArrayList<>();
if (cursor.moveToFirst()) {
do {
studyRoomGroups.add(new StudyRoomGroup(cursor.getInt(0), cursor.getString(1),
cursor.getString(2), getStudyRoomsFromCursor(getStudyRoomsFromDb(cursor
.getInt(0)))));
} while (cursor.moveToNext());
}
Collections.sort(studyRoomGroups);
return studyRoomGroups;
}
/**
* Retrieves all study rooms of a given group from db, ordered by occupation status.
*/
public Cursor getStudyRoomsFromDb(int studyRoomGroupId) {
return db.rawQuery("SELECT id as _id, code, name, location, occupied_till, group_id FROM " +
"study_rooms WHERE group_id = ? ORDER BY occupied_till ASC", new String[]{String
.valueOf(studyRoomGroupId)});
}
private static List<StudyRoom> getStudyRoomsFromCursor(Cursor cursor) {
List<StudyRoom> studyRooms = new ArrayList<>(cursor.getCount());
if (cursor.moveToFirst()) {
do {
studyRooms.add(getStudyRoomFromCursor(cursor));
} while (cursor.moveToNext());
cursor.close();
}
return studyRooms;
}
/**
* Gets a single study room from a cursor, if possible. Note: This won't move the cursor
* forward.
*
* @param cursor the cursor which contains study room information
* @return study room
*/
public static StudyRoom getStudyRoomFromCursor(Cursor cursor) {
StudyRoom studyRoom = null;
try {
studyRoom = new StudyRoom(cursor.getInt(0), cursor.getString(1), cursor.getString
(2), cursor.getString(3), new SimpleDateFormat(DATEFORMAT, Locale.US).parse(cursor
.getString(4)));
} catch (ParseException e) {
Utils.log(e);
}
return studyRoom;
}
}