package pwc.taxtech.atms.security;

import java.util.Hashtable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import pwc.taxtech.atms.common.CommonConstants;

@Component
public class LdapAuthenticationProviderImpl implements LdapAuthenticationProvider {
    private static final Logger logger = LoggerFactory.getLogger(LdapAuthenticationProviderImpl.class);

    /*
     * (non-Javadoc)
     * 
     * @see
     * pwc.taxtech.atms.security.LdapAuthenticationProvider#authenticate(java.lang.
     * String, java.lang.String)
     */
    @Override
    public boolean authenticate(final String username, final String password) {
        String ldapUrl = fetchDefaultDlapUrl();
        String domain = fetchDefaultDomain();
        return authenticate(username, password, ldapUrl, domain);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * pwc.taxtech.atms.security.LdapAuthenticationProvider#fetchDefaultDomain()
     */
    @Override
    public String fetchDefaultDomain() {
        return CommonConstants.LDAP_DOMAIN;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * pwc.taxtech.atms.security.LdapAuthenticationProvider#fetchDefaultDlapUrl()
     */
    @Override
    public String fetchDefaultDlapUrl() {
        return CommonConstants.LDAPUri;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * pwc.taxtech.atms.security.LdapAuthenticationProvider#authenticate(java.lang.
     * String, java.lang.String, java.lang.String, java.lang.String)
     */
    @Override
    public boolean authenticate(final String username, final String password, final String ldapUrl,
            final String domain) {
        Hashtable<String, String> env = buildParam(username, password, ldapUrl, domain);
        /*
         * 进行LDAP连接
         */
        javax.naming.ldap.LdapContext ctx = null;
        boolean result = false;
        // initialize the ldap context
        try {
            ctx = new javax.naming.ldap.InitialLdapContext(env, null);
            result = true;
        } catch (Exception ex) {
            logger.warn("catch Exception:" + ex);
        } finally {
            safeClose(ctx);
        }
        return result;
    }

    public Hashtable<String, String> buildParam(final String username, final String password, final String ldapUrl,
            final String domain) {
        Assert.hasText(username, "empty username");
        Assert.hasText(password, "empty password");
        Assert.hasText(ldapUrl, "empty ldapUrl");
        Assert.hasText(domain, "empty domain");
        logger.debug("auth start");
        // 设置相关常量
        String initialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory";
        // String ad4ProviderURL = "ldap://nam.ad.pwcinternal.com";
        String ad4ProviderURL = ldapUrl;
        logger.debug("ad server url:{}", ad4ProviderURL);
        String securityAuthentication = "simple";
        String usernameWithDomain = domain + "\\" + username;
        logger.debug("username:{}", usernameWithDomain);
        /*
         * 组织参数集合
         */
        Hashtable<String, String> env = new Hashtable<String, String>();
        // set the initializing information of the context
        env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
        // set the URL of ldap server
        env.put(javax.naming.Context.PROVIDER_URL, ad4ProviderURL);
        // set the authentication mode
        env.put(javax.naming.Context.SECURITY_AUTHENTICATION, securityAuthentication);
        // set user of AD
        env.put(javax.naming.Context.SECURITY_PRINCIPAL, usernameWithDomain);
        // set password of user
        env.put(javax.naming.Context.SECURITY_CREDENTIALS, password);
        return env;
    }

    private void safeClose(javax.naming.ldap.LdapContext ctx) {
        if (ctx != null) {
            try {
                ctx.close();
            } catch (Exception ex) {
                logger.error("Cannot close InitialLdapContext", ex.getMessage());
            }
        }
    }

}