package babysteps.model;

import java.util.List;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.stream.Collectors;

public class TaskModel {
    
    /**
     * Top of the task B-tree. All subtasks should be contained within this instance.
     */
    private Task currentTask;
    
    /**
     * Name of the file used for serialization.
     * TODO Let the user manipulate this value through JFileChooser.
     */
    private static final String SAVE_PATH = ".tasksave";
    
    /**
     * Constructor. If a backup exists, load it. Otherwise instantiate new task tree.
     */
    public TaskModel() {
        File saveFile = new File(SAVE_PATH);
        if(saveFile.exists() && !saveFile.isDirectory()) { 
            deseriablize();
        } else {
            currentTask = new Task("Tasks");
        }
    }
    
    /**
     * Provide all of the subtask titles.
     * 
     * @return a List of strings
     */
    public List<String> subtaskNames() {
        return currentTask.getSubtasks().stream()
                .map(Task::getTitle)
                .collect(Collectors.toList());
    }
    
    /**
     * Return the head of the task tree.
     * 
     * @return a Task instance
     */
    public Task getCurrentTask() {
        return currentTask;
    }
    
    /**
     * Add a child to the current task.
     * 
     * @param title
     */
    public void createTask(String title) {
        currentTask.getSubtasks().add(new Task(title, currentTask));
    }
    
    /**
     * Move down the tree to a specific task.
     * 
     * @param taskNumber
     */
    public void enterTask(int taskNumber) {
        currentTask = currentTask.getSubtasks().get(taskNumber);
    }
    
    /**
     * Go to the task above this one in the task tree.
     */
    public void moveUp() {
        currentTask.getParent().ifPresent(t -> currentTask = t);
    }
    
    /**
     * Find the top of the task tree. i.e. discover the most general task.
     * 
     * @return the parent task
     */
    private Task headTask() {
        Task place = currentTask;
        while(place.getParent().isPresent()) {
            place = place.getParent().get();
        }
        return place;
    }
    
    /**
     * Save all tasks (including parents) to a file.
     * 
     * @return true if successful, false otherwise
     */
    public boolean serialize() {
        try {
            FileOutputStream fileOut = new FileOutputStream(SAVE_PATH);
            ObjectOutputStream out = new ObjectOutputStream(fileOut);
            Task head = headTask();
            out.writeObject(head);
            out.close();
            fileOut.close();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }
    
    /**
     * Overwrite the entire model with a new task tree. The previous task tree is not saved.
     * 
     * @return true if successful, false otherwise
     */
    public boolean deseriablize() {
        try {
            FileInputStream fileIn = new FileInputStream(SAVE_PATH);
            ObjectInputStream in = new ObjectInputStream(fileIn);
            currentTask = (Task) in.readObject();
            in.close();
            fileIn.close();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return false;
        }
    }
}

@@ -42,16 +42,45 @@
 l.List;%0A
+import java.util.Observable;%0A
 import j
@@ -314,16 +314,35 @@
 skModel 
+extends Observable 
 %7B%0A    %0A 
@@ -1304,24 +1304,212 @@
    %0A    /**%0A
+     * Find the size of the current task.%0A     * %0A     * @return an integer%0A     */%0A    public int numberOfSubtasks() %7B%0A        return currentTask.getSubtasks().size();%0A    %7D%0A    %0A    /**%0A
      * Retur
@@ -1696,32 +1696,53 @@
 the current task
+ and notify observers
 .%0A     * %0A     *
@@ -1871,24 +1871,714 @@
 rentTask));%0A
+        System.out.println(%22Creating a new task...%22);%0A        setChanged();%0A        notifyObservers();%0A    %7D%0A    %0A    /**%0A     * Modify a subtask and notify observers.%0A     * %0A     * @param taskNumber%0A     * @param newTitle%0A     */%0A    public void retitleTask(int taskNumber, String newTitle) %7B%0A        currentTask.getSubtasks().get(taskNumber).setTitle(newTitle);%0A        setChanged();%0A        notifyObservers();%0A    %7D%0A    %0A    /**%0A     * Remove a subtask from the current task and notify observers.%0A     * %0A     * @param taskNumber%0A     */%0A    public void removeTask(int taskNumber) %7B%0A        currentTask.getSubtasks().remove(taskNumber);%0A        setChanged();%0A        notifyObservers();%0A
     %7D%0A    %0A 
@@ -2624,24 +2624,45 @@
 pecific task
+ and notify observers
 .%0A     * %0A  
@@ -2797,24 +2797,73 @@
 askNumber);%0A
+        setChanged();%0A        notifyObservers();%0A
     %7D%0A    %0A 
@@ -2914,32 +2914,53 @@
 in the task tree
+ and notify observers
 .%0A     */%0A    pu
@@ -3041,24 +3041,73 @@
 tTask = t);%0A
+        setChanged();%0A        notifyObservers();%0A
     %7D%0A    %0A 

Make TaskModel observable