package performa.orm;

import java.util.*;
import oneit.logging.LoggingArea;
import oneit.objstore.StorageException;
import oneit.objstore.rdbms.filters.EqualsFilter;
import oneit.objstore.rdbms.filters.IsNotNullFilter;
import oneit.utils.filter.CollectionFilter;
import oneit.utils.filter.Filter;
import oneit.utils.parsers.FieldException;
import performa.orm.types.AppProcessOption;
import performa.orm.types.ApplicationStatus;
import performa.orm.types.CriteriaType;


public class JobApplication extends BaseJobApplication
{
    private static final long   serialVersionUID    = 0L;
    public  static LoggingArea  LOG                 = LoggingArea.createLoggingArea("JobApplication");
    
    // This constructor should not be called
    public JobApplication ()
    {
        // Do not add any code to this, always put it in initialiseNewObject
    }

    
    public static JobApplication createNewApplication(Candidate candidate, Job job) throws StorageException, FieldException
    {
        JobApplication  jobApplication  =   createJobApplication(job.getTransaction());
        
        jobApplication.setCandidate(candidate);
        jobApplication.setJob(job);
        
        jobApplication.initACAnswers();
//        jobApplication.initCCAnswers();
        
        return jobApplication;
    }
    
    
    private void initACAnswers()
    {
        if(isIncludeAssessmentCriteria())
        {
            for(AssessmentCriteria assessmentCriteria : getJob().getAssessmentCriteriasSet())
            {
                AssessmentCriteriaAnswer    answer  =   AssessmentCriteriaAnswer.createAssessmentCriteriaAnswer(getTransaction());

                addToAssessmentCriteriaAnswers(answer);
                assessmentCriteria.addToAnswers(answer);
            }
        }
    }
    
    
    public boolean initCCAnswers()
    {
        boolean redirect    =   false;
        
        if(getCultureCriteriaAnswersCount() == 0)   //initCCAnswers not called yet
        {
            for(CultureCriteria cultureCriteria : getJob().getCultureCriteriasSet())
            {
                redirect                        =   true;
                CultureCriteriaAnswer   answer  =   CultureCriteriaAnswer.createCultureCriteriaAnswer(getTransaction());

                addToCultureCriteriaAnswers(answer);
                cultureCriteria.addToAnswers(answer);
            }
        }
        return redirect;
    }
    
    public boolean initAssessmentAnswers(List<Question> allQuestions) throws StorageException, FieldException
    {
        boolean redirect    =   false;
        
        if(getProfileAssessmentAnswersCount() == 0)
        {
            for(Question question : allQuestions)
            {
                redirect        =   true;
                Answer  answer  =   Answer.createAnswer(getTransaction());
            
                addToProfileAssessmentAnswers(answer);
                answer.setQuestion(question);

                if(question.getRightQuestion() != null)
                {
                    Answer  rightAnswer = Answer.createAnswer(getTransaction());

                    addToProfileAssessmentAnswers(rightAnswer);
                    rightAnswer.setQuestion(question.getRightQuestion());
                }
            }
        }
        return redirect;
    }
    
    public Answer getAnswerForQuestion(Question question) throws FieldException
    {
        Filter  filter  =   Answer.SearchByAll().andQuestion(new EqualsFilter<>(question));
        
        return CollectionFilter.getFirstMatch(getProfileAssessmentAnswersSet(), filter);
    }
    
    
    public Collection<AssessmentCriteriaAnswer> getACAnswersByType(CriteriaType criteriaType)
    {
        Filter  filter  =   AssessmentCriteriaAnswer.SearchByCriteriaType().byCriteriaType(criteriaType);

        return  CollectionFilter.filter(getAssessmentCriteriaAnswersSet(), filter);
    }

    
    public boolean selectionCompleted()
    {
        int allAnswersCount =   getAssessmentCriteriaAnswersCount();
        
        if(allAnswersCount > 0)
        {
            Filter      filter          =   AssessmentCriteriaAnswer.SearchByAll().andAnswer(new IsNotNullFilter<>());
            Collection  selectedAnswers =   pipelineJobApplication().toAssessmentCriteriaAnswers(filter).vals();

            return (selectedAnswers.size() == allAnswersCount);
        }
        return false;
    }
       
    
    public boolean cultureCompleted()
    {
        int allAnswersCount =   getCultureCriteriaAnswersCount();
        
        if(allAnswersCount > 0)
        {
            Filter      filter          =   CultureCriteriaAnswer.SearchByAll().andSelectedQuestion(new IsNotNullFilter<>());
            Collection  selectedAnswers =   pipelineJobApplication().toCultureCriteriaAnswers(filter).vals();

            return (selectedAnswers.size() == allAnswersCount);
        }
        return false;
    }
    
    
    public boolean assessmentCompleted()
    {
        int allAnswersCount =   getJob().getAllProfileAssessmentQuestions().size();
        
        if(allAnswersCount > 0)
        {
            Filter      filter          =   Answer.SearchByAll().andAnswerNo(new IsNotNullFilter<>());
            Collection  selectedAnswers =   pipelineJobApplication().toProfileAssessmentAnswers(filter).vals();

            return (selectedAnswers.size() == allAnswersCount);
        }
        return false;
    }
    
    
    public boolean isIncludeAssessmentCriteria()
    {
        return getJob() != null && isTrue(getJob().getIncludeAssessmentCriteria());
    }
    
//    TODO: Fix these hard coded values
    @Override
    public Integer getOverallSuitability()
    {
        return 1;
    }
    
    
    public int getJobMatchPercentage()
    {
        return 85;
    }
    
    
    public int getCulturePercentage()
    {
        return 90;
    }
    
    
    public int getCriteriaPercentage ()
    {
        return 95;
    }
    
    
    public List<AppProcessOption> getValidProcessOptions()
    {
        List<AppProcessOption>  options = new ArrayList<>();
        
        if(getApplicationStatus() == ApplicationStatus.SUBMITTED)
        {
            options.add(AppProcessOption.TO_SHORTLIST);
        }
        else if(getApplicationStatus() == ApplicationStatus.SHORTLISTED)
        {
            options.add(AppProcessOption.REMOVE_FROM_SHORTLIST);
        }
        
        return options;
    }
    
    
    public String getApplicantStatusStr()
    {
        if(getApplicationStatus() == ApplicationStatus.SUBMITTED)
        {
            return "Applicant";
        }
        else
        {
            return getApplicationStatus().getDescription();
        }
    }
}