package performa.form;

import java.util.Map;
import oneit.objstore.ObjectTransaction;
import oneit.objstore.StorageException;
import oneit.objstore.parser.BusinessObjectParser;
import oneit.security.SecUser;
import oneit.servlets.forms.SubmissionDetails;
import oneit.servlets.forms.SuccessfulResult;
import oneit.servlets.process.ORMProcessState;
import oneit.servlets.process.SaveFP;
import oneit.utils.BusinessException;
import oneit.utils.CollectionUtils;
import oneit.utils.Debug;
import oneit.utils.MultiException;
import oneit.utils.RandomStringGen;
import oneit.utils.StringUtils;
import performa.orm.Candidate;
import performa.orm.Job;
import performa.orm.JobApplication;
import performa.utils.Utils;
import javax.servlet.http.HttpServletRequest;
import oneit.logging.LogLevel;
import oneit.logging.LogMgr;
import oneit.logging.LoggingArea;
import oneit.servlets.security.SessionSecUserDecorator;


public class IdentifyMaskedUserFP  extends SaveFP
{
    private static final LoggingArea  LOG   =   LoggingArea.createLoggingArea("IdentifyMaskedUserFP");

    @Override
    public void validate(ORMProcessState process, SubmissionDetails submission, MultiException exceptions, Map params) throws StorageException 
    {
        HttpServletRequest  request =   submission.getRequest();
        Job                 job     =   (Job) request.getAttribute("Job");

        Debug.assertion(job != null, "BO not avaialble");
        
        Candidate   candidate   =   (Candidate) request.getAttribute("Candidate");
        SecUser     secUser     =   candidate.getUser();

        BusinessObjectParser.assertFieldCondition(secUser.getEmail() != null , job, Job.FIELD_Email, "mandatory", exceptions, true, request);
        BusinessObjectParser.assertFieldCondition(StringUtils.isEmailAddress(secUser.getEmail()), job, Job.FIELD_Email, "invalid", exceptions, true, request);
        BusinessObjectParser.assertFieldCondition(secUser.getFirstName() != null, secUser, SecUser.FIELD_FirstName, "mandatory", exceptions, true, request);
        BusinessObjectParser.assertFieldCondition(secUser.getLastName() != null, secUser, SecUser.FIELD_LastName, "mandatory", exceptions, true, request);

        if(candidate.isEmailFound())
        {
            String  password = (String) request.getParameter("password");
            
            BusinessObjectParser.assertFieldCondition(password != null, secUser, SecUser.FIELD_Password, "mandatory", exceptions, true, request);
        }
        
        super.validate(process, submission, exceptions, params);
    }
    
    
    @Override 
    public SuccessfulResult processForm(ORMProcessState process, SubmissionDetails submission, Map params) throws BusinessException, StorageException
    {
        HttpServletRequest  request         =   submission.getRequest();
        ObjectTransaction   objTran         =   process.getTransaction();
        Candidate           candidate       =   (Candidate) request.getAttribute("Candidate");
        JobApplication      jobApplication  =   (JobApplication) request.getAttribute("JobApplication");
        String              password        =   (String) request.getParameter("password");
        Job                 job             =   (Job) request.getAttribute("Job");
        
        LogMgr.log(LOG, LogLevel.PROCESSING1, "Started IdentifyMaskedUserFP", candidate);

        if(candidate.isTrue(candidate.getIsEmailIngest()) && candidate.isTrue(candidate.getIsMaskedEmail()))
        {
            SecUser old         =   (SecUser) candidate.getUser().getEarliestBackup();
            String  userEmail   =   candidate.getUser().getEmail();

            if(CollectionUtils.equals(old.getEmail(), candidate.getUser().getEmail()))
            {
                throw new BusinessException("Please enter a valid email address");
            }

            if(Utils.emailExists(objTran, userEmail))
            {
                LogMgr.log(LOG, LogLevel.PROCESSING1, "User account already exists with the entered email", candidate, "email: " , userEmail);

                if(Utils.isCompanyUserEmailFound(objTran, userEmail))
                {
                    throw new BusinessException("This email address is already in use by a Hiring Team account.");
                }

                SecUser     newUser             =   candidate.getUser();
                SecUser     existingUser        =   SecUser.searchNAME(objTran, userEmail);
                Candidate   existingCandidate   =   existingUser.getExtension(Candidate.REFERENCE_Candidate);

                if(!existingUser.checkPassword(password))
                {
                    throw new BusinessException("Invalid Password. Please try again");
                }

                try
                {
                    //Ideally should be managed with uniqueGroup, but uniqueGroup doesnt work without atleast 1 attribute
                    JobApplication.searchCandidateJob(process.getTransaction(), candidate, job); //It will throw RuntimeException when more than 1 record found.
                }
                catch(RuntimeException ex)
                {
                    throw new BusinessException("You have already applied for this job.");
                }
                
                for(JobApplication application : candidate.getJobApplicationsSet())
                {
                    application.setCandidate(existingCandidate);
                }
                
                existingUser.setFirstName(newUser.getFirstName());
                existingUser.setLastName(newUser.getLastName());
                existingCandidate.setKnownAsAlias(old.getEmail());
                
                candidate.delete();
                newUser.delete();
                
                request.getSession().setAttribute (SecUser.SEC_USER_ID, existingUser);
                request.getSession().setAttribute (SessionSecUserDecorator.REFRESH_SECURITY, Boolean.TRUE);
            }
            else
            {
                //set new verification key as email changed
                candidate.setVerificationKey(new RandomStringGen().generateAlphaNum(6));

                candidate.getUser().setUserName(candidate.getUser().getEmail());
                candidate.setIsMaskedEmail(false);
                candidate.setKnownAsAlias(old.getEmail());
            }
        }
        
        LogMgr.log(LOG, LogLevel.PROCESSING1, "Finish IdentifyMaskedUserFP");

        return super.processForm(process, submission, params);
    }
}
