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().toJobApplications().toProfileAssessmentAnswers().toQuestion().toSection().uniqueVals();
        testInput.pipelineTestInput().toCandidates().toJobApplications().toProfileAssessmentAnswers().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(JobApplication application: candidate.getJobApplicationsSet())
            {
                for (Answer answer : application.getProfileAssessmentAnswersSet())
                {
                    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");
    }
}