/*PLEASE DO NOT EDIT THIS CODE*/
/*This code was generated using the UMPLE 1.17.0.2716 modeling language!*/

package example.two;
import java.util.*;
import example.one.*;
import example.three.*;

public class Student
{

  //------------------------
  // MEMBER VARIABLES
  //------------------------

  //Student Attributes
  private String number;

  //Student Associations
  private List<Mentor> mentors;
  private List<Course> courses;

  //------------------------
  // CONSTRUCTOR
  //------------------------

  public Student(String aNumber, Mentor... allMentors)
  {
    number = aNumber;
    mentors = new ArrayList<Mentor>();
    boolean didAddMentors = setMentors(allMentors);
    if (!didAddMentors)
    {
      throw new RuntimeException("Unable to create Student, must have at least 1 mentors. See https://manual.umple.org?RE002ViolationofAssociationMultiplicity.html");
    }
    courses = new ArrayList<Course>();
  }

  //------------------------
  // INTERFACE
  //------------------------

  public boolean setNumber(String aNumber)
  {
    boolean wasSet = false;
    number = aNumber;
    wasSet = true;
    return wasSet;
  }

  public String getNumber()
  {
    return number;
  }

  public Mentor getMentor(int index)
  {
    Mentor aMentor = mentors.get(index);
    return aMentor;
  }

  public List<Mentor> getMentors()
  {
    List<Mentor> newMentors = Collections.unmodifiableList(mentors);
    return newMentors;
  }

  public int numberOfMentors()
  {
    int number = mentors.size();
    return number;
  }

  public boolean hasMentors()
  {
    boolean has = mentors.size() > 0;
    return has;
  }

  public int indexOfMentor(Mentor aMentor)
  {
    int index = mentors.indexOf(aMentor);
    return index;
  }

  public Course getCourse(int index)
  {
    Course aCourse = courses.get(index);
    return aCourse;
  }

  public List<Course> getCourses()
  {
    List<Course> newCourses = Collections.unmodifiableList(courses);
    return newCourses;
  }

  public int numberOfCourses()
  {
    int number = courses.size();
    return number;
  }

  public boolean hasCourses()
  {
    boolean has = courses.size() > 0;
    return has;
  }

  public int indexOfCourse(Course aCourse)
  {
    int index = courses.indexOf(aCourse);
    return index;
  }

  public static int minimumNumberOfMentors()
  {
    return 1;
  }

  public boolean addMentor(Mentor aMentor)
  {
    boolean wasAdded = false;
    if (mentors.contains(aMentor)) { return false; }
    Student existingStudent = aMentor.getStudent();
    if (existingStudent != null && existingStudent.numberOfMentors() <= minimumNumberOfMentors())
    {
      return wasAdded;
    }
    else if (existingStudent != null)
    {
      existingStudent.mentors.remove(aMentor);
    }
    mentors.add(aMentor);
    setStudent(aMentor,this);
    wasAdded = true;
    return wasAdded;
  }

  public boolean removeMentor(Mentor aMentor)
  {
    boolean wasRemoved = false;
    if (mentors.contains(aMentor) && numberOfMentors() > minimumNumberOfMentors())
    {
      mentors.remove(aMentor);
      setStudent(aMentor,null);
      wasRemoved = true;
    }
    return wasRemoved;
  }

  public boolean setMentors(Mentor... newMentors)
  {
    boolean wasSet = false;
    if (newMentors.length < minimumNumberOfMentors())
    {
      return wasSet;
    }

    ArrayList<Mentor> checkNewMentors = new ArrayList<Mentor>();
    HashMap<Student,Integer> studentToNewMentors = new HashMap<Student,Integer>();
    for (Mentor aMentor : newMentors)
    {
      if (checkNewMentors.contains(aMentor))
      {
        return wasSet;
      }
      else if (aMentor.getStudent() != null && !this.equals(aMentor.getStudent()))
      {
        Student existingStudent = aMentor.getStudent();
        if (!studentToNewMentors.containsKey(existingStudent))
        {
          studentToNewMentors.put(existingStudent, Integer.valueOf(existingStudent.numberOfMentors()));
        }
        Integer currentCount = studentToNewMentors.get(existingStudent);
        int nextCount = currentCount - 1;
        if (nextCount < 1)
        {
          return wasSet;
        }
        studentToNewMentors.put(existingStudent, Integer.valueOf(nextCount));
      }
      checkNewMentors.add(aMentor);
    }

    mentors.removeAll(checkNewMentors);

    for (Mentor orphan : mentors)
    {
      setStudent(orphan, null);
    }
    mentors.clear();
    for (Mentor aMentor : newMentors)
    {
      if (aMentor.getStudent() != null)
      {
        aMentor.getStudent().mentors.remove(aMentor);
      }
      setStudent(aMentor, this);
      mentors.add(aMentor);
    }
    wasSet = true;
    return wasSet;
  }

