/**
 * Class representation of a test
 * Section 2.2.1
 * @author Andrew Guenther
 *
 * This class holds references to the profile that generated it
 * and all of the questions contained in it.
 */
package test;

import java.util.Collection;
import java.util.List;
import question.*;
import datatypes.Duration;
import publish.PublishOptions;

public abstract class Test {
  /**
   * The name of the test
   */
   public String name;

  /**
   * The question bank associated with the test
   */
   public QuestionBankAdmin course;

  /**
   * The minimum and maximum amount of time the generated test must take
   */
   public Duration minTime, maxTime;

  /**
   * The minimum and maximum difficulty of any question that can be placed on the test
   */
   public int minDiff, maxDiff;

  /**
   * The options the instructor selects when publishing the test
   */
   public PublishOptions publishOptions;

  /**
   * A collection of question keywords that can appear on the generated test
   */
   public Collection<Keyword> keywords;

  /**
   * The question type breakdown specified for the test
   */
   public Breakdown<Integer> typeBreakdown;

  /**
   * The difficulty breakdown specified for the test
   */
   public Breakdown<Integer> difficultyBreakdown;

  /**
   * The keyword breakdown specified for the test
   */
   public Breakdown<Keyword> keywordBreakdown;

  /**
   * The list of questions that will appear on the test
   */
   public List<TestItem> questions;

  /**
   * Adds the input TestItem to the list of questions
   */
  /*@
    requires
    //
    // The TestItem is not null
    //
    (q != null);

    ensures
    //
    // The given TestItem is on the Test
    //
    questions.contains(q) 
    &&
     (\forall TestItem question ;
            questions.contains(question) <==>
                question.equals(q) || \old(questions).contains(q));
    @*/

   public abstract void add(TestItem q);

  /**
   * Removes the given TestItem from the Test
   */
  /*@
    requires
    //
    // The given TestItem is in the collection of question
    //
    (questions.contains(q));
    
    ensures
    //
    // A TestItem is on the Test if and only if
    // it is not equal to the input TestItem. 
    //
    (\forall TestItem question ; 
       questions.contains(question) <==>
          !question.equals(q) && \old(questions).contains(question)) ;

    @*/  
   public abstract TestItem remove(TestItem q);

  /**
   * Replaces the given TestItem with another TestItem that matches the same test generation criteria
   */
   /*@
    requires 
    // The oldq is in the current collection
     ((questions).contains(oldq));
     ensures
    // The old question is no longer in the DB
     (!questions.contains(oldq));
    @*/
   public abstract TestItem replace(TestItem oldq);

  /**
   * Populates the question list with a set of questions that meets the minimum and maximum difficulty and time constraints, as well as any associated breakdowns.
   */
   /*@
    ensures
    //there is at least one question in the test
     questions.size() > 0
     
     &&
    
    //all questions fall in the difficulty range
     (\forall TestItem t; questions.contains(t);
     	t.difficulty >= minDiff && t.difficulty <= maxDiff);


//     &&
// I cannot figure out how to do the sum of all of the times.
    @*/
   public abstract void generate();
}