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


import java.util.*;
import java.io.Serializable;

// line 12 "model.ump"
public class Course implements java.io.Serializable
{

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

  //Course Attributes
  private String code;
  private transient Comparator<Registration> registrationsPriority;

  //Course Associations
  private Academy academy;
  private List<Registration> registrations;

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

  public Course(String aCode, Academy aAcademy)
  {
    code = aCode;
    registrationsPriority = 
      Comparator.comparing(Registration::getName);
    boolean didAddAcademy = setAcademy(aAcademy);
    if (!didAddAcademy)
    {
      throw new RuntimeException("Unable to create course due to academy. See https://manual.umple.org?RE002ViolationofAssociationMultiplicity.html");
    }
    registrations = new ArrayList<Registration>();
  }

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

  public boolean setCode(String aCode)
  {
    boolean wasSet = false;
    code = aCode;
    wasSet = true;
    return wasSet;
  }

  public boolean setRegistrationsPriority(Comparator<Registration> aRegistrationsPriority)
  {
    boolean wasSet = false;
    registrationsPriority = aRegistrationsPriority;
    wasSet = true;
    return wasSet;
  }

  public String getCode()
  {
    return code;
  }

  public Comparator<Registration> getRegistrationsPriority()
  {
    return registrationsPriority;
  }
  /* Code from template association_GetOne */
  public Academy getAcademy()
  {
    return academy;
  }
  /* Code from template association_GetMany */
  public Registration getRegistration(int index)
  {
    Registration aRegistration = registrations.get(index);
    return aRegistration;
  }

  public List<Registration> getRegistrations()
  {
    List<Registration> newRegistrations = Collections.unmodifiableList(registrations);
    return newRegistrations;
  }

  public int numberOfRegistrations()
  {
    int number = registrations.size();
    return number;
  }

  public boolean hasRegistrations()
  {
    boolean has = registrations.size() > 0;
    return has;
  }

  public int indexOfRegistration(Registration aRegistration)
  {
    int index = registrations.indexOf(aRegistration);
    return index;
  }
  /* Code from template association_SetOneToMany */
  public boolean setAcademy(Academy aAcademy)
  {
    boolean wasSet = false;
    if (aAcademy == null)
    {
      return wasSet;
    }

    Academy existingAcademy = academy;
    academy = aAcademy;
    if (existingAcademy != null && !existingAcademy.equals(aAcademy))
    {
      existingAcademy.removeCourse(this);
    }
    academy.addCourse(this);
    wasSet = true;
    return wasSet;
  }
  /* Code from template association_MinimumNumberOfMethod */
  public static int minimumNumberOfRegistrations()
  {
    return 0;
  }
  /* Code from template association_AddManyToOne */
  public Registration addRegistration(Student aStudent)
  {
    return new Registration(aStudent, this);
  }

  public boolean addRegistration(Registration aRegistration)
  {
    boolean wasAdded = false;
    if (registrations.contains(aRegistration)) { return false; }
    Course existingCourse = aRegistration.getCourse();
    boolean isNewCourse = existingCourse != null && !this.equals(existingCourse);
    if (isNewCourse)
    {
      aRegistration.setCourse(this);
    }
    else
    {
      registrations.add(aRegistration);
    }
    wasAdded = true;
    if(wasAdded)
        Collections.sort(registrations, registrationsPriority);
    
    return wasAdded;
  }

  public boolean removeRegistration(Registration aRegistration)
  {
    boolean wasRemoved = false;
    //Unable to remove aRegistration, as it must always have a course
    if (!this.equals(aRegistration.getCourse()))
    {
      registrations.remove(aRegistration);
      wasRemoved = true;
    }
    return wasRemoved;
  }


  /* Code from template association_sorted_serializable_readObject */ 
  private void readObject(java.io.ObjectInputStream in)
  throws Exception
  {
    in.defaultReadObject();

    registrationsPriority = 
      Comparator.comparing(Registration::getName);
  }
  
  public void delete()
  {
    Academy placeholderAcademy = academy;
    this.academy = null;
    if(placeholderAcademy != null)
    {
      placeholderAcademy.removeCourse(this);
    }
    for(int i=registrations.size(); i > 0; i--)
    {
      Registration aRegistration = registrations.get(i - 1);
      aRegistration.delete();
    }
  }


  public String toString()
  {
    return super.toString() + "["+
            "code" + ":" + getCode()+ "]" + System.getProperties().getProperty("line.separator") +
            "  " + "registrationsPriority" + "=" + (getRegistrationsPriority() != null ? !getRegistrationsPriority().equals(this)  ? getRegistrationsPriority().toString().replaceAll("  ","    ") : "this" : "null") + System.getProperties().getProperty("line.separator") +
            "  " + "academy = "+(getAcademy()!=null?Integer.toHexString(System.identityHashCode(getAcademy())):"null");
  }
}