/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.brooklyn.rest.security.provider;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Supplier;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.brooklyn.api.mgmt.ManagementContext;
import org.apache.brooklyn.config.StringConfigMap;
import org.apache.brooklyn.core.internal.BrooklynProperties;
import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
import org.apache.brooklyn.rest.BrooklynWebConfig;
import org.apache.brooklyn.util.core.ClassLoaderUtils;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DelegatingSecurityProvider implements SecurityProvider {

    private static final Logger log = LoggerFactory.getLogger(DelegatingSecurityProvider.class);
    protected final ManagementContext mgmt;

    public DelegatingSecurityProvider(ManagementContext mgmt) {
        this.mgmt = mgmt;
    }
    
    private SecurityProvider delegate;

    public synchronized SecurityProvider getDelegate() {
        if (delegate == null) {
            delegate = loadDelegate();
        }
        return delegate;
    }

    @SuppressWarnings("unchecked")
    private synchronized SecurityProvider loadDelegate() {
        StringConfigMap brooklynProperties = mgmt.getConfig();

        SecurityProvider presetDelegate = brooklynProperties.getConfig(BrooklynWebConfig.SECURITY_PROVIDER_INSTANCE);
        if (presetDelegate!=null) {
            log.trace("Brooklyn security: using pre-set security provider {}", presetDelegate);
            return presetDelegate;
        }

        String className = brooklynProperties.getConfig(BrooklynWebConfig.SECURITY_PROVIDER_CLASSNAME);

        if (delegate != null && BrooklynWebConfig.hasNoSecurityOptions(mgmt.getConfig())) {
            log.debug("Brooklyn security: {} refusing to change from {}: No security provider set in reloaded properties.",
                    this, delegate);
            return delegate;
        }

        try {
            String bundle = brooklynProperties.getConfig(BrooklynWebConfig.SECURITY_PROVIDER_BUNDLE);
            // use synch block to prevent multiple instances and messages from loading
            synchronized (DelegatingSecurityProvider.class) {
                // try again with preset delegate
                presetDelegate = brooklynProperties.getConfig(BrooklynWebConfig.SECURITY_PROVIDER_INSTANCE);
                if (presetDelegate!=null) {
                    log.trace("Brooklyn security: using pre-set security provider, found late - {}", presetDelegate);
                    return presetDelegate;
                }

                if (bundle != null) {
                    String bundleVersion = brooklynProperties.getConfig(BrooklynWebConfig.SECURITY_PROVIDER_BUNDLE_VERSION);
                    log.info("Brooklyn security: using security provider " + className + " from " + bundle + ":" + bundleVersion);
                    BundleContext bundleContext = ((ManagementContextInternal) mgmt).getOsgiManager().get().getFramework().getBundleContext();
                    delegate = loadProviderFromBundle(mgmt, bundleContext, bundle, bundleVersion, className);
                    saveDelegate();
                } else {
                    log.info("Brooklyn security: using security provider " + className);
                    ClassLoaderUtils clu = new ClassLoaderUtils(this, mgmt);
                    Class<? extends SecurityProvider> clazz = (Class<? extends SecurityProvider>) clu.loadClass(className);
                    delegate = createSecurityProviderInstance(mgmt, clazz);
                    saveDelegate();
                }
            }
        } catch (Exception e) {
            log.warn("Brooklyn security: unable to instantiate security provider " + className + "; all logins are being disallowed", e);
            delegate = new BlackholeSecurityProvider();
        }
        return delegate;
    }

    private void saveDelegate() {
        // Deprecated in 0.11.0. Add to release notes and remove in next release.
        ((BrooklynProperties)mgmt.getConfig()).put(BrooklynWebConfig.SECURITY_PROVIDER_INSTANCE, delegate);
        mgmt.getScratchpad().put(BrooklynWebConfig.SECURITY_PROVIDER_INSTANCE, delegate);
    }

    public static SecurityProvider loadProviderFromBundle(
        ManagementContext mgmt, BundleContext bundleContext,
        String symbolicName, String version, String className) {
        try {
            Collection<Bundle> bundles = getMatchingBundles(bundleContext, symbolicName, version);
            if (bundles.isEmpty()) {
                throw new IllegalStateException("No bundle " + symbolicName + ":" + version + " found");
            } else if (bundles.size() > 1) {
                log.warn("Brooklyn security: found multiple bundles matching symbolicName " + symbolicName + " and version " + version +
                    " while trying to load security provider " + className + ". Will use first one that loads the class successfully.");
            }
            SecurityProvider p = tryLoadClass(mgmt, className, bundles);
            if (p == null) {
                throw new ClassNotFoundException("Unable to load class " + className + " from bundle " + symbolicName + ":" + version);
            }
            return p;
        } catch (Exception e) {
            Exceptions.propagateIfFatal(e);
            throw new IllegalStateException("Can not load or create security provider " + className + " for bundle " + symbolicName + ":" + version, e);
        }
    }

    private static SecurityProvider tryLoadClass(ManagementContext mgmt, String className, Collection<Bundle> bundles)
        throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        for (Bundle b : bundles) {
            try {
                @SuppressWarnings("unchecked")
                Class<? extends SecurityProvider> securityProviderType = (Class<? extends SecurityProvider>) b.loadClass(className);
                return DelegatingSecurityProvider.createSecurityProviderInstance(mgmt, securityProviderType);
            } catch (ClassNotFoundException e) {
            }
        }
        return null;
    }

    private static Collection<Bundle> getMatchingBundles(BundleContext bundleContext, final String symbolicName, final String version) {
        Collection<Bundle> bundles = new ArrayList<>();
        for (Bundle b : bundleContext.getBundles()) {
            if (b.getSymbolicName().equals(symbolicName) &&
                (version == null || b.getVersion().toString().equals(version))) {
                bundles.add(b);
            }
        }
        return bundles;
    }

    public static SecurityProvider createSecurityProviderInstance(ManagementContext mgmt,
            Class<? extends SecurityProvider> clazz) throws NoSuchMethodException, InstantiationException,
                    IllegalAccessException, InvocationTargetException {
        Constructor<? extends SecurityProvider> constructor = null;
        Object delegateO;
        try {
            constructor = clazz.getConstructor(ManagementContext.class);
        } catch (NoSuchMethodException e) {
            // ignore
        }
        if (constructor!=null) {
            delegateO = constructor.newInstance(mgmt);
        } else {
            try {
                constructor = clazz.getConstructor();
            } catch (NoSuchMethodException e) {
                // ignore
            }
            if (constructor!=null) {
                delegateO = constructor.newInstance();
            } else {
                throw new NoSuchMethodException("Security provider "+clazz+" does not have required no-arg or 1-arg (mgmt) constructor");
            }
        }
        
        if (!(delegateO instanceof SecurityProvider)) {
            // if classloaders get mangled it will be a different CL's SecurityProvider
            throw new ClassCastException("Delegate is either not a security provider or has an incompatible classloader: "+delegateO);
        }
        return (SecurityProvider) delegateO;
    }

    @Override
    public boolean isAuthenticated(HttpSession session) {
        return getDelegate().isAuthenticated(session);
    }

    @Override
    public boolean authenticate(HttpServletRequest request, Supplier<HttpSession> sessionSupplierOnSuccess, String user, String pass) throws SecurityProviderDeniedAuthentication {
        boolean authenticated = getDelegate().authenticate(request, sessionSupplierOnSuccess, user, pass);
        if (log.isTraceEnabled() && authenticated) {
            log.trace("User {} authenticated with provider {}", user, getDelegate());
        } else if (!authenticated && log.isDebugEnabled()) {
            log.debug("Failed authentication for user {} with provider {}", user, getDelegate());
        }
        return authenticated;
    }

    @Override
    public boolean logout(HttpSession session) { 
        return getDelegate().logout(session);
    }

    @Override
    public boolean requiresUserPass() {
        return getDelegate().requiresUserPass();
    }

    @Override
    public String toString() {
        return super.toString()+"["+getDelegate()+"]";
    }
    
}
