package performa.form;

import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import oneit.business.content.Article;
import oneit.components.ParticipantInitialisationContext;
import oneit.email.ConfigurableArticleTemplateEmailer;
import oneit.email.ConfigurableEmailerException;
import oneit.logging.*;
import oneit.net.LoopbackHTTP;
import oneit.objstore.ObjectTransaction;
import oneit.objstore.StorageException;
import oneit.objstore.parser.BusinessObjectParser;
import oneit.security.SecUser;
import oneit.servlets.forms.*;
import oneit.servlets.process.*;
import oneit.utils.*;
import performa.orm.*;
import performa.orm.types.RoleType;
import performa.utils.Utils;
import performa.utils.WebUtils;
 

public class SendVerificationMailFP extends SaveFP
{
    private static final LoggingArea  LOG                 =   LoggingArea.createLoggingArea("SendVerificationLink");
    protected ConfigurableArticleTemplateEmailer  emailer;

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

        Debug.assertion(company != null || job!=null, "BO not avaialble");
        
        if(company!=null)
        {
            CompanyUser companyUser =   company.getAddedByUser();
            SecUser     secUser     =   companyUser.getUser();
            
            BusinessObjectParser.assertFieldCondition(!Utils.isCompanyUserEmailFound(process.getTransaction(), secUser.getEmail()), secUser, SecUser.FIELD_Email, "emailExists", exceptions, true, request);
        }
        else
        {
            BusinessObjectParser.assertFieldCondition(!job.isEmailFound(), job, Job.FIELD_Email, "emailExists", 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();
        Job                 job         =   (Job) request.getAttribute("Job");
        Company             company     =   (Company) request.getAttribute("Company");
        
        if(company!=null)
        {
            CompanyUser companyUser         =   company.getAddedByUser();
            SecUser     secUser             =   companyUser.getUser();
            SecUser     availableSecUser    =   SecUser.searchNAME(objTran, secUser.getEmail());
            
            LogMgr.log(LOG, LogLevel.PROCESSING1, "Started to send varification email.", companyUser);
                            
            if(availableSecUser!=null)
            {
                if(availableSecUser.getExtension(CompanyUser.REFERENCE_CompanyUser)!=null)
                {
                    Debug.assertion(false, "user available", availableSecUser);
                }
                else
                {
                    LogMgr.log(LOG, LogLevel.PROCESSING1, "SecUser available", availableSecUser);

                    availableSecUser.addToExtensions(companyUser);

                    //remove new sec user obj
                    secUser.removeFromExtensions(companyUser);
                    secUser.delete();
                }
            }
            else
            {

                secUser.setUserName(secUser.getEmail().toLowerCase());
                secUser.setAttribute("md5:" + SecUser.FIELD_Password, CompanyUser.DEFAULT_PASSWORD);
                secUser.addRole(Utils.getRole(Utils.ROLE_CLIENT, objTran));
                
                LogMgr.log(LOG, LogLevel.PROCESSING1, "New user created :: ", secUser);
            }
            
            //set default to admin
            companyUser.setRole(RoleType.ADMIN);

            Utils.sendVerificationMail(companyUser, request, emailer, SendVerificationMailFP.class.getName());

            LogMgr.log(LOG, LogLevel.PROCESSING1, "End of sending varification email.", companyUser);
        }
        else
        {
            String      email   =   job.getEmail();

            Debug.assertion(email != null, "Email not avaialble");
            
            email   =   email.toLowerCase();

            LogMgr.log(LOG, LogLevel.PROCESSING1, "Started to send varification email.", job , email);

            SecUser     secUser =   SecUser.searchNAME(objTran, email);
            
            if(secUser!=null)
            {
                Debug.assertion(secUser.getExtension(Candidate.REFERENCE_Candidate)==null, "user available", email, secUser);
            }

            LogMgr.log(LOG, LogLevel.PROCESSING1, "Inside SendVerificationMailFP for send account verification mail for ", email);
            
            
            if(secUser==null)
            {
                secUser =   SecUser.createSecUser(objTran);

                secUser.setUserName(email);
                secUser.setAttribute("md5:" + SecUser.FIELD_Password, CompanyUser.DEFAULT_PASSWORD);
                secUser.addRole(Utils.getRole(Utils.ROLE_APPLICANT, objTran));
            }
            
            Candidate   candidate   =   secUser.getExtensionOrCreate(Candidate.REFERENCE_Candidate);
            
            LogMgr.log(LOG, LogLevel.PROCESSING1, "New user created :: ", secUser);

            sendVerificationMail(candidate, job, request);

            request.setAttribute("nextPage", request.getAttribute("nextPage") + "&JobID=" + job.getID());
        }

        return super.processForm(process, submission, params);
    }
    
        
    @Override
    public void init(ParticipantInitialisationContext context) throws InitialisationException
    {
        super.init(context);
        
        emailer = (ConfigurableArticleTemplateEmailer) (context.getSingleChild("AccountVerificationEmailer"));
    }
    
    
    private void sendVerificationMail(Candidate candidate, Job job, HttpServletRequest request) throws BusinessException
    {
        if(!candidate.isTrue(candidate.getIsAccountVerified()))
        {
            try
            {
                LogMgr.log(LOG, LogLevel.PROCESSING1, "Sending verification mail from  SendVerificationMailFP to :: ", candidate);

                Article         verificationArticle =   WebUtils.getArticleByShortCut(candidate.getTransaction(), WebUtils.APPLICANT_ACCOUNT_VERIFICATION);
                RandomStringGen random              =   new RandomStringGen();

                //set verification key and send mail time
                candidate.setVerificationKey(random.generateAlphaNum(6));
                candidate.setVerificationMailSendDate(new Date());

                String          link                =   LoopbackHTTP.getRemoteAccessURL(request) 
                                                            + verificationArticle.getLink(request, CollectionUtils.EMPTY_MAP, "/") 
                                                            + "?id=" + job.getID() 
                                                            + "&key=" + job.getRandomKey() 
                                                            + "&aid=" + candidate.getID()
                                                            + "&pin=" + candidate.getVerificationKey();
                Map             defaultParams       =   CollectionUtils.mapEntry("link", link).toMap(); 
                ObjectTransform transform           =   Utils.createCompoundTransform(defaultParams, candidate);

                Utils.sendMail(emailer, transform, new String[]{candidate.getUser().getUserName()}, null, candidate);

                LogMgr.log(LOG, LogLevel.PROCESSING1, "Sent verification mail successfully from " + SendVerificationMailFP.class + " to :: ", candidate);
            }
            catch (ConfigurableEmailerException ex)
            {
                LogMgr.log(LOG, LogLevel.SYSTEMERROR1, ex, "Error occured while sending mail for Candidate :: " + candidate);

                throw new BusinessException("We are unable to send mail. Please try again or contact Talentology for more details.");
            }
        }
        else
        {
            LogMgr.log(LOG, LogLevel.PROCESSING1, "Call from " + SendVerificationMailFP.class + ". Account is already verified  for candidate :: ", candidate);
        }
    }
}