package com.uvigo.mhp;

import java.beans.*;
import java.util.*;

// La clase TestManager sirve para construir ex�menes desde un entorno de programacion
// visual. Recoge un conjunto de preguntas (objetos Test y Question), y fija el numero minimo
// de ellas correcto para aprobar. Los objetos Test se tratan como una sola pregunta: o se
// aprueba o se suspende en su totalidad.
// Un TestManager puede depender a su vez de otro TestManager... y asi indefinidamente, de modo
// que pueden construirse estructuras de evaluacion arbitrariamente complejas, si bien lo mas
// normal seran estructuras mas simples, como un solo TestManager controlando un conjunto de
// preguntas sueltas; otra posibilidad es un objeto Test, sin TestManager ni nada.

public class TestManager implements TestElement
{
    private Vector elements;
    private Vector listeners;
    private int minimumCorrectAnswers;
    private PropertyChangeSupport changes;
    private TestManager testManager;
    
    public TestManager()
    {
        elements=new Vector();
        listeners=new Vector();
        minimumCorrectAnswers=0;
        changes=new PropertyChangeSupport(this);
    }
    
    public void addTestElement(TestElement te)
    {
        if (!(elements.contains(te)))
            elements.add(te);
    }
    
    public void removeTestElement(TestElement te)
    {
        if (elements.contains(te))
            elements.remove(te);
    }
    
    ////////////////////////////////////////////////////////////////////////////
    // Metodos de la interfaz TestElement
    ////////////////////////////////////////////////////////////////////////////
    
    public int getMinimumCorrectAnswers()
    {
        return minimumCorrectAnswers;
    }
    
    public void setMinimumCorrectAnswers(int i)
    {
        int old=minimumCorrectAnswers;
        minimumCorrectAnswers=i;
        changes.firePropertyChange("minimumCorrectAnswers", new Integer(old), new Integer(i));
    }
    
    public void addTestListener(TestListener c)
    {
        if (!(listeners.contains(c)))
            listeners.add(c);
    }
    
    public void removeTestListener(TestListener c)
    {
        if (listeners.contains(c))
            listeners.remove(c);
    }
    
    public void checkAnswers()
    {
        if (isPassed())
            for (int i=0;i<listeners.size();i++)
            {
                TestListener c=(TestListener) listeners.get(i);
                c.testPassed(new TestEvent(this));
            }
        else
            for (int i=0;i<listeners.size();i++)
            {
                TestListener c=(TestListener) listeners.get(i);
                c.testFailed(new TestEvent(this));
            }
        
        // Por ultimo, se lanza un evento indicando que se han evaluado las respuestas
        for (int i=0;i<listeners.size();i++)
        {
            TestListener c=(TestListener) listeners.get(i);
            c.testChecked(new TestEvent(this));
        }
    }
    
    public int countCorrectAnswers()
    {
        int correct=0;
        for (int i=0;i<elements.size();i++)
        {
            TestElement te=(TestElement) elements.get(i);
            if (te.isPassed())
                correct++;
        }
        return correct;
    }
    
    public int countIncorrectAnswers()
    {
        return elements.size()-countCorrectAnswers();
    }
    
    public int countQuestions()
    {
        return elements.size();
    }
    
    public boolean isFailed()
    {
        return !isPassed();
    }
    
    public boolean isPassed()
    {
        if (countCorrectAnswers()>=minimumCorrectAnswers)
            return true;
        return false;
    }
    
    public void reset()
    {
        for (int i=0;i<elements.size();i++)
        {
            TestElement te=(TestElement) elements.get(i);
            te.reset();
        }
    }
    
    public void showCorrection()
    {
        for (int i=0;i<elements.size();i++)
        {
            TestElement te=(TestElement) elements.get(i);
            te.showCorrection();
        }
    }
    
    public TestManager getTestManager()
    {
        return testManager;
    }
    
    public void setTestManager(TestManager c)
    {
        TestManager old=testManager;
        
        // si se indica el mismo testManager que estaba configurado, no se hace nada
        if (c==old)
            return;
        
        // si habia alguno configurado, nos damos de baja
        if (old!=null)
            old.removeTestElement(this);
        
        // nos registramos en el nuevo ContextManager, pero solo si no es null
        if (c!=null)
            c.addTestElement(this);
        
        testManager=c;
        changes.firePropertyChange("testManager",old,c);
    }
}