  private void setStudent(Mentor aMentor, Student aStudent)
  {
    try
    {
      java.lang.reflect.Field mentorField = aMentor.getClass().getDeclaredField("student");
      mentorField.setAccessible(true);
      mentorField.set(aMentor, aStudent);
    }
    catch (Exception e)
    {
      throw new RuntimeException("Issue internally setting aStudent to aMentor", e);
    }
  }

  public boolean addMentorAt(Mentor aMentor, int index)
  {  
    boolean wasAdded = false;
    if(addMentor(aMentor))
    {
      if(index < 0 ) { index = 0; }
      if(index > numberOfMentors()) { index = numberOfMentors() - 1; }
      mentors.remove(aMentor);
      mentors.add(index, aMentor);
      wasAdded = true;
    }
    return wasAdded;
  }

  public boolean addOrMoveMentorAt(Mentor aMentor, int index)
  {
    boolean wasAdded = false;
    if(mentors.contains(aMentor))
    {
      if(index < 0 ) { index = 0; }
      if(index > numberOfMentors()) { index = numberOfMentors() - 1; }
      mentors.remove(aMentor);
      mentors.add(index, aMentor);
      wasAdded = true;
    } 
    else 
    {
      wasAdded = addMentorAt(aMentor, index);
    }
    return wasAdded;
  }

  public static int minimumNumberOfCourses()
  {
    return 0;
  }

  public boolean addCourse(Course aCourse)
  {
    boolean wasAdded = false;
    if (courses.contains(aCourse)) { return false; }
    courses.add(aCourse);
    if (aCourse.indexOfStudent(this) != -1)
    {
      wasAdded = true;
    }
    else
    {
      wasAdded = aCourse.addStudent(this);
      if (!wasAdded)
      {
        courses.remove(aCourse);
      }
    }
    return wasAdded;
  }

  public boolean removeCourse(Course aCourse)
  {
    boolean wasRemoved = false;
    if (!courses.contains(aCourse))
    {
      return wasRemoved;
    }

    int oldIndex = courses.indexOf(aCourse);
    courses.remove(oldIndex);
    if (aCourse.indexOfStudent(this) == -1)
    {
      wasRemoved = true;
    }
    else
    {
      wasRemoved = aCourse.removeStudent(this);
      if (!wasRemoved)
      {
        courses.add(oldIndex,aCourse);
      }
    }
    return wasRemoved;
  }

  public boolean addCourseAt(Course aCourse, int index)
  {  
    boolean wasAdded = false;
    if(addCourse(aCourse))
    {
      if(index < 0 ) { index = 0; }
      if(index > numberOfCourses()) { index = numberOfCourses() - 1; }
      courses.remove(aCourse);
      courses.add(index, aCourse);
      wasAdded = true;
    }
    return wasAdded;
  }

  public boolean addOrMoveCourseAt(Course aCourse, int index)
  {
    boolean wasAdded = false;
    if(courses.contains(aCourse))
    {
      if(index < 0 ) { index = 0; }
      if(index > numberOfCourses()) { index = numberOfCourses() - 1; }
      courses.remove(aCourse);
      courses.add(index, aCourse);
      wasAdded = true;
    } 
    else 
    {
      wasAdded = addCourseAt(aCourse, index);
    }
    return wasAdded;
  }

  public void delete()
  {
    for(Mentor aMentor : mentors)
    {
      setStudent(aMentor,null);
    }
    mentors.clear();
    ArrayList<Course> copyOfCourses = new ArrayList<Course>(courses);
    courses.clear();
    for(Course aCourse : copyOfCourses)
    {
      aCourse.removeStudent(this);
    }
  }


  public String toString()
  {
    return super.toString() + "["+
            "number" + ":" + getNumber()+ "]";
  }
}
