package performa.form;

import java.util.*;
import javax.servlet.http.HttpServletRequest;
import oneit.business.content.Article;
import oneit.components.ParticipantInitialisationContext;
import oneit.email.ConfigurableEmailer;
import oneit.logging.*;
import oneit.net.LoopbackHTTP;
import oneit.objstore.*;
import oneit.objstore.parser.BusinessObjectParser;
import oneit.objstore.rdbms.filters.EqualsFilter;
import oneit.security.SecUser;
import oneit.servlets.forms.*;
import oneit.servlets.process.*;
import oneit.utils.*;
import performa.orm.*;
import performa.utils.*;


public class ForgotPasswordFP extends SaveFP
{
    private static final    LoggingArea     LOG                     =   LoggingArea.createLoggingArea("ForgotPasswordFP");
    protected       int                     DEFAULT_PASSWORD_LENGTH =   6;
    protected       ConfigurableEmailer     resetCodeEmailer;

    @Override 
    public SuccessfulResult processForm(ORMProcessState process, SubmissionDetails submission, Map params) throws BusinessException, StorageException
    {
        HttpServletRequest  request     =   submission.getRequest();
        ObjectTransaction   objTran     =   process.getTransaction();
        Job                 job         =   (Job) process.getAttribute("Job");
        CompanyUserNPO      tmpComUser  =   (CompanyUserNPO) request.getAttribute("CompanyUser");
        String              email       =   job != null ? job.getEmail() : (tmpComUser != null ? tmpComUser.getEmail() : null);
        Map                 emailParams =   null;

        Debug.assertion(StringUtils.subBlanks(email) != null, "Email not avaialble");
        
        email   =   StringUtils.trim(email);
        
        LogMgr.log(LOG, LogLevel.PROCESSING1, "Started to send pasword reset link email.", email);
                
        SecUser secUser =   SecUser.searchNAME (objTran, email);
        
        if(secUser == null)
        {
            SecUser[]   userSearch  =   SecUser.SearchByALL().andEmail(new EqualsFilter<>(email)).search(objTran);

            if(userSearch.length>0)
            {
                secUser =   userSearch[0];
            }
        }
        
        if(secUser != null)
        {
            LogMgr.log(LOG, LogLevel.PROCESSING1, "Inside ForgotPasswordFP for send reset pasword link mail to ", email);

            if(tmpComUser != null)
            {
                CompanyUser companyUser =   secUser.getExtension(CompanyUser.REFERENCE_CompanyUser);

                if(companyUser == null)
                {
                    throw new BusinessException("Sorry, you are not an authorised user to access admin portal.");
                }
                
                if(companyUser.getForgotPasswordKey() == null)
                {
                    String  resetCode   =   new RandomStringGen().generateHumanAlphaNum(DEFAULT_PASSWORD_LENGTH);
                    companyUser.setForgotPasswordKey(resetCode);
                }

                companyUser.setForgotPasswordMailSendDate(new Date());

                emailParams =   CollectionUtils.mapEntry("resetcode", companyUser.getForgotPasswordKey())
                                            .mapEntry("url", LoopbackHTTP.getRemoteAccessURL() + "/extensions/adminportal/reset_password.jsp"
                                                                + "?id=" + companyUser.getID() 
                                                                + "&key=" + companyUser.getForgotPasswordKey()).toMap();
            }
            else if(job != null)
            {
                Candidate   candidate   =   secUser.getExtension(Candidate.REFERENCE_Candidate);
                
                if(candidate == null)
                {
                    throw new BusinessException("Sorry, we don't recognize that email address.");
                }
                
                Article applyJobArticle =   WebUtils.getArticleByShortCut(objTran, WebUtils.APPLY_JOB);
                
                if(candidate.getForgotPasswordKey() == null)
                {
                    String resetCode = new RandomStringGen().generateHumanAlphaNum(DEFAULT_PASSWORD_LENGTH);
                    candidate.setForgotPasswordKey(resetCode);
                }

                candidate.setForgotPasswordMailSendDate(new Date());

                emailParams =   CollectionUtils.mapEntry("resetcode", candidate.getForgotPasswordKey())
                                                .mapEntry("url",  LoopbackHTTP.getRemoteAccessURL(request)
                                                                   + applyJobArticle.getLink(request, CollectionUtils.mapEntry("cms.rm", WebUtils.RESET_PASSWORD).toMap(), "/") 
                                                                    + "&id=" + candidate.getID() 
                                                                    + "&key=" + candidate.getForgotPasswordKey()
                                                                    + "&jid=" + job.getID()).toMap();
            }
            
            ObjectTransform transform   =   Utils.createCompoundTransform(emailParams, secUser);
            
            try
            {
                Utils.sendMail(resetCodeEmailer, transform, new String[]{email}, null, secUser);
                
                LogMgr.log(LOG, LogLevel.PROCESSING1, "Reset code email sent to :: ", email);
            }
            catch(Exception e)
            {
                LogMgr.log(LoggingArea.ALL, LogLevel.PROCESSING1, e, "Error while sending email");

                throw new BusinessException("Mail can not be sent. Please contact administrator.");
            }
        }
        else
        {
            throw new BusinessException("Sorry, we don't recognize that email address.");
        }
            
        return super.processForm(process, submission, params);
    }
    
        
    @Override
    public void init(ParticipantInitialisationContext context) throws InitialisationException
    {
        super.init(context);

        resetCodeEmailer = (ConfigurableEmailer)(context.getSingleChild("ResetCodeEmailer"));
    }

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

        if(job != null)
        {
            BusinessObjectParser.assertFieldCondition(StringUtils.subBlanks(job.getEmail()) != null, job, Job.FIELD_Email, "mandatory", exceptions, true, request);
        }
        else if(companyUser != null)
        {
            BusinessObjectParser.assertFieldCondition(StringUtils.subBlanks(companyUser.getEmail()) != null, companyUser, CompanyUserNPO.FIELD_Email, "mandatory", exceptions, true, request);
        }
    }
}