/*
 *  Team 1
 *  CS575: Software Design
 *  Project Phase II
 *  Imlicit Invocation style
 *  IISorter.java
 */

import java.util.Vector;

/**
 *  <p>Sorter class for the Imlicit Invocation KWIC system.
 *
 *  <p>Listens for events that enable it to sort the data in a given collection.
 *  Once that event is received, it will sort all the data in the given collection.
 *  It will broadcast messages to inform others of the progress it is making.</p>
 *
 *  <p>This class implements the KWICListener interface which enables it to 
 *  receive message sent by a KWICBroadcaster it is registered with. The class must 
 *  registered by a third party class; it cannot register on its own.
 *  </p>
 *
 *  <p>First, the constructor of the class must be called.  After that, the class will 
 *  simply wait for message to come in to its eventArrived() method.  These events
 *  will indicate what the class should do.  Those events that are not of importance to 
 *  this class will simply be ignored by the event handling processing of this class.
 *  </p>
 *
 *  <p>This class is capable of performing the following function.  It can traverse 
 *  a data collection and sort the data in it.  
 *  This functionality will be invoked when a message is
 *  received with a collection to be sorted. 
 *  </p> 
 *  @author Luiza da Silva
 */

public class IISorter implements KWICListener
{
    boolean verboseFlag;
    
    SentenceCollection collection;
    
    KWICBroadcaster broadcaster;

    /**
     * Constructor
     */
    public IISorter(KWICBroadcaster _broadcaster, boolean verbose)
    {
        verboseFlag = verbose;
        collection = new SentenceCollection();
        broadcaster = _broadcaster;
    }
   
    /**
     * Implements the KWICListener interface method.  This method will receive events and 
     * process them accordingly base on their content.
     * @param   event       KWICEvent which has been broadcasted
     */
    public void eventArrived(KWICEvent event) 
    {
        try{
            if( event.getEventType() == KWICEvent.SENTENCE_SHIFTED )
                addSentences((Vector)(event.getPayLoad()));

            else if( event.getEventType() == KWICEvent.SHIFTER_DONE )
            {
		collection = (SentenceCollection)(event.getPayLoad());
                sort();
            }
        }
        catch( KWICException e )
        {
            if( verboseFlag )
                System.out.println("EXCEPTION Message sent");
            
            broadcaster.eventBroadcast(new KWICEvent(
                            "Sorter",
                            KWICEvent.EXCEPTION,
                            e));
        }            
    }
 
    /**
     * This method will add the given sentence to the collection.
     * @param   sentence       Vector of words to be added to the collection as a sentence
     */
    private void addSentences(Vector sentence) throws KWICException
    {
        collection.addKWICRow(sentence.toArray());        
    }
        
    /** 
     * This method will call the appropriate sort algorithm to sort the list
     */
    private void sort() throws KWICException
    {
        insertionSort();
        
        if( verboseFlag )
            System.out.println("SORTER_DONE Message sent");        
        broadcaster.eventBroadcast(new KWICEvent(
            "Sorter",
            KWICEvent.SORTER_DONE,
            collection));
    }
    
    /**
     * <p> This method will sort the incoming data and place it in the 
     * SentenceCollection data object with all of the new sorted data in it.
     */
    private void insertionSort() throws KWICException 
    {
        // if empty, returns without operating on data
        // otherwise sorts data alphanumerically (Unicode)
        if (collection.isEmpty())
        {
            return;
        }		    
        else 
        {
            // sorts the data by direct insertion
            int n = collection.size();
            for (int i=1; i<n; i++)
            {
                int temp = i;
                for( int j = i-1; j >= 0; j-- )
                {
                    if( collection.isGreaterThan(collection.getKWICRowAt(j), collection.getKWICRowAt(temp))) 
                    {
                       // the key is smaller, so Sentence at j has to be moved one position up
                       collection.swapKWICRows(temp, j);
                       temp = j;
                    }	
                }
            }
            return;
        }
    }
    
    /** 
     * Returns the name of the class.  Used for broadcasting purposes.
     * @return  "Sorter"
     */
    public String getName() 
    {
        return "Sorter";
    }    
}