diff --git a/README.md b/README.md
index 8715d4d91..a62e419ac 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,175 @@
-# Duke project template
-
-This is a project template for a greenfield Java project. It's named after the Java mascot _Duke_. Given below are instructions on how to use it.
-
-## Setting up in Intellij
-
-Prerequisites: JDK 11, update Intellij to the most recent version.
-
-1. Open Intellij (if you are not in the welcome screen, click `File` > `Close Project` to close the existing project first)
-1. Open the project into Intellij as follows:
- 1. Click `Open`.
- 1. Select the project directory, and click `OK`.
- 1. If there are any further prompts, accept the defaults.
-1. Configure the project to use **JDK 11** (not other versions) as explained in [here](https://www.jetbrains.com/help/idea/sdk.html#set-up-jdk).
- In the same dialog, set the **Project language level** field to the `SDK default` option.
-3. After that, locate the `src/main/java/Duke.java` file, right-click it, and choose `Run Duke.main()` (if the code editor is showing compile errors, try restarting the IDE). If the setup is correct, you should see something like the below as the output:
- ```
- Hello from
- ____ _
- | _ \ _ _| | _____
- | | | | | | | |/ / _ \
- | |_| | |_| | < __/
- |____/ \__,_|_|\_\___|
- ```
+# SAGE iP project
+
+# User Guide For Sage Task Manager
+─────────────────────────────────────────────────────────────
+─██████████████─██████████████─██████████████─██████████████─
+─██░░░░░░░░░░██─██░░░░░░░░░░██─██░░░░░░░░░░██─██░░░░░░░░░░██─
+─██░░██████████─██░░██████░░██─██░░██████████─██░░██████████─
+─██░░██─────────██░░██──██░░██─██░░██─────────██░░██─────────
+─██░░██████████─██░░██████░░██─██░░██─────────██░░██████████─
+─██░░░░░░░░░░██─██░░░░░░░░░░██─██░░██──██████─██░░░░░░░░░░██─
+─██████████░░██─██░░██████░░██─██░░██──██░░██─██░░██████████─
+─────────██░░██─██░░██──██░░██─██░░██──██░░██─██░░██─────────
+─██████████░░██─██░░██──██░░██─██░░██████░░██─██░░██████████─
+─██░░░░░░░░░░██─██░░██──██░░██─██░░░░░░░░░░██─██░░░░░░░░░░██─
+─██████████████─██████──██████─██████████████─██████████████─
+─────────────────────────────────────────────────────────────
+
+## Features
+
+### Add Task (Todo, Event or Deadline)
+
+This feature allows the user to add a task to the task list. The user can add a task to the application.
+
+### Delete A Task
+
+To delete a task from the application
+
+### List All Tasks
+
+To list all tasks in the application
+
+### Find A Task
+
+To find tasks with a matching query in the task description.
+
+### Mark/Unmark Task
+
+You can mark/unmark a task as done/not done in the application.
+
+### Data Persistence Support
+
+Your previous session data will be automatically stored (in ./data/sage.txt) and restored (If applicable)
+
+## Usage
+
+### `Todo` - Add a Todo Task
+
+Adds a Todo task to the task list.
+
+Example of usage:
+
+`todo buy groceries`
+
+Expected outcome:
+
+```
+Got it. I've added this task:
+[T][ ] buy groceries
+Now you have X tasks in the list.
+```
+
+### `deadline` - Add a Deadline Task
+
+Adds a Deadline task to the task list.
+
+Example of usage:
+
+`deadline submit report /by 2022-03-31`
+
+Expected outcome:
+
+```
+Got it. I've added this task:
+[D][ ] submit report (by: 31 Mar 2022)
+Now you have X tasks in the list.
+```
+
+### `event` - Add an Event Task
+
+Adds an Event task to the task list.
+
+Example of usage:
+
+`event project meeting /from 2022-04-01 /to 2022-04-02`
+
+Expected outcome:
+
+```
+Got it. I've added this task:
+[E][ ] project meeting (from: 2022-04-01 to: 2022-04-02)
+Now you have X tasks in the list.
+```
+
+### `delete` - Delete a Task
+
+Deletes the specified task from the task list.
+
+Example of usage:
+
+`delete 2`
+
+Expected outcome:
+
+```
+Noted. I've removed this task:
+[D][ ] submit report (by: 31 Mar 2022)
+Now you have X tasks in the list.
+```
+
+### `find` - Find Tasks
+
+Displays a list of tasks that match the specified keyword.
+
+Example of usage:
+
+`find meeting`
+
+Expected outcome:
+
+```
+Found 1 matching queries!
+1.[E][ ] project meeting (from: 2022-04-01 to: 2022-04-02)
+```
+
+### `list` - List All Tasks
+
+Displays a list of all tasks in the task list.
+
+Example of usage:
+
+`list`
+
+Expected outcome:
+
+```
+Here are the tasks in your list:
+1.[T][ ] buy groceries
+2.[E][ ] project meeting (from: 2022-04-01 to: 2022-04-02)
+```
+
+### `mark` - Mark a Task as Done
+
+Marks the specified task as done.
+
+Example of usage:
+
+`mark 1`
+
+Expected outcome:
+
+```
+Nice! I've marked this task as done:
+[T][X] buy groceries
+```
+
+### `unmark` - Unmark a Task as Undone
+
+Marks the specified task as undone.
+
+Example of usage:
+
+`unmark 1`
+
+Expected outcome:
+
+```
+Noted. I've marked this task as undone:
+[T][ ] buy groceries
+```
+
+## Other Commands
+
+### `bye` - Quit the application
+
+Exit the application
diff --git a/data/sage.txt b/data/sage.txt
new file mode 100644
index 000000000..fee1a737f
--- /dev/null
+++ b/data/sage.txt
@@ -0,0 +1,4 @@
+[T][ ] read book
+[D][ ] return book (by: June 6th)
+[T][ ] aasdadsada
+[D][X] ajsdkaakd,as (by: wkjsdas)
diff --git a/docs/README.md b/docs/README.md
index 8077118eb..7281790d7 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,29 +1,160 @@
-# User Guide
+# User Guide For Sage Task Manager
-## Features
+## Features
-### Feature-ABC
+### Add Task (Todo, Event or Deadline)
-Description of the feature.
+This feature allows the user to add a task to the task list. The user can add a task to the application.
-### Feature-XYZ
+### Delete A Task
-Description of the feature.
+To delete a task from the application
+
+### List All Tasks
+
+To list all tasks in the application
+
+### Find A Task
+
+To find tasks with a matching query in the task description.
+
+### Mark/Unmark Task
+
+You can mark/unmark a task as done/not done in the application.
+
+### Data Persistence Support
+
+Your previous session data will be automatically stored (in ./data/sage.txt) and restored (If applicable)
## Usage
-### `Keyword` - Describe action
+### `Todo` - Add a Todo Task
-Describe the action and its outcome.
+Adds a Todo task to the task list.
-Example of usage:
+Example of usage:
-`keyword (optional arguments)`
+`todo buy groceries`
Expected outcome:
-Description of the outcome.
+```
+Got it. I've added this task:
+[T][ ] buy groceries
+Now you have X tasks in the list.
+```
+
+### `deadline` - Add a Deadline Task
+
+Adds a Deadline task to the task list.
+
+Example of usage:
+
+`deadline submit report /by 2022-03-31`
+
+Expected outcome:
```
-expected output
+Got it. I've added this task:
+[D][ ] submit report (by: 31 Mar 2022)
+Now you have X tasks in the list.
```
+
+### `event` - Add an Event Task
+
+Adds an Event task to the task list.
+
+Example of usage:
+
+`event project meeting /from 2022-04-01 /to 2022-04-02`
+
+Expected outcome:
+
+```
+Got it. I've added this task:
+[E][ ] project meeting (from: 2022-04-01 to: 2022-04-02)
+Now you have X tasks in the list.
+```
+
+### `delete` - Delete a Task
+
+Deletes the specified task from the task list.
+
+Example of usage:
+
+`delete 2`
+
+Expected outcome:
+
+```
+Noted. I've removed this task:
+[D][ ] submit report (by: 31 Mar 2022)
+Now you have X tasks in the list.
+```
+
+### `find` - Find Tasks
+
+Displays a list of tasks that match the specified keyword.
+
+Example of usage:
+
+`find meeting`
+
+Expected outcome:
+
+```
+Found 1 matching queries!
+1.[E][ ] project meeting (from: 2022-04-01 to: 2022-04-02)
+```
+
+### `list` - List All Tasks
+
+Displays a list of all tasks in the task list.
+
+Example of usage:
+
+`list`
+
+Expected outcome:
+
+```
+Here are the tasks in your list:
+1.[T][ ] buy groceries
+2.[E][ ] project meeting (from: 2022-04-01 to: 2022-04-02)
+```
+
+### `mark` - Mark a Task as Done
+
+Marks the specified task as done.
+
+Example of usage:
+
+`mark 1`
+
+Expected outcome:
+
+```
+Nice! I've marked this task as done:
+[T][X] buy groceries
+```
+
+### `unmark` - Unmark a Task as Undone
+
+Marks the specified task as undone.
+
+Example of usage:
+
+`unmark 1`
+
+Expected outcome:
+
+```
+Noted. I've marked this task as undone:
+[T][ ] buy groceries
+```
+
+## Other Commands
+
+### `bye` - Quit the application
+
+Exit the application
diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java
deleted file mode 100644
index 5d313334c..000000000
--- a/src/main/java/Duke.java
+++ /dev/null
@@ -1,10 +0,0 @@
-public class Duke {
- public static void main(String[] args) {
- String logo = " ____ _ \n"
- + "| _ \\ _ _| | _____ \n"
- + "| | | | | | | |/ / _ \\\n"
- + "| |_| | |_| | < __/\n"
- + "|____/ \\__,_|_|\\_\\___|\n";
- System.out.println("Hello from\n" + logo);
- }
-}
diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..62b526a76
--- /dev/null
+++ b/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: sage.main.Sage
+
diff --git a/src/main/java/sage/enums/TaskType.java b/src/main/java/sage/enums/TaskType.java
new file mode 100644
index 000000000..ed74470a8
--- /dev/null
+++ b/src/main/java/sage/enums/TaskType.java
@@ -0,0 +1,7 @@
+package sage.enums;
+
+public enum TaskType {
+ DEADLINE,
+ TODO,
+ EVENT
+}
diff --git a/src/main/java/sage/exceptions/EmptyListException.java b/src/main/java/sage/exceptions/EmptyListException.java
new file mode 100644
index 000000000..8a2603160
--- /dev/null
+++ b/src/main/java/sage/exceptions/EmptyListException.java
@@ -0,0 +1,11 @@
+package sage.exceptions;
+
+/**
+ * Exception which returns an error message when operations is conducted on an empty list.
+ */
+public class EmptyListException extends Exception {
+
+ public void errorMsg() {
+ System.out.println("There are currently no tasks in your list!");
+ }
+}
diff --git a/src/main/java/sage/exceptions/IllegalOperationException.java b/src/main/java/sage/exceptions/IllegalOperationException.java
new file mode 100644
index 000000000..eb5b02c79
--- /dev/null
+++ b/src/main/java/sage/exceptions/IllegalOperationException.java
@@ -0,0 +1,15 @@
+package sage.exceptions;
+
+/**
+ * Exception which returns an error message when operations is conducted on an empty list.
+ */
+public class IllegalOperationException extends Exception {
+
+ public void errorAlreadyUnmarked() {
+ System.out.println("Task already marked as not completed!");
+ }
+
+ public void errorAlreadyMarked() {
+ System.out.println("Task already marked as completed!");
+ }
+}
diff --git a/src/main/java/sage/exceptions/MissingParameterException.java b/src/main/java/sage/exceptions/MissingParameterException.java
new file mode 100644
index 000000000..b18c32709
--- /dev/null
+++ b/src/main/java/sage/exceptions/MissingParameterException.java
@@ -0,0 +1,32 @@
+package sage.exceptions;
+
+/**
+ * Exception which returns an error message when there are missing parameter(s) in task operations.
+ */
+public class MissingParameterException extends Exception {
+
+ public void missingParamDesc() {
+ System.out.println("Task \"description\" parameter is missing");
+ }
+
+ public void missingParamStart() {
+ System.out.println("Task \"from\" parameter is missing");
+ }
+
+ public void missingParamEnd() {
+ System.out.println("Task \"to\" parameter is missing");
+
+ }
+
+ public void missingParamBy() {
+ System.out.println("Task \"by\" parameter is missing");
+ }
+
+ public void missingParamTaskIndex() {
+ System.out.println("\"index\" parameter is missing");
+ }
+
+ public void missingParamKeyword() {
+ System.out.println("\"Keywords\" parameter is missing");
+ }
+}
diff --git a/src/main/java/sage/exceptions/OutOfBoundException.java b/src/main/java/sage/exceptions/OutOfBoundException.java
new file mode 100644
index 000000000..ab41e14e0
--- /dev/null
+++ b/src/main/java/sage/exceptions/OutOfBoundException.java
@@ -0,0 +1,20 @@
+package sage.exceptions;
+
+/**
+ * Exception which returns an error message when an out-of-bound task index is provided by the user
+ */
+public class OutOfBoundException extends Exception {
+
+ public void errorMark() {
+ System.out.println("Unable to mark the specified task: task index provided is invalid.");
+ }
+
+ public void errorUnmark() {
+ System.out.println("Unable to unmark the specified task: task index provided is invalid.");
+ }
+
+ public void errorDelete() {
+ System.out.println("Unable to delete the specified task: task index provided is invalid.");
+ }
+
+}
diff --git a/src/main/java/sage/main/Sage.java b/src/main/java/sage/main/Sage.java
new file mode 100644
index 000000000..ef7d6b95e
--- /dev/null
+++ b/src/main/java/sage/main/Sage.java
@@ -0,0 +1,21 @@
+package sage.main;
+
+import sage.utility.Display;
+import sage.utility.Parser;
+import sage.utility.Ui;
+
+
+public class Sage {
+ public static void main(String[] args) {
+ Display display = new Display();
+ Ui ui = new Ui();
+ ui.recoverData();
+ boolean isExit = false;
+ display.printWelcomeUser();
+ while (!isExit) {
+ String input = ui.readInput();
+ Parser parsed = new Parser(input);
+ isExit = ui.readCommand(parsed);
+ }
+ }
+}
diff --git a/src/main/java/sage/tasktypes/Deadline.java b/src/main/java/sage/tasktypes/Deadline.java
new file mode 100644
index 000000000..a94788057
--- /dev/null
+++ b/src/main/java/sage/tasktypes/Deadline.java
@@ -0,0 +1,57 @@
+package sage.tasktypes;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+
+
+/**
+ * An inherited class from Task that represents Deadline which also stores the expected completion date of a task
+ */
+
+public class Deadline extends Task {
+ private String byWhen = "";
+
+ private LocalDate date = null;
+
+ public Deadline(String taskName, String byWhen) {
+ super(taskName);
+ DateTimeFormatter dateformat1 = DateTimeFormatter.ofPattern("dd-MM-uuuu");
+ DateTimeFormatter dateformat2 = DateTimeFormatter.ofPattern("uuuu-MM-dd");
+ try {
+ this.date = LocalDate.parse(byWhen, dateformat1);
+ } catch (DateTimeParseException e1) {
+ try {
+ this.date = LocalDate.parse(byWhen, dateformat2);
+ } catch (DateTimeParseException e2) {
+ this.byWhen = byWhen;
+ }
+ }
+ }
+
+ public String getByWhen() {
+ return byWhen;
+ }
+
+ public String getFormattedTime() {
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd MMM yyyy");
+ return this.date.format(formatter);
+ }
+
+ @Override
+ public String toString() {
+ if (this.date != null) {
+ if (super.isCompleted()) {
+ return "[D][X] " + super.getTaskDetails() + "(by: " + getFormattedTime() + ")";
+ } else {
+ return "[D][ ] " + super.getTaskDetails() + "(by: " + getFormattedTime() + ")";
+ }
+ } else {
+ if (super.isCompleted()) {
+ return "[D][X] " + super.getTaskDetails() + "(by: " + getByWhen() + ")";
+ } else {
+ return "[D][ ] " + super.getTaskDetails() + "(by: " + getByWhen() + ")";
+ }
+ }
+ }
+}
diff --git a/src/main/java/sage/tasktypes/Event.java b/src/main/java/sage/tasktypes/Event.java
new file mode 100644
index 000000000..b30dc4f61
--- /dev/null
+++ b/src/main/java/sage/tasktypes/Event.java
@@ -0,0 +1,34 @@
+package sage.tasktypes;
+
+/**
+ * An inherited class from Task that represents Event which also stores the expected starting and ending time of a task
+ */
+
+public class Event extends Task {
+
+ private String startWhen = "";
+ private String endWhen = "";
+
+ public Event(String taskName, String startWhen, String endWhen) {
+ super(taskName);
+ this.startWhen = startWhen;
+ this.endWhen = endWhen;
+ }
+
+ public String getStartWhen() {
+ return startWhen;
+ }
+
+ public String getEndWhen() {
+ return endWhen;
+ }
+
+ @Override
+ public String toString() {
+ if (super.isCompleted()) {
+ return "[E][X] " + super.getTaskDetails() + "(from: " + getStartWhen() + " to: " + getEndWhen() + ")";
+ } else {
+ return "[E][ ] " + super.getTaskDetails() + "(from: " + getStartWhen() + " to: " + getEndWhen() + ")";
+ }
+ }
+}
diff --git a/src/main/java/sage/tasktypes/Task.java b/src/main/java/sage/tasktypes/Task.java
new file mode 100644
index 000000000..95d9a168f
--- /dev/null
+++ b/src/main/java/sage/tasktypes/Task.java
@@ -0,0 +1,40 @@
+package sage.tasktypes;
+
+
+/**
+ * A parent class that represents a task's description and completion status.
+ */
+public class Task {
+ private String taskDetails = "";
+ private boolean isCompleted = false;
+
+ public Task(String taskDetails) {
+ this.taskDetails = taskDetails;
+ this.isCompleted = false;
+ }
+
+ public String getTaskDetails() {
+ return this.taskDetails;
+ }
+
+ public void setCompleted(boolean completed) {
+ this.isCompleted = completed;
+ }
+
+ public boolean isCompleted() {
+ return isCompleted;
+ }
+
+ public char printStatusSymbol() {
+ if (isCompleted) {
+ return 'X';
+ }
+ return ' ';
+ }
+
+ public String toString() {
+ return "";
+ }
+
+ ;
+}
diff --git a/src/main/java/sage/tasktypes/Todo.java b/src/main/java/sage/tasktypes/Todo.java
new file mode 100644
index 000000000..8cd10a385
--- /dev/null
+++ b/src/main/java/sage/tasktypes/Todo.java
@@ -0,0 +1,21 @@
+package sage.tasktypes;
+
+/**
+ * An inherited class from Task that represents Todo.
+ */
+public class Todo extends Task {
+
+ public Todo(String taskName) {
+ super(taskName);
+ }
+
+ @Override
+ public String toString() {
+ if (super.isCompleted()) {
+ return "[T][X] " + super.getTaskDetails();
+ } else {
+ return "[T][ ] " + super.getTaskDetails();
+ }
+ }
+
+}
diff --git a/src/main/java/sage/utility/Display.java b/src/main/java/sage/utility/Display.java
new file mode 100644
index 000000000..5ad377d99
--- /dev/null
+++ b/src/main/java/sage/utility/Display.java
@@ -0,0 +1,105 @@
+package sage.utility;
+
+import java.util.ArrayList;
+
+import sage.tasktypes.Task;
+
+/**
+ * A class containing methods for printing text on the console.
+ */
+
+public class Display {
+ private static final String LINE =
+ "█████╗█████╗█████╗█████╗█████╗█████╗█████╗\n" +
+ "╚════╝╚════╝╚════╝╚════╝╚════╝╚════╝╚════╝";
+ private static final String LOGO = "░██████╗░█████╗░░██████╗░███████╗\n" +
+ "██╔════╝██╔══██╗██╔════╝░██╔════╝\n" +
+ "╚█████╗░███████║██║░░██╗░█████╗░░\n" +
+ "░╚═══██╗██╔══██║██║░░╚██╗██╔══╝░░\n" +
+ "██████╔╝██║░░██║╚██████╔╝███████╗\n" +
+ "╚═════╝░╚═╝░░╚═╝░╚═════╝░╚══════╝";
+
+ public String printLine() {
+ return LINE;
+ }
+
+ public void printWelcomeUser() {
+ String welcome = "Hello! I'm SAGE, the knowledgeable one\n"
+ + "What can I do for you today?\n";
+ System.out.println(LOGO);
+ System.out.println(welcome);
+ }
+
+ public void printGoodByeUser() {
+ System.out.println("Bye. Hope to see you again soon!");
+ }
+
+ public void printResumeSession() {
+ System.out.println("Info: Data from previous session is resumed");
+ }
+
+ /**
+ * This method prints a message to the console indicating the addition of a TODO task to the task list and its details.
+ *
+ * @param taskObj A task object (TODO/DEADLINE/EVENT)
+ * @param taskCount The number of tasks in list.
+ */
+ public void printAddedTask(Task taskObj, int taskCount) {
+ System.out.println(LINE);
+ System.out.println("Got it. I've added this task:");
+ System.out.println(taskObj);
+ System.out.println("Now you have " + taskCount + " tasks in the list");
+ System.out.println(LINE);
+ }
+
+ public void printUnknownInput() {
+ System.out.println("I don't understand what you mean, please try again!");
+ }
+
+
+ /**
+ * This method is used to display a marked/unmark task as not done/done in the task list.
+ *
+ * @param list the list of tasks
+ * @param taskNumber the taskNumber index that is to be unmarked
+ * @param isToMark whether operation executed is to mark a task
+ */
+ public void printMarking(ArrayList list, int taskNumber, boolean isToMark) {
+ Task taskObj = list.get(taskNumber - 1);
+ if (isToMark) {
+ System.out.println("Nice! I've marked this task as done:");
+ } else {
+ System.out.println("OK, I've marked this task as not done yet:");
+ }
+ System.out.println(taskObj);
+ }
+
+ /**
+ * This method is used to display delete operation in the task list.
+ *
+ * @param list the list of tasks
+ * @param taskNumber the taskNumber index of the task that is to be deleted
+ */
+ public void printDeletedTask(ArrayList list, int taskNumber) {
+ Task taskObj = list.get(taskNumber - 1);
+ System.out.println("Noted. I've removed this task:");
+ System.out.println(taskObj);
+ System.out.println("Now you have " + (list.size() - 1) + " tasks in the list.");
+ }
+
+ public void printSearchTask(ArrayList results) {
+ System.out.println(LINE);
+ if (results.isEmpty()) {
+ System.out.println("Found no matching query. Please try another again!");
+ } else {
+ System.out.println("Found " + results.size() + " matching queries!");
+ for (int i = 0; i < results.size(); i++) {
+ System.out.print(i + 1 + ".");
+ System.out.println(results.get(i));
+ }
+
+ }
+ System.out.println(LINE);
+ }
+
+}
diff --git a/src/main/java/sage/utility/Parser.java b/src/main/java/sage/utility/Parser.java
new file mode 100644
index 000000000..eda400645
--- /dev/null
+++ b/src/main/java/sage/utility/Parser.java
@@ -0,0 +1,69 @@
+package sage.utility;
+
+
+/**
+ * A class containing methods for parsing of raw user input for easier reading
+ */
+public class Parser {
+ private String[] rawOutput;
+ private String taskType;
+ private String taskDescription;
+ private String by = null;
+ private String from = null;
+ private String to = null;
+
+ private static final Integer MAXSPLIT = 2;
+ private static final Integer TASKTYPEINDEX = 0;
+ private static final Integer TASKDESCRIPTIONINDEX = 1;
+
+ /**
+ * Parses user input into its respective task type, description and other attributes
+ *
+ * @param input raw user input to be parsed
+ */
+ public Parser(String input) {
+ this.rawOutput = input.split("/");
+ String[] body = rawOutput[TASKTYPEINDEX].split(" ", MAXSPLIT);
+ this.taskType = body[TASKTYPEINDEX].toLowerCase();
+ if (body.length > 1) {
+ this.taskDescription = body[TASKDESCRIPTIONINDEX];
+ }
+
+ for (String i : rawOutput) {
+ String[] line = i.split(" ", MAXSPLIT);
+ String field = line.length > 1 ? line[TASKDESCRIPTIONINDEX].trim() : null;
+ switch (line[TASKTYPEINDEX]) {
+ case "by":
+ this.by = field;
+ break;
+ case "from":
+ this.from = field;
+ break;
+ case "to":
+ this.to = field;
+ break;
+ }
+ }
+
+ }
+
+ public String getTaskType() {
+ return taskType;
+ }
+
+ public String getTaskDescription() {
+ return taskDescription;
+ }
+
+ public String getBy() {
+ return by;
+ }
+
+ public String getFrom() {
+ return from;
+ }
+
+ public String getTo() {
+ return to;
+ }
+}
diff --git a/src/main/java/sage/utility/Storage.java b/src/main/java/sage/utility/Storage.java
new file mode 100644
index 000000000..0229bf078
--- /dev/null
+++ b/src/main/java/sage/utility/Storage.java
@@ -0,0 +1,106 @@
+package sage.utility;
+
+import sage.tasktypes.Task;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Scanner;
+
+
+/**
+ * A class that contains storage and file related I/O methods
+ */
+public class Storage {
+
+ private static final String PROJECT_FILE_DIR = "./data/sage.txt";
+ private static final Integer TASKTYPEINDEX = 1;
+ private static final Integer TASKCOMPLETIONINDEX = 4;
+ private static final Integer TASKFROMLENGTH = 6;
+ private static final Integer TASKTOLENGTH = 4;
+
+ private static final Integer TASKBYLENGTH = 2;
+
+ private static final Integer TASKDESCENTRYINDEX = 7;
+
+ /**
+ * Recovers and parse any stored data in ./data/sage.txt to taskList
+ *
+ * @param taskList contains information and methods about all the tasks currently in the list
+ */
+ public void recoverData(TaskList taskList) {
+ File f = new File(PROJECT_FILE_DIR);
+ if (f.exists()) {
+ Display UI = new Display();
+ UI.printResumeSession();
+ try {
+ Scanner scanner = new Scanner(f);
+ while (scanner.hasNextLine()) {
+ String line = scanner.nextLine();
+ writeToApp(line, taskList);
+ }
+ scanner.close();
+ } catch (FileNotFoundException e) {
+ System.out.println("An error occurred when trying to read/access the data file");
+ }
+ }
+ }
+
+ /**
+ * Writes a given line recovered from previous session data to the application
+ *
+ * @param line contains information about a recovered task from the previous session
+ * @param taskList contains information and methods about all the tasks currently in the list
+ */
+ public void writeToApp(String line, TaskList taskList) {
+ char taskType = line.charAt(TASKTYPEINDEX);
+ String taskDescription = "";
+ boolean isCompleted = false;
+ char s = line.charAt(TASKCOMPLETIONINDEX);
+
+ if (s == 'X') {
+ isCompleted = true;
+ }
+ if (taskType == 'T') {
+ taskDescription = line.substring(TASKDESCENTRYINDEX);
+ taskList.addTask(taskDescription, isCompleted, true);
+ } else {
+ String taskPeriod = line.substring(line.indexOf('(') + 1, line.indexOf(')'));
+ taskDescription = line.substring(7, line.indexOf('(') - 1) + " ";
+ if (taskType == 'D') {
+ String taskBy = taskPeriod.substring(taskPeriod.indexOf(':') + TASKBYLENGTH);
+ taskList.addTask(taskDescription, taskBy, isCompleted, true);
+ } else {
+ String taskFrom = taskPeriod.substring(taskPeriod.indexOf("from: ") + TASKFROMLENGTH,
+ taskPeriod.indexOf("to: ") - 1);
+ String taskTo = taskPeriod.substring(taskPeriod.indexOf("to: ") + TASKTOLENGTH);
+ taskList.addTask(taskDescription, taskFrom, taskTo, isCompleted, true);
+ }
+ }
+ }
+
+ /**
+ * Updates the data file in ./data/sage.txt with the latest list of tasks
+ *
+ * @param list list of tasks information in the application
+ */
+
+ public void updateFile(ArrayList list) {
+ File f = new File(PROJECT_FILE_DIR);
+ try {
+ f.getParentFile().mkdirs();
+ if (!f.exists()) {
+ f.createNewFile();
+ }
+ FileWriter fw = new FileWriter(PROJECT_FILE_DIR);
+ for (Task taskobj : list) {
+ fw.write(taskobj + " \r\n");
+ }
+ fw.close();
+ } catch (IOException e) {
+ System.out.println("Info: Error Updating Changes to Data File, Please refresh App!");
+ }
+ }
+}
diff --git a/src/main/java/sage/utility/TaskList.java b/src/main/java/sage/utility/TaskList.java
new file mode 100644
index 000000000..91bc13494
--- /dev/null
+++ b/src/main/java/sage/utility/TaskList.java
@@ -0,0 +1,214 @@
+package sage.utility;
+
+import java.util.ArrayList;
+
+import sage.exceptions.IllegalOperationException;
+import sage.exceptions.MissingParameterException;
+import sage.exceptions.EmptyListException;
+import sage.exceptions.OutOfBoundException;
+import sage.tasktypes.Deadline;
+import sage.tasktypes.Event;
+import sage.tasktypes.Task;
+import sage.tasktypes.Todo;
+
+/**
+ * A class that stores the list of tasks in the application and access methods for all task operations
+ */
+
+public class TaskList {
+ private static ArrayList list = new ArrayList<>();
+
+ private static final Display display = new Display();
+ private static final Storage fm = new Storage();
+
+ /**
+ * Display a list of tasks with its description matching the search query (keywords) provided by the user.
+ *
+ * @param keywords the search term input provided by the user
+ */
+ public void findTask(String keywords) {
+ ArrayList results = new ArrayList();
+ try {
+ if (keywords == null) {
+ throw new MissingParameterException();
+ }
+ for (Task t : list) {
+ if (t.getTaskDetails().contains(keywords)) {
+ results.add(t);
+ }
+ }
+ display.printSearchTask(results);
+ } catch (MissingParameterException e) {
+ e.missingParamKeyword();
+ }
+ }
+
+ /**
+ * This method instantiate a Todo object and add the Todo object to the TaskList
+ *
+ * @param taskName The name of the TODO task to be added
+ **/
+ public void addTask(String taskName, boolean isCompleted, boolean isSilentMode) {
+ try {
+ if (taskName == null) {
+ throw new MissingParameterException();
+ } else {
+ Todo t = new Todo(taskName);
+ list.add(t);
+ t.setCompleted(isCompleted);
+ if (!isSilentMode) {
+ display.printAddedTask(t, list.size());
+ fm.updateFile(list);
+ }
+ }
+ } catch (MissingParameterException e) {
+ e.missingParamDesc();
+ }
+ }
+
+ /**
+ * This method instantiate a Deadline object and add the Deadline object to the TaskList
+ *
+ * @param taskName a string that represents the name of the Deadline task to add.
+ * @param byWhen a string that represents the deadline of the Deadline task.
+ **/
+ public void addTask(String taskName, String byWhen, boolean isCompleted, boolean isSilentMode) {
+ try {
+ if (taskName == null || byWhen == null) {
+ throw new MissingParameterException();
+ } else {
+ Deadline d = new Deadline(taskName, byWhen);
+ list.add(d);
+ d.setCompleted(isCompleted);
+ if (!isSilentMode) {
+ fm.updateFile(list);
+ display.printAddedTask(d, list.size());
+ }
+ }
+ } catch (MissingParameterException e) {
+ if (taskName == null) {
+ e.missingParamDesc();
+ } else {
+ e.missingParamBy();
+ }
+ }
+ }
+
+ /**
+ * This method instantiate an Event object and add the Event object to the TaskList
+ *
+ * @param taskName a string that represents the name of the Event task to add.
+ * @param startWhen a string that represents the start date and time of the Event task.
+ * @param endWhen a string that represents the end date and time of the Event task.
+ */
+ public void addTask(String taskName, String startWhen, String endWhen, boolean isCompleted, boolean isSilentMode) {
+ try {
+ if (taskName == null || startWhen == null || endWhen == null) {
+ throw new MissingParameterException();
+ } else {
+ Event e = new Event(taskName, startWhen, endWhen);
+ list.add(e);
+ e.setCompleted(isCompleted);
+ if (!isSilentMode) {
+ fm.updateFile(list);
+ display.printAddedTask(e, list.size());
+ }
+ }
+ } catch (MissingParameterException e) {
+ if (taskName == null) {
+ e.missingParamDesc();
+ } else if (startWhen == null) {
+ e.missingParamStart();
+ } else {
+ e.missingParamEnd();
+ }
+ }
+ }
+
+ /**
+ * Deletes a task.
+ *
+ * @param taskIndex string that represents the index of the task to unmark (1-Indexed).
+ */
+ public void deleteTask(String taskIndex) {
+ try {
+ if (taskIndex == null) {
+ throw new MissingParameterException();
+ }
+ int taskNumber = Integer.parseInt(taskIndex);
+ if (taskNumber <= 0 || taskNumber > list.size()) {
+ throw new OutOfBoundException();
+ } else {
+ display.printDeletedTask(list, taskNumber);
+ list.remove(taskNumber - 1);
+ fm.updateFile(list);
+ }
+ } catch (OutOfBoundException e) {
+ e.errorDelete();
+ } catch (MissingParameterException e) {
+ e.missingParamTaskIndex();
+ }
+ }
+
+ /**
+ * Unmarks a completed task.
+ *
+ * @param taskIndex string that represents the index of the task to unmark (1-Indexed).
+ */
+ public void markingTask(String taskIndex, Boolean isMark) {
+
+ try {
+ if (taskIndex == null) {
+ throw new MissingParameterException();
+ }
+ int taskNumber = Integer.parseInt(taskIndex);
+ if (taskNumber <= 0 || taskNumber > list.size()) {
+ throw new OutOfBoundException();
+ } else if ((!isMark && !list.get(taskNumber - 1).isCompleted()) ||
+ (isMark && list.get(taskNumber - 1).isCompleted())) {
+ throw new IllegalOperationException();
+ } else {
+ list.get(taskNumber - 1).setCompleted(isMark);
+ fm.updateFile(list);
+ display.printMarking(list, taskNumber, isMark);
+ }
+ } catch (OutOfBoundException e) {
+ e.errorUnmark();
+ } catch (IllegalOperationException e) {
+ if (isMark) {
+ e.errorAlreadyMarked();
+ } else {
+ e.errorAlreadyUnmarked();
+ }
+ } catch (MissingParameterException e) {
+ e.missingParamTaskIndex();
+ }
+
+ }
+
+ /**
+ * Display a list of tasks currently stored in the list
+ */
+ public void listTask() {
+ System.out.println(display.printLine());
+ try {
+ if (list.size() > 0) {
+ System.out.println("Here are the tasks in your list:");
+ for (int i = 0; i < list.size(); i++) {
+ System.out.print(i + 1 + ".");
+ System.out.println(list.get(i).toString());
+ }
+ } else {
+ throw new EmptyListException();
+ }
+ } catch (EmptyListException e) {
+ e.errorMsg();
+ }
+ System.out.println(display.printLine());
+ }
+
+ public int getTaskCount() {
+ return list.size();
+ }
+}
+
diff --git a/src/main/java/sage/utility/Ui.java b/src/main/java/sage/utility/Ui.java
new file mode 100644
index 000000000..76d128aa2
--- /dev/null
+++ b/src/main/java/sage/utility/Ui.java
@@ -0,0 +1,71 @@
+package sage.utility;
+
+import java.util.Scanner;
+
+/**
+ * A class that represents user interaction methods such as the execution of user input and recovering previous session.
+ */
+
+public class Ui {
+
+ private static Display display = new Display();
+ private static TaskList taskList = new TaskList();
+
+ private static Storage fm = new Storage();
+
+
+ /**
+ * Retrieves and restore any available task information data stored in ./data/sage.txt
+ */
+ public void recoverData() {
+ fm.recoverData(taskList);
+ }
+
+ public String readInput() {
+ Scanner input = new Scanner(System.in);
+ return input.nextLine();
+ }
+
+ /**
+ * Reads the parsed user input and delegate the respective operation based on the task type
+ *
+ * @param parsed a Parser object that contains parsed user input
+ * @return boolean that indicates whether to exit the application
+ */
+ public boolean readCommand(Parser parsed) {
+ switch (parsed.getTaskType()) {
+ case "bye":
+ display.printGoodByeUser();
+ return true;
+ case "list":
+ taskList.listTask();
+ break;
+ case "unmark":
+ taskList.markingTask(parsed.getTaskDescription(), false);
+ break;
+ case "mark":
+ taskList.markingTask(parsed.getTaskDescription(), true);
+ break;
+ case "delete":
+ taskList.deleteTask(parsed.getTaskDescription());
+ break;
+ case "todo":
+ taskList.addTask(parsed.getTaskDescription(), false, false);
+ break;
+ case "deadline":
+ taskList.addTask(parsed.getTaskDescription(), parsed.getBy(), false, false);
+ break;
+ case "event":
+ taskList.addTask(parsed.getTaskDescription(), parsed.getFrom(), parsed.getTo(), false, false);
+ break;
+ case "find":
+ taskList.findTask(parsed.getTaskDescription());
+ break;
+ default:
+ display.printUnknownInput();
+ break;
+ }
+ return false;
+ }
+
+}
diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT
index 657e74f6e..c713e4352 100644
--- a/text-ui-test/EXPECTED.TXT
+++ b/text-ui-test/EXPECTED.TXT
@@ -1,7 +1,62 @@
-Hello from
- ____ _
-| _ \ _ _| | _____
-| | | | | | | |/ / _ \
-| |_| | |_| | < __/
-|____/ \__,_|_|\_\___|
+Hello! I'm SAGE, the knowledgeable one
+What can I do for you today?
+Got it. I've added this task:
+[T][ ] return books
+Now you have 1 tasks in the list
+Got it. I've added this task:
+[T][ ] return laundry
+Now you have 2 tasks in the list
+*****************************
+Here are the tasks in your list:
+1.[T][ ] return books
+2.[T][ ] return laundry
+*****************************
+Got it. I've added this task:
+[D][ ] assignment 1 (by: Next monday)
+Now you have 3 tasks in the list
+Got it. I've added this task:
+[D][ ] lab 10 (by: Next tues)
+Now you have 4 tasks in the list
+*****************************
+Here are the tasks in your list:
+1.[T][ ] return books
+2.[T][ ] return laundry
+3.[D][ ] assignment 1 (by: Next monday)
+4.[D][ ] lab 10 (by: Next tues)
+*****************************
+I don't understand what you mean, please try again!
+I don't understand what you mean, please try again!
+Got it. I've added this task:
+[E][ ] funfair 1 (from: 21 jan to: 4 feb)
+Now you have 5 tasks in the list
+Got it. I've added this task:
+[E][ ] fund raising (from: 30 feb to: 31 mar)
+Now you have 6 tasks in the list
+*****************************
+Here are the tasks in your list:
+1.[T][ ] return books
+2.[T][ ] return laundry
+3.[D][ ] assignment 1 (by: Next monday)
+4.[D][ ] lab 10 (by: Next tues)
+5.[E][ ] funfair 1 (from: 21 jan to: 4 feb)
+6.[E][ ] fund raising (from: 30 feb to: 31 mar)
+*****************************
+Nice! I've marked this task as done:
+[X] assignment 1
+Nice! I've marked this task as done:
+[X] funfair 1
+Uh-oh! Task Not Found!
+Task already marked as not completed!
+OK, I've marked this task as not done yet:
+[ ] assignment 1
+Task already marked as completed!
+*****************************
+Here are the tasks in your list:
+1.[T][ ] return books
+2.[T][ ] return laundry
+3.[D][ ] assignment 1 (by: Next monday)
+4.[D][ ] lab 10 (by: Next tues)
+5.[E][X] funfair 1 (from: 21 jan to: 4 feb)
+6.[E][ ] fund raising (from: 30 feb to: 31 mar)
+*****************************
\ No newline at end of file
diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt
index e69de29bb..dde8dc667 100644
--- a/text-ui-test/input.txt
+++ b/text-ui-test/input.txt
@@ -0,0 +1,18 @@
+todo return books
+todo return laundry
+list
+deadline assignment 1 /by Next monday
+deadline lab 10 /by Next tues
+list
+garbage 12323
+garbage asdasda
+event funfair 1 /from 21 jan /to 4 feb
+event fund raising /from 30 feb /to 31 mar
+list
+mark 3
+mark 5
+mark 100
+unmark 2
+unmark 3
+mark 5
+list
\ No newline at end of file