001package edu.pdx.cs410J.grader.poa;
002
003import com.google.common.eventbus.EventBus;
004import com.google.common.eventbus.Subscribe;
005import com.google.inject.Inject;
006import com.google.inject.Singleton;
007import edu.pdx.cs410J.grader.gradebook.GradeBook;
008import edu.pdx.cs410J.grader.gradebook.Student;
009
010import java.util.Collections;
011import java.util.Comparator;
012import java.util.List;
013import java.util.stream.Collectors;
014
015@Singleton
016public class StudentsPresenter {
017  private final EventBus bus;
018  private final StudentsView view;
019  private List<Student> students = Collections.emptyList();
020
021  @Inject
022  public StudentsPresenter(EventBus bus, StudentsView view) {
023    this.bus = bus;
024    this.view = view;
025
026    this.bus.register(this);
027
028    this.view.addSelectStudentHandler(this::fireSelectedStudentEventForStudentAtIndex);
029  }
030
031  private void fireSelectedStudentEventForStudentAtIndex(int index) {
032    Student student;
033    if (index == 0) {
034      student = null;
035
036    } else {
037      student = this.students.get(index - 1);
038    }
039    fireStudentSelectedEvent(student);
040  }
041
042  private void fireStudentSelectedEvent(Student student) {
043    this.bus.post(new StudentSelectedEvent(student));
044  }
045
046  @Subscribe
047  public void populateViewWithStudents(GradeBookLoaded event) {
048    GradeBook book = event.getGradeBook();
049
050    this.students = book.studentsStream()
051      .sorted(sortStudentsByLastNameFirstNameEmail())
052      .collect(Collectors.toList());
053
054    List<String> studentsDisplayStrings = this.students.stream()
055      .map(this::getStudentDisplayText)
056      .collect(Collectors.toList());
057    studentsDisplayStrings.add(0, "<unknown student>");
058    this.view.setStudents(studentsDisplayStrings);
059
060    this.view.setSelectedStudentIndex(0);
061  }
062
063  private Comparator<Student> sortStudentsByLastNameFirstNameEmail() {
064    return (student1, student2) -> {
065      String lastName1 = getLastNameOfStudent(student1);
066      String lastName2 = getLastNameOfStudent(student2);
067      if (!lastName1.equals(lastName2)) {
068        return lastName1.compareTo(lastName2);
069
070      } else {
071        String firstName1 = getFirstNameOfStudent(student1);
072        String firstName2 = getFirstNameOfStudent(student2);
073        if (!firstName1.equals(firstName2)) {
074          return firstName1.compareTo(firstName2);
075
076        } else {
077          return student1.getEmail().compareTo(student2.getEmail());
078        }
079      }
080    };
081  }
082
083  private String getLastNameOfStudent(Student student) {
084    String lastName = student.getLastName();
085    if (lastName == null) {
086      throw new IllegalStateException("Student " + student.getId() + " doesn't have a last name");
087    }
088    return lastName;
089  }
090
091  private String getStudentDisplayText(Student student) {
092    return getFirstNameOfStudent(student) + " " + getLastNameOfStudent(student) + " <" + student.getEmail() + ">";
093  }
094
095  @Subscribe
096  public void attemptToMatchSubmissionWithStudent(POASubmissionSelected selected) {
097    for (int i = 0; i < students.size(); i++) {
098      Student student = students.get(i);
099      if (submitterMatchesStudent(selected.getSubmission(), student)) {
100        this.view.setSelectedStudentIndex(i + 1);
101        fireStudentSelectedEvent(student);
102        return;
103      }
104    }
105
106    if (this.students.size() > 0) {
107      this.view.setSelectedStudentIndex(0);
108    }
109    fireStudentSelectedEvent(null);
110  }
111
112  private boolean submitterMatchesStudent(POASubmission submission, Student student) {
113    String submitter = submission.getSubmitter();
114    return submitterContainsStudentName(student, submitter) || submitterContainsStudentEmail(student, submitter);
115  }
116
117  private boolean submitterContainsStudentEmail(Student student, String submitter) {
118    return submitter.contains(student.getEmail());
119  }
120
121  private boolean submitterContainsStudentName(Student student, String submitter) {
122    return submitter.contains(getFirstNameOfStudent(student)) && submitter.contains(getLastNameOfStudent(student));
123  }
124
125  private String getFirstNameOfStudent(Student student) {
126    String firstName = student.getFirstName();
127    if (firstName == null) {
128      throw new IllegalStateException("Student " + student.getId() + " doesn't have a first name");
129    }
130    return firstName;
131  }
132
133}