package ulcrs.data;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import ulcrs.models.course.Course;
import ulcrs.models.shift.Shift;
import ulcrs.models.tutor.Tutor;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.time.LocalDateTime;
import java.util.List;

public class DataStore {

    private List<Tutor> tutors;
    private List<Course> courses;
    private List<Shift> shifts;
    private LocalDateTime timeFetched = LocalDateTime.MIN;

    private static DataStore dataStore;

    public static DataStore getInstance() {
        if (dataStore == null) {
            dataStore = new DataStore();
        }
        return dataStore;
    }


    public static Tutor getTutor(int id) {
    	if (requiresFetch(getInstance().tutors)) {
    		fetch();
    	}
    	
        return getInstance().tutors.stream()
                .filter(tutor -> tutor.getId() == id)
                .findFirst()
                .orElse(null);
    }

    public static Course getCourse(int id) {
        if (requiresFetch(getInstance().courses)) {
        	fetch();
        }
        
        return getInstance().courses.stream()
                .filter(course -> course.getId() == id)
                .findFirst()
                .orElse(null);
    }

    public static Shift getShift(int id) {
        return getInstance().shifts.stream()
                .filter(s -> s.getId() == id)
                .findFirst()
                .orElse(null);
    }

    public static List<Tutor> getTutors() {
        if (requiresFetch(getInstance().tutors)) {
        	fetch();
        }

        return getInstance().tutors;
    }

    public static List<Course> getCourses() {
        if (requiresFetch(getInstance().courses)) {
        	fetch();
        }

        return getInstance().courses;
    }

    private static <T> boolean requiresFetch(T reference) {
        return reference == null;
    }
    
    private static void fetch() {
    	// Fetch from ULC - TODO
    	// For now, just get data from mock data    	
    	
    	// Tutor
        InputStream is = DataStore.class.getClassLoader().getResourceAsStream("mockTutorsFull.json");
        JsonReader reader = new JsonReader(new InputStreamReader(is));
        getInstance().tutors = new Gson().fromJson(reader, new TypeToken<List<Tutor>>() {}.getType());
        
    	// Course
        is = DataStore.class.getClassLoader().getResourceAsStream("mockCoursesFull.json");
        reader = new JsonReader(new InputStreamReader(is));
        getInstance().courses = new Gson().fromJson(reader, new TypeToken<List<Course>>() {}.getType());
    }  
    
}

@@ -761,24 +761,208 @@
 %0A    %7D%0D%0A%0D%0A%0D%0A
+    /**%0D%0A     * Get the tutor of the specified id%0D%0A     * @param id - id of the tutor%0D%0A     * @return Tutor - the Tutor with the specified id, if it exists. Otherwise, null.%0D%0A     */%0D%0A
     public s
@@ -1237,32 +1237,220 @@
 ull);%0D%0A    %7D%0D%0A%0D%0A
+    /**%0D%0A     * Get the course of the specified id%0D%0A     * @param id - id of the course%0D%0A     * @return Course - the Course with the specified id, if it exists. Otherwise, null.%0D%0A     */%0D%0A
     public stati
@@ -1755,56 +1755,323 @@
     
-public static Shift getShift(int id) %7B%0D%0A        
+/**%0D%0A     * Get the shift of the specified id%0D%0A     * @param id - id of the shift%0D%0A     * @return Shift - the shift with the specified id, if it exists. Otherwise, null.%0D%0A     */%0D%0A    public static Shift getShift(int id) %7B%0D%0A    %09if (requiresFetch(getInstance().shifts)) %7B%0D%0A        %09fetch();%0D%0A        %7D%0D%0A    %09%0D%0A    %09
 retu
@@ -2214,32 +2214,155 @@
 ull);%0D%0A    %7D%0D%0A%0D%0A
+    /**%0D%0A     * Get all tutors, fetching from ULC if necessary.%0D%0A     * @return List%3CTutor%3E - list of all tutors%0D%0A     */%0D%0A
     public stati
@@ -2517,24 +2517,150 @@
 ;%0D%0A    %7D%0D%0A%0D%0A
+    /**%0D%0A     * Get all courses, fetching from ULC if necessary.%0D%0A     * @return List%3CCourse%3E - list of all courses%0D%0A     */%0D%0A
     public s
@@ -2820,24 +2820,278 @@
 ses;%0D%0A    %7D%0D
+%0A    %0D%0A    public static List%3CShift%3E getShifts() %7B%0D%0A    %09// TODO implement - requires getting shifts from course, tutor data%0D%0A    %09if (requiresFetch(getInstance().courses)) %7B%0D%0A        %09fetch();%0D%0A        %7D%0D%0A    %09%0D%0A    %09return getInstance().shifts;%0D%0A    %7D%0D
 %0A%0D%0A    priva
@@ -3890,24 +3890,206 @@
 etType());%0D%0A
+        %0D%0A        // TODO using tutors and courses, get all shift information and save into getInstance().shifts%0D%0A        %0D%0A        getInstance().timeFetched = LocalDateTime.now();%0D%0A
     %7D  %0D%0A   

Add comments in DataStore, add initial shift implementations