/* ======================================================================
   Parts Copyright 2006 University of Leeds, Oxford University, University of the Highlands and Islands.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

====================================================================== */

package org.bodington.assessment;

import java.util.Hashtable;
import java.util.Vector;

import org.bodington.database.PrimaryKey;
import org.bodington.server.BuildingServerException;
import org.bodington.server.SingleResourceSession;

/**
 * Class that encapsulates the analysis of the responses to a questionnaire.
 * @see QuestionnaireResult
 * @see QuestionnaireResponse
 * @author Jon Maber
 * @author Alexis O'Connor
 */
public class QuestionnaireAnalysis
	{
	private Hashtable item_counts;                 
    private Hashtable comments;
	
	
	/**
	 * Create a new instance.
	 */
	public QuestionnaireAnalysis()
		{
		item_counts = new Hashtable();
		comments = new Hashtable();
		}
		
		
    /* TODO: do something about this empty method.
     * Current thinking would be to implement it properly (it is called). 
     * 1) Modify the analyse() method in QuestionnaireSession to be:
     * QuestionnaireAnalysis analysis(String whereSQL, QuestionnaireAnalysis)
     * the analysis object accepted and returned would be the same object.
     * 2) Add a method such as List getQuestionnaireResults() to this class(?).
     * = Alternatively =
     * Just remove this method!
     */
    /**
     * Add the questionnaire result. This object will collate data from the
     * arguments in order to provide analytical information via other methods.
     * @param result the questionnaire result.
     * @see #getComments(PrimaryKey, int)
     * @see #getItemCounts(PrimaryKey, int)
     */
	public void addQuestionnaireResult( QuestionnaireResult result )
		{
		}
	
	/**
     * Add the questionnaire question response. This object will
     * collate data from the arguments in order to provide analytical
     * information via other methods.
	 * @param question the questionnaire question.
	 * @param result the questionnaire result.
	 * @param response the questionnaire question response.
     * @see #getComments(PrimaryKey, int)
     * @see #getItemCounts(PrimaryKey, int)
	 */
	public void addQuestionnaireResponse( QuestionnaireQuestion question, 
        QuestionnaireResult result, QuestionnaireResponse response )
		throws BuildingServerException
		{
		String comment;
		int[] items = (int[])item_counts.get( response.getQuestionnaireQuestionId() );
		if ( items == null )
			{
			items = new int[10];
			item_counts.put( response.getQuestionnaireQuestionId(), items );
			}
			
		Vector[] c = (Vector[])comments.get( response.getQuestionnaireQuestionId() );
		if ( c == null )
			{
			c = new Vector[11];
			for ( int j=0; j<11; j++ )
				c[j] = new Vector();
			comments.put( response.getQuestionnaireQuestionId(), c );
			}

        if ( question.isMultipleResponse() )
            {
            byte[] selection = response.getSelection();
            for (int i = 0; i < selection.length; i++)
                items[selection[i]]++;
            }
        else
            {
            if ( response.getItem()>=0 && response.getItem()<10 )
                items[response.getItem()]++;
            }
        
			
		if ( response.getComment() != null )
			{
			comment = response.getComment().trim();
			if ( comment.length()>0 )
				{
                int item = response.getItem();
				if ( !question.isMultipleResponse() && item >= 0 && item < 10 )
					c[item].addElement( comment );
				else
					c[10].addElement( comment );
				}
			}
		}

	// more methods to retrieve the results of the analysis...


	/**
     * Get the number of times a multiple-choice item was selected for the
     * specified question. The <code>statement</code> parameter refers to
     * which of the multiple-choice items you wish to obtain the total for.
     * @param question_id the ID of the question of interest.
     * @param statement the index of the statement of interest.
     * @return the number of times a multiple-choice item was selected for the
     *         specified question.
     * @see QuestionnaireQuestion#getQuestionnaireQuestionId()
     */
	public int getItemCounts( PrimaryKey question_id, int statement )
		{
		int[] items = (int[])item_counts.get( question_id );
		if ( items == null )
			return 0;
		return items[statement];
		}

    /**
     * Get the list of comments corresponding to a question and single MCQ
     * response. The <code>statement</code> parameter refers to which of the
     * single MCQ response choices you are interested in. The maximum number of
     * possible single MCQ response choices to choose from is <code>10</code>
     * (indexed from <code>0</code> to <code>9</code>). If there was no
     * corresponding single MCQ response selection, the comment is available at
     * index <code>10</code> (where the question is a multiple response type,
     * any comment is <em>always</em> placed at this index).
     * @param question_id the ID of the question of interest.
     * @param statement the index of the single MCQ response.
     * @return the list of comments corresponding to a question and single MCQ
     *         response.
     * @see QuestionnaireQuestion#getQuestionnaireQuestionId()
     * @see QuestionnaireResponse#getItem()
     * @see QuestionnaireQuestion#isMultipleResponse()
     */
	public Vector getComments( PrimaryKey question_id, int statement )
		{
		Vector[] c = (Vector[])comments.get( question_id );
		if ( c == null )
			return new Vector();
		return c[statement];
		}
	}
