package performa.utils;

import java.util.*;
import oneit.logging.*;
import oneit.objstore.*;
import oneit.objstore.rdbms.filters.*;
import oneit.utils.filter.Filter;
import oneit.utils.parsers.FieldException;
import performa.orm.*;
import performa.orm.types.*;

/**
 *
 * @author nilu
 */
public class AnalysisEngine 
{
    public static void analyseAnswers(TestInput testInput) throws StorageException, FieldException
    {
        LogMgr.log(TestInput.LOG, LogLevel.PROCESSING1, "Inside AnalysisEngine --> analyseAnswers");
        
        ObjectTransaction           objTran         =   testInput.getTransaction();
        Set<Factor>                 levelFactors    =   testInput.pipelineTestInput().toLevel().toFactors().toFactor().uniqueVals();
        Filter<FactorQuestionLink>  factorFilter    =   FactorQuestionLink.SearchByAll().andFactor(new InFilter(levelFactors));
        
        //Preloading Data
        testInput.pipelineTestInput().toCandidates().toAnswers().toQuestion().toSection().uniqueVals();
        testInput.pipelineTestInput().toCandidates().toAnswers().toQuestion().toFactors().toFactor().uniqueVals();
        Factor.pipesFactor(levelFactors).toResults().uniqueVals();
        
        for (Candidate candidate : testInput.getCandidatesSet())
        {
            LogMgr.log(TestInput.LOG, LogLevel.PROCESSING1, "Processing candidate ", candidate);
            
            Map<Factor, Integer>    factorScoreMap  =   new HashMap();
            
            for (Answer answer : candidate.getAnswersSet())
            {
                Set<FactorQuestionLink> links   =   answer.pipelineAnswer().toQuestion().toFactors(factorFilter).uniqueVals();
                
                for (FactorQuestionLink link : links) 
                {
                    int     factorScore =   0;
                    Factor  factor      =   link.getFactor();

                    if(factorScoreMap.containsKey(factor))
                    {
                        factorScore =   factorScoreMap.get(factor);
                    }

                    if(link.isTrue(link.getReverseScore()))
                    {
                        if(answer.getQuestion().getQuestionType() == QuestionType.IPSATIVE)
                        {
                            factorScore += (10 - answer.getAnswerNo());
                        }
                        else
                        {
                            factorScore += (8 - answer.getAnswerNo());
                        }
                    }
                    else
                    {
                        factorScore += answer.getAnswerNo();
                    }
                    factorScoreMap.put(factor, factorScore);
                }
            }
            TestAnalysis    testAnalysis    =   TestAnalysis.createTestAnalysis(objTran);
            
            testInput.getLevel().addToTestAnalysises(testAnalysis);
            candidate.addToTestAnalysises(testAnalysis);
            
            for(Factor factor : factorScoreMap.keySet())
            {
                int score   =   factorScoreMap.get(factor);
                
                LogMgr.log(TestInput.LOG, LogLevel.PROCESSING1, "Candidate:", candidate, " Factor:", factor, " Score:", score);
                
                Filter<FactorScoreResult>   factorScoreFilter   =   FactorScoreResult.SearchByAll().andLevel(new EqualsFilter<>(testInput.getLevel()))
                                                                                                .andFromScore(new LessThanEqualFilter<>(score))
                                                                                                .andToScore(new GreaterThanEqualFilter<>(score));
                
                List<FactorScoreResult>     factorScoreResults  =   (List<FactorScoreResult>) factor.pipelineFactor().toResults(factorScoreFilter).vals();

                if(factorScoreResults != null && !factorScoreResults.isEmpty())
                {
                    FactorScoreResult   factorScoreResult   =   factorScoreResults.get(0);
                    
                    FactorScore factorScore =   FactorScore.createFactorScore(objTran);

                    factorScore.setFactor(factor);
                    factorScore.setScore(score);
                    factorScore.setColorCode(factorScoreResult.getColorCode());
                    factorScore.setColorRank(factorScoreResult.getColorCode() != null ? factorScoreResult.getColorCode().getWeightage() : 0);
                    factorScore.setNarrative(factorScoreResult.getNarrative());

                    testAnalysis.addToFactorScores(factorScore);
                }
            }
        }
        LogMgr.log(TestInput.LOG, LogLevel.PROCESSING1, "AnalysisEngine --> analyseAnswers completed");
    }
}