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(JobApplication jobApplication) throws StorageException, FieldException
    {
        LogMgr.log(JobApplication.LOG, LogLevel.PROCESSING1, "Inside AnalysisEngine --> analyseAnswers");
        
        ObjectTransaction           objTran         =   jobApplication.getTransaction();
        Set<Factor>                 levelFactors    =   jobApplication.pipelineJobApplication().toJob().toLevel().toFactors().toFactor().uniqueVals();
        Filter<FactorQuestionLink>  factorFilter    =   FactorQuestionLink.SearchByAll().andFactor(new InFilter(levelFactors));
        
        //Preloading Data
        jobApplication.pipelineJobApplication().toProfileAssessmentAnswers().toQuestion().toSection().uniqueVals();
        jobApplication.pipelineJobApplication().toProfileAssessmentAnswers().toQuestion().toFactors().toFactor().uniqueVals();
        Factor.pipesFactor(levelFactors).toResults().uniqueVals();

        LogMgr.log(JobApplication.LOG, LogLevel.PROCESSING1, "Processing Job Application ", jobApplication);

        Map<Factor, Integer>    factorScoreMap  =   new HashMap();
            
        for (Answer answer : jobApplication.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() != null ? answer.getAnswerNo() : 0;
                }
                
                factorScoreMap.put(factor, factorScore);
            }
        }

        TestAnalysis    testAnalysis    =   TestAnalysis.createTestAnalysis(objTran);
            
        jobApplication.getJob().getLevel().addToTestAnalysises(testAnalysis);
        jobApplication.getCandidate().addToTestAnalysises(testAnalysis);
        testAnalysis.setJob(jobApplication.getJob());
        
        for(Factor factor : factorScoreMap.keySet())
        {
            int score   =   factorScoreMap.get(factor);

            LogMgr.log(JobApplication.LOG, LogLevel.PROCESSING1, "Candidate:", jobApplication.getCandidate(), " Factor:", factor, " Score:", score);

            Filter<FactorScoreResult>   factorScoreFilter   =   FactorScoreResult.SearchByAll().andLevel(new EqualsFilter<>(jobApplication.getJob().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.setLevel(jobApplication.getJob().getLevel());
                factorScore.setScore(score);
                factorScore.setWghtdScore(score);   //temp fix, to-do change later
                factorScore.setColorCode(factorScoreResult.getColorCode());
                factorScore.setColorRank(factorScoreResult.getColorCode() != null ? factorScoreResult.getColorCode().getWeightage() : 0);
                factorScore.setNarrative(factorScoreResult.getNarrative());

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