/*******************************************************************************
 * Copyright (c) 2010-2016 SAP AG and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     SAP AG - initial API and implementation
 *******************************************************************************/
package org.eclipse.skalli.core.user.ldap;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.SizeLimitExceededException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.LdapContext;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.eclipse.skalli.commons.CollectionUtils;
import org.eclipse.skalli.core.cache.Cache;
import org.eclipse.skalli.core.cache.GroundhogCache;
import org.eclipse.skalli.core.user.NormalizeUtil;
import org.eclipse.skalli.model.User;
import org.eclipse.skalli.services.configuration.ConfigurationService;
import org.eclipse.skalli.services.configuration.Configurations;
import org.eclipse.skalli.services.configuration.EventConfigUpdate;
import org.eclipse.skalli.services.event.EventListener;
import org.eclipse.skalli.services.event.EventService;
import org.eclipse.skalli.services.user.EventUserUpdate;
import org.eclipse.skalli.services.user.UserService;
import org.eclipse.skalli.services.user.ldap.LdapContextProvider;
import org.osgi.service.component.ComponentConstants;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Implementation of {@link UserService} accessing an LDAP server.
 */
public class LDAPUserComponent implements UserService, EventListener<EventConfigUpdate> {

    private static final Logger LOG = LoggerFactory.getLogger(LDAPUserComponent.class);

    private static final String DEFAULT_POOL_PROTOCOLS = "plain ssl"; //$NON-NLS-1$
    private static final int DEFAULT_POOL_MAXSIZE = 5;
    private static final long DEFAULT_POOL_TIMEOUT = 10000L;
    private static final int DEFAULT_CACHE_SIZE = 100;

    private static final String CONNECT_POOL_PROTOCOLS = "com.sun.jndi.ldap.connect.pool.protocol"; //$NON-NLS-1$
    private static final String CONNECT_POOL_DEBUG = "com.sun.jndi.ldap.connect.pool.debug"; //$NON-NLS-1$
    private static final String CONNECT_POOL_MAXSIZE = "com.sun.jndi.ldap.connect.pool.maxsize"; //$NON-NLS-1$
    private static final String CONNECT_POOL_TIMEOUT = "com.sun.jndi.ldap.connect.pool.timeout"; //$NON-NLS-1$

    private ConcurrentHashMap<String,LdapContextProvider> ctxProviders =
            new ConcurrentHashMap<String, LdapContextProvider>();

    private LdapContextProvider ctxProvider;
    private String destination;
    private String baseDN;
    private LDAPSubDNs subDNs;
    private String searchScope;
    private EventService eventService;

    private Cache<String, User> cache;

    protected void activate(ComponentContext context) {
        // define properties for the LDAP connection pool globally, but let the individual context providers
        // decide whether to use the connection pool or not; note, for some weird reason the pool properties
        // are system properties and cannot be set per context
        System.setProperty(CONNECT_POOL_PROTOCOLS, DEFAULT_POOL_PROTOCOLS);
        System.setProperty(CONNECT_POOL_MAXSIZE, Integer.toString(DEFAULT_POOL_MAXSIZE));
        System.setProperty(CONNECT_POOL_TIMEOUT, Long.toString(DEFAULT_POOL_TIMEOUT));
        if (LOG.isDebugEnabled()) {
            System.setProperty(CONNECT_POOL_DEBUG, "fine"); //$NON-NLS-1$
        }

        LOG.info(MessageFormat.format("[UserService][LDAP] {0} : activated", //$NON-NLS-1$
                (String) context.getProperties().get(ComponentConstants.COMPONENT_NAME)));
        initialize();
    }

    protected void deactivate(ComponentContext context) {
        LOG.info(MessageFormat.format("[UserService][LDAP] {0} : deactivated", //$NON-NLS-1$
                (String) context.getProperties().get(ComponentConstants.COMPONENT_NAME)));
    }

    protected void bindEventService(EventService eventService) {
        eventService.registerListener(EventConfigUpdate.class, this);
        this.eventService = eventService;
    }

    protected void unbindEventService(EventService eventService) {
        eventService.unregisterListener(EventConfigUpdate.class, this);
        this.eventService = null;
    }

    protected void bindConfigurationService(ConfigurationService configurationService) {
        initialize();
    }

    protected void unbindConfigurationService(ConfigurationService configurationService) {
    }

    protected void bindLdapContextProvider(LdapContextProvider ctxProvider) {
        ctxProviders.put(ctxProvider.getId(), ctxProvider);
        initialize();
    }

    protected void unbindLdapContextProvider(LdapContextProvider ctxProvider) {
        ctxProviders.remove(ctxProvider.getId());
    }

    protected synchronized void initialize() {
        int cacheSize = DEFAULT_CACHE_SIZE;
        LDAPConfig ldapConfig = Configurations.getConfiguration(LDAPConfig.class);
        if (ldapConfig != null) {
            String providerId = StringUtils.isNotBlank(ldapConfig.getProviderId())
                    ? ldapConfig.getProviderId()
                    : "default"; //$NON-NLS-1$
            ctxProvider = ctxProviders.get(providerId);
            destination = ldapConfig.getDestination();
            baseDN = ldapConfig.getBaseDN();
            subDNs = ldapConfig.getLDAPSubDNs();
            searchScope = ldapConfig.getSearchScope();
            cacheSize = NumberUtils.toInt(ldapConfig.getCacheSize(), DEFAULT_CACHE_SIZE);
        }
        cache = new GroundhogCache<String, User>(cacheSize, cache);
    }

    @Override
    public String getType() {
        return "ldap"; //$NON-NLS-1$
    }

    @Override
    public synchronized List<User> findUser(String searchText) {
        if (StringUtils.isBlank(searchText)) {
            return Collections.emptyList();
        }
        if (ctxProvider == null) {
            return Collections.emptyList();
        }
        List<User> users = searchUserByName(searchText);
        for (User user : users) {
            if (user != null) {
                addUserToCache(user);
            }
        }
        return users;
    }

    /**
     * Adds or updates the given user within the cache class data member.
     * Also fires an event so other user cache instances can be updated (See UserContainer class).
     * @param user
     */
    private void addUserToCache(User user){
        cache.put(user.getUserId().toLowerCase(Locale.ENGLISH), user);

        if (this.eventService != null) {
            this.eventService.fireEvent(new EventUserUpdate(user));
        }
    }


    @Override
    public synchronized User getUserById(String userId) {
        if (StringUtils.isBlank(userId)) {
            return null;
        }
        String lowerCaseUserId = userId.toLowerCase(Locale.ENGLISH);
        User user = cache.get(lowerCaseUserId);
        if (user == null) {
            if (ctxProvider == null) {
                return null;
            }
            user = searchUserById(userId);
            if (user != null) {
                addUserToCache(user);
            }
        }
        return user;
    }

    @Override
    public synchronized List<User> getUsers() {
        return new LinkedList<User>(cache.values());
    }

    @Override
    public synchronized Set<User> getUsersById(Set<String> userIds) {
        if (userIds == null || userIds.isEmpty()) {
            return Collections.emptySet();
        }
        Set<User> users = new HashSet<User>(userIds.size());
        Set<String> notFoundInCache = new HashSet<String>();
        for (String userId : userIds) {
            if (StringUtils.isBlank(userId)) {
                continue;
            }
            String lowerCaseUserId = userId.toLowerCase(Locale.ENGLISH);
            User user = cache.get(lowerCaseUserId);
            if (user != null) {
                users.add(user);
            } else {
                notFoundInCache.add(lowerCaseUserId);
            }
        }
        if (notFoundInCache.size() > 0) {
            if (ctxProvider == null) {
                return users;
            }
            Set<User> ldapUsers = searchUsersByIds(notFoundInCache);
            for (User user : ldapUsers) {
                if (user != null) {
                    String userId = user.getUserId();
                    if (StringUtils.isNotBlank(userId)) {
                        users.add(user);
                        addUserToCache(user);
                    }
                }
            }
        }
        return users;
    }

    @Override
    public synchronized void onEvent(EventConfigUpdate event) {
        if (LDAPConfig.class.equals(event.getConfigClass())) {
            initialize();
        }
    }

    private User searchUserById(String userId) {
        LdapContext ctx = null;
        try {
            ctx = ctxProvider.getLdapContext(destination);
            return searchUserById(ctx, userId);
        } catch (Exception e) {
            LOG.debug(MessageFormat.format("Failed to retrieve user ''{0}''", userId), e);
            return new User(userId);
        } finally {
            closeQuietly(ctx);
        }
    }

    private Set<User> searchUsersByIds(Set<String> userIds) {
        LdapContext ctx = null;
        try {
            if (ctxProvider == null) {
                return Collections.emptySet();
            }
            ctx = ctxProvider.getLdapContext(destination);
            Set<User> ret = new HashSet<User>();
            for (String userId : userIds) {
                ret.add(searchUserById(ctx, userId));
            }
            return ret;
        } catch (Exception e) {
            LOG.debug(MessageFormat.format("Failed to retrieve users {0}",
                    CollectionUtils.toString(userIds, ',')), e);
            return Collections.emptySet();
        } finally {
            closeQuietly(ctx);
        }
    }

    private List<User> searchUserByName(String name) {
        LdapContext ctx = null;
        try {
            if (ctxProvider == null) {
                return Collections.emptyList();
            }
            ctx = ctxProvider.getLdapContext(destination);
            return searchUserByName(ctx, name);
        } catch (Exception e) {
            LOG.debug(MessageFormat.format("Failed to search user ''{0}''", name), e);
            return Collections.emptyList();
        } finally {
            closeQuietly(ctx);
        }
    }

    private User searchUserById(LdapContext ctx, String userId) throws NamingException {
        SearchControls sc = getSearchControls();
        ArrayList<SearchResult> results = null;
        results = ctxSearch(MessageFormat.format("(&(objectClass=user)(sAMAccountName={0}))", userId), sc, ctx);//$NON-NLS-1$
        for (SearchResult entry : results) {
            User user = processEntry(entry);
            if (user != null) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug(MessageFormat.format("Success reading from LDAP: {0}, {1} <{2}>", //$NON-NLS-1$
                            user.getUserId(), user.getDisplayName(), user.getEmail()));
                }
                return user;
            }
        }

        return new User(userId);
    }

    private List<User> searchUserByName(LdapContext ctx, String name) throws NamingException {
        List<User> ret = new ArrayList<User>(0);
        try {
            boolean somethingAdded = false;
            SearchControls sc = getSearchControls();
            String[] parts = StringUtils.split(NormalizeUtil.normalize(name), " ,"); //$NON-NLS-1$

            if (parts.length == 1) {
                somethingAdded = search(parts[0], ret, ctx, sc);
            } else if (parts.length > 1) {

                // givenname surname ('Michael Ochmann'), or surname givenname('Ochmann, Michael')
                ArrayList<SearchResult> results = null;

                results = ctxSearch(MessageFormat.format("(&(objectClass=user)(givenName={0}*)(sn={1}*))", //$NON-NLS-1$
                        parts[0], parts[1]), sc, ctx);
                somethingAdded |= addLDAPSearchResult(ret, results);

                results = ctxSearch(MessageFormat.format("(&(objectClass=user)(sn={0}*)(givenName={1}*))", //$NON-NLS-1$
                        parts[0], parts[1]), sc, ctx);
                somethingAdded |= addLDAPSearchResult(ret, results);

                // givenname initial surname, e.g. 'Michael R. Ochmann'
                if (parts.length > 2) {

                    results = ctxSearch(MessageFormat.format("(&(objectClass=user)(givenName={0}*)(sn={1}*))", //$NON-NLS-1$
                            parts[0], parts[2]), sc, ctx);
                    somethingAdded |= addLDAPSearchResult(ret, results);

                    results = ctxSearch(MessageFormat.format("(&(objectClass=user)(sn={0}*)(givenName={1}*))", //$NON-NLS-1$
                            parts[0], parts[2]), sc, ctx);
                    somethingAdded |= addLDAPSearchResult(ret, results);

                }
                if (!somethingAdded) {
                    // try to match each part individually
                    for (int i = 0; i < parts.length; ++i) {
                        somethingAdded = search(parts[i], ret, ctx, sc);
                    }
                }
            }
        } catch (SizeLimitExceededException e) {
            // 1000 is good enough at the moment for this use case...
            LOG.warn(MessageFormat.format("LDAP query size limit exceeded while searching for ''{0}''", name), e);
        }
        return ret;
    }

    private boolean search(String s, List<User> ret, LdapContext ctx, SearchControls sc) throws NamingException {
        // try a match with surname*
        boolean somethingAdded = false;
        ArrayList<SearchResult> results = null;

        results = ctxSearch(MessageFormat.format("(&(objectClass=user)(|(sn={0}*)(givenName={1}*)))", s, s), sc, //$NON-NLS-1$
                    ctx);
        somethingAdded = addLDAPSearchResult(ret, results);

        if (!somethingAdded) {
            // try a match with the account name and mail address
            results = ctxSearch(MessageFormat.format("(&(objectClass=user)(sAMAccountName={0}*))", s), sc, ctx); //$NON-NLS-1$
            somethingAdded |= addLDAPSearchResult(ret, results);
        }
        if (!somethingAdded) {
            // try to match surname~= or givenname~=
            results = ctxSearch(MessageFormat.format("(&(objectClass=user)(|(sn~={0})(givenName~={1})))", s, s), //$NON-NLS-1$
                    sc, ctx);
            somethingAdded |= addLDAPSearchResult(ret, results);
        }
        if (!somethingAdded) {
            results = ctxSearch(MessageFormat.format("(&(objectClass=user)(mail={0}*))", s), sc, ctx); //$NON-NLS-1$
            somethingAdded |= addLDAPSearchResult(ret, results);
        }

        return somethingAdded;
    }

    private ArrayList<SearchResult> ctxSearch(String query, SearchControls sc, LdapContext ctx)
            throws NamingException {
        ArrayList<SearchResult> result = new ArrayList<SearchResult>();
        if (subDNs != null && subDNs.size() > 0){
            for (String subDN : subDNs.getList()) {
                addSearchResult(result, subDN + "," + baseDN, query, sc, ctx);
            }
        }
        else {
            //in case subDNs are not set, we search only using baseDN
            addSearchResult(result, baseDN, query, sc, ctx);
        }
        return result;
    }

    private void addSearchResult(List<SearchResult> result, String dn, String query, SearchControls sc, LdapContext ctx)
            throws NamingException {
        NamingEnumeration<SearchResult> resultQuery = ctx.search(dn, query, sc); //$NON-NLS-1$
        try {
            if (resultQuery != null && resultQuery.hasMore()) {
                result.addAll(Collections.list(resultQuery));
            }
        }
        finally {
            closeQuietly(resultQuery);
            resultQuery = null;
        }
    }

    // Iterate over a batch of search results sent by the server
    private boolean addLDAPSearchResult(List<User> users, ArrayList<SearchResult> results)
            throws NamingException {
        boolean somethingAdded = false;
        for (SearchResult entry : results) {
            User user = processEntry(entry);
            if (user != null) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug(MessageFormat.format("Success reading from LDAP: {0}, {1} <{2}>",
                            user.getUserId(), user.getDisplayName(), user.getEmail()));
                }
                users.add(user);
                somethingAdded = true;
            }
        }
        return somethingAdded;
    }

    private String getStringValue(Attributes attributes, LDAPAttributeNames attributeName)
            throws NamingException {
        String ret = null;
        Attribute attribute = attributes.get(attributeName.getLdapKey());
        if (attribute != null) {
            for (int i = 0; i < attribute.size(); i++) {
                ret = (String) attribute.get(i);
            }
        }
        return ret;
    }

    private User processEntry(SearchResult entry) throws NamingException {
        User user = new User();
        Attributes attrs = entry.getAttributes();
        Attribute attrBits = attrs.get(LDAPAttributeNames.BITS.getLdapKey());
        if (attrBits != null) {
            long lng = Long.parseLong(attrBits.get(0).toString());
            long secondBit = lng & 2; // get bit 2
            if (secondBit != 0) {
                // User not enabled
                return null;
            }
        }
        user.setUserId(StringUtils.lowerCase(getStringValue(attrs, LDAPAttributeNames.USERID)));
        user.setFirstname(getStringValue(attrs, LDAPAttributeNames.FIRSTNAME));
        user.setLastname(getStringValue(attrs, LDAPAttributeNames.LASTNAME));
        user.setEmail(getStringValue(attrs, LDAPAttributeNames.EMAIL));
        user.setTelephone(getStringValue(attrs, LDAPAttributeNames.TELEPHONE));
        user.setMobile(getStringValue(attrs, LDAPAttributeNames.MOBILE));
        user.setRoom(getStringValue(attrs, LDAPAttributeNames.ROOM));
        user.setLocation(getStringValue(attrs, LDAPAttributeNames.LOCATION));
        user.setDepartment(getStringValue(attrs, LDAPAttributeNames.DEPARTMENT));
        user.setCompany(getStringValue(attrs, LDAPAttributeNames.COMPANY));
        user.setSip(getStringValue(attrs, LDAPAttributeNames.SIP));
        return user;
    }

    @SuppressWarnings("nls")
    private SearchControls getSearchControls() {
        SearchControls sc = new SearchControls();
        if ("base".equalsIgnoreCase(searchScope)) {
            sc.setSearchScope(SearchControls.OBJECT_SCOPE);
        } else if ("onelevel".equalsIgnoreCase(searchScope)) {
            sc.setSearchScope(SearchControls.ONELEVEL_SCOPE);
        } else if ("subtree".equalsIgnoreCase(searchScope)) {
            sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
        }
        sc.setReturningAttributes(LDAPAttributeNames.getAll());
        return sc;
    }

    private void closeQuietly(LdapContext ctx) {
        if (ctx != null) {
            try {
                ctx.close();
            } catch (NamingException e) {
                LOG.error("Failed to close LDAP connection", e);
            }
        }
    }

    private void closeQuietly(NamingEnumeration<?> result) {
        if (result != null) {
            try {
                result.close();
            } catch (NamingException e) {
                LOG.error("Failed to close LDAP result set", e);
            }
        }
    }
}
