/*
 * 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.guacamole.extension;

import com.google.inject.Provides;
import com.google.inject.servlet.ServletModule;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.guacamole.auth.file.FileAuthenticationProvider;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleServerException;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.net.event.listener.Listener;
import org.apache.guacamole.properties.StringSetProperty;
import org.apache.guacamole.resource.Resource;
import org.apache.guacamole.resource.ResourceServlet;
import org.apache.guacamole.resource.SequenceResource;
import org.apache.guacamole.resource.WebApplicationResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A Guice Module which loads all extensions within the
 * GUACAMOLE_HOME/extensions directory, if any.
 */
public class ExtensionModule extends ServletModule {

    /**
     * Logger for this class.
     */
    private final Logger logger = LoggerFactory.getLogger(ExtensionModule.class);

    /**
     * The version strings of all Guacamole versions whose extensions are
     * compatible with this release.
     */
    private static final List<String> ALLOWED_GUACAMOLE_VERSIONS =
        Collections.unmodifiableList(Arrays.asList(
            "*",
            "1.0.0",
            "1.1.0",
            "1.2.0",
            "1.3.0",
            "1.4.0",
            "1.5.0",
            "1.5.1",
            "1.5.2",
            "1.5.3",
            "1.5.4"
        ));

    /**
     * The name of the directory within GUACAMOLE_HOME containing any .jars
     * which should be included in the classpath of all extensions.
     */
    private static final String LIB_DIRECTORY = "lib";

    /**
     * The name of the directory within GUACAMOLE_HOME containing all
     * extensions.
     */
    private static final String EXTENSIONS_DIRECTORY = "extensions";

    /**
     * The string that the filenames of all extensions must end with to be
     * recognized as extensions.
     */
    private static final String EXTENSION_SUFFIX = ".jar";

    /**
     * A comma-separated list of the identifiers of all authentication
     * providers whose internal failures should be tolerated during the
     * authentication process. If an authentication provider within this list
     * encounters an internal error during the authentication process, it will
     * simply be skipped, allowing other authentication providers to continue
     * trying to authenticate the user. Internal errors within authentication
     * providers that are not within this list will halt the authentication
     * process entirely.
     */
    public static final StringSetProperty SKIP_IF_UNAVAILABLE = new StringSetProperty() {

        @Override
        public String getName() {
            return "skip-if-unavailable";
        }

    };

    /**
     * A comma-separated list of the namespaces of all extensions that should
     * be loaded in a specific order. The special value "*" can be used in
     * lieu of a namespace to represent all extensions that are not listed. All
     * extensions explicitly listed will be sorted in the order given, while
     * all extensions not explicitly listed will be sorted by their filenames.
     */
    public static final ExtensionOrderProperty EXTENSION_PRIORITY = new ExtensionOrderProperty() {

        @Override
        public String getName() {
            return "extension-priority";
        }

    };

    /**
     * The Guacamole server environment.
     */
    private final Environment environment;

    /**
     * All currently-bound authentication providers, if any.
     */
    private final List<AuthenticationProvider> boundAuthenticationProviders =
            new ArrayList<AuthenticationProvider>();

    /**
     * All currently-bound authentication providers, if any.
     */
    private final List<Listener> boundListeners =
            new ArrayList<Listener>();

    /**
     * All temporary files that should be deleted upon application shutdown, in
     * reverse order of desired deletion. This will typically simply be the
     * order that each file was created.
     */
    private final List<File> temporaryFiles = new ArrayList<>();

    /**
     * Service for adding and retrieving language resources.
     */
    private final LanguageResourceService languageResourceService;

    /**
     * Service for adding and retrieving HTML patch resources.
     */
    private final PatchResourceService patchResourceService;
    
    /**
     * Returns the classloader that should be used as the parent classloader
     * for all extensions. If the GUACAMOLE_HOME/lib directory exists, this
     * will be a classloader that loads classes from within the .jar files in
     * that directory. Lacking the GUACAMOLE_HOME/lib directory, this will
     * simply be the classloader associated with the ExtensionModule class.
     *
     * @return
     *     The classloader that should be used as the parent classloader for
     *     all extensions.
     *
     * @throws GuacamoleException
     *     If an error occurs while retrieving the classloader.
     */
    private ClassLoader getParentClassLoader() throws GuacamoleException {

        // Retrieve lib directory
        File libDir = new File(environment.getGuacamoleHome(), LIB_DIRECTORY);

        // If lib directory does not exist, use default class loader
        if (!libDir.isDirectory())
            return ExtensionModule.class.getClassLoader();

        // Return classloader which loads classes from all .jars within the lib directory
        return DirectoryClassLoader.getInstance(libDir);

    }

    /**
     * Creates a module which loads all extensions within the
     * GUACAMOLE_HOME/extensions directory.
     *
     * @param environment
     *     The environment to use when configuring authentication.
     */
    public ExtensionModule(Environment environment) {
        this.environment = environment;
        this.languageResourceService = new LanguageResourceService(environment);
        this.patchResourceService = new PatchResourceService();
    }

    /**
     * Binds the given AuthenticationProvider class such that any service
     * requiring access to the AuthenticationProvider can obtain it via
     * injection, along with any other bound AuthenticationProviders.
     *
     * @param authenticationProvider
     *     The AuthenticationProvider class to bind.
     *
     * @param tolerateFailures
     *     The set of identifiers of all authentication providers whose
     *     internal failures should be tolerated during the authentication
     *     process. If the identifier of an authentication provider is within
     *     this set, errors during authentication will result in the
     *     authentication provider being ignored for that authentication
     *     attempt, with the authentication process proceeding as if that
     *     authentication provider were not present. By default, errors during
     *     authentication halt the authentication process entirely.
     */
    private void bindAuthenticationProvider(
            Class<? extends AuthenticationProvider> authenticationProvider,
            Set<String> tolerateFailures) {

        // Bind authentication provider
        logger.debug("[{}] Binding AuthenticationProvider \"{}\".",
                boundAuthenticationProviders.size(), authenticationProvider.getName());
        boundAuthenticationProviders.add(new AuthenticationProviderFacade(
                authenticationProvider, tolerateFailures));

    }

    /**
     * Binds each of the given AuthenticationProvider classes such that any
     * service requiring access to the AuthenticationProvider can obtain it via
     * injection.
     *
     * @param authProviders
     *     The AuthenticationProvider classes to bind.
     *
     * @param tolerateFailures
     *     The set of identifiers of all authentication providers whose
     *     internal failures should be tolerated during the authentication
     *     process. If the identifier of an authentication provider is within
     *     this set, errors during authentication will result in the
     *     authentication provider being ignored for that authentication
     *     attempt, with the authentication process proceeding as if that
     *     authentication provider were not present. By default, errors during
     *     authentication halt the authentication process entirely.
     */
    private void bindAuthenticationProviders(
            Collection<Class<AuthenticationProvider>> authProviders,
            Set<String> tolerateFailures) {

        // Bind each authentication provider within extension
        for (Class<AuthenticationProvider> authenticationProvider : authProviders)
            bindAuthenticationProvider(authenticationProvider, tolerateFailures);

    }

    /**
     * Returns a list of all currently-bound AuthenticationProvider instances.
     *
     * @return
     *     A List of all currently-bound AuthenticationProvider. The List is
     *     not modifiable.
     */
    @Provides
    public List<AuthenticationProvider> getAuthenticationProviders() {
        return Collections.unmodifiableList(boundAuthenticationProviders);
    }

    /**
     * Returns a list of all temporary files that should be deleted upon
     * application shutdown, in reverse order of desired deletion. This will
     * typically simply be the order that each file was created.
     *
     * @return
     *     A List of all temporary files that should be deleted upon
     *     application shutdown. The List is not modifiable.
     */
    @Provides
    public List<File> getTemporaryFiles() {
        return Collections.unmodifiableList(temporaryFiles);
    }
    
    /**
     * Binds the given provider class such that a listener is bound for each
     * listener interface implemented by the provider and such that all bound
     * listener instances can be obtained via injection.
     *
     * @param providerClass
     *     The listener class to bind.
     */
    private void bindListener(Class<?> providerClass) {

        logger.debug("[{}] Binding listener \"{}\".",
                boundListeners.size(), providerClass.getName());
        boundListeners.addAll(ListenerFactory.createListeners(providerClass));

    }

    /**
     * Binds each of the given Listener classes such that any
     * service requiring access to the Listener can obtain it via
     * injection.
     *
     * @param listeners
     *     The Listener classes to bind.
     */
    private void bindListeners(Collection<Class<?>> listeners) {

        // Bind each listener within extension
        for (Class<?> listener : listeners)
            bindListener(listener);
    }

    /**
     * Returns a list of all currently-bound Listener instances.
     *
     * @return
     *     A List of all currently-bound Listener instances. The List is
     *     not modifiable.
     */
    @Provides
    public List<Listener> getListeners() {
        return Collections.unmodifiableList(boundListeners);
    }

    /**
     * Serves each of the given resources as a language resource. Language
     * resources are served from within the "/translations" directory as JSON
     * files, where the name of each JSON file is the language key.
     *
     * @param resources
     *     A map of all language resources to serve, where the key of each
     *     entry in the language key from which the name of the JSON file will
     *     be derived.
     */
    private void serveLanguageResources(Map<String, Resource> resources) {

        // Add all resources to language resource service
        for (Map.Entry<String, Resource> translationResource : resources.entrySet()) {

            // Get path and resource from path/resource pair
            String path = translationResource.getKey();
            Resource resource = translationResource.getValue();

            // Derive key from path
            String languageKey = languageResourceService.getLanguageKey(path);
            if (languageKey == null) {
                logger.warn("Invalid language file name: \"{}\"", path);
                continue;
            }

            // Add language resource
            languageResourceService.addLanguageResource(languageKey, resource);

        }

    }

    /**
     * Serves each of the given resources under the given prefix. The path of
     * each resource relative to the prefix is the key of its entry within the
     * map.
     *
     * @param prefix
     *     The prefix under which each resource should be served.
     *
     * @param resources
     *     A map of all resources to serve, where the key of each entry in the
     *     map is the desired path of that resource relative to the prefix.
     */
    private void serveStaticResources(String prefix, Map<String, Resource> resources) {

        // Add all resources under given prefix
        for (Map.Entry<String, Resource> staticResource : resources.entrySet()) {

            // Get path and resource from path/resource pair
            String path = staticResource.getKey();
            Resource resource = staticResource.getValue();

            // Serve within namespace-derived path
            serve(prefix + path).with(new ResourceServlet(resource));

        }

    }

    /**
     * Returns whether the given version of Guacamole is compatible with this
     * version of Guacamole as far as extensions are concerned.
     *
     * @param guacamoleVersion
     *     The version of Guacamole the extension was built for.
     *
     * @return
     *     true if the given version of Guacamole is compatible with this
     *     version of Guacamole, false otherwise.
     */
    private boolean isCompatible(String guacamoleVersion) {
        return ALLOWED_GUACAMOLE_VERSIONS.contains(guacamoleVersion);
    }

    /**
     * Returns the set of identifiers of all authentication providers whose
     * internal failures should be tolerated during the authentication process.
     * If the identifier of an authentication provider is within this set,
     * errors during authentication will result in the authentication provider
     * being ignored for that authentication attempt, with the authentication
     * process proceeding as if that authentication provider were not present.
     * By default, errors during authentication halt the authentication process
     * entirely.
     *
     * @return
     *     The set of identifiers of all authentication providers whose
     *     internal failures should be tolerated during the authentication
     *     process.
     */
    private Set<String> getToleratedAuthenticationProviders() {

        // Parse list of auth providers whose internal failures should be
        // tolerated
        try {
            return environment.getProperty(SKIP_IF_UNAVAILABLE, Collections.<String>emptySet());
        }

        // Use empty set by default if property cannot be parsed
        catch (GuacamoleException e) {
            logger.warn("The list of authentication providers specified via the \"{}\" property could not be parsed: {}", SKIP_IF_UNAVAILABLE.getName(), e.getMessage());
            logger.debug("Unable to parse \"{}\" property.", SKIP_IF_UNAVAILABLE.getName(), e);
            return Collections.<String>emptySet();
        }

    }

    /**
     * Returns a comparator that sorts extensions by their desired load order,
     * as dictated by the "extension-priority" property and their filenames.
     *
     * @return
     *     A comparator that sorts extensions by their desired load order.
     */
    private Comparator<Extension> getExtensionLoadOrder() {

        // Parse desired sort order of extensions
        try {
            return environment.getProperty(EXTENSION_PRIORITY, ExtensionOrderProperty.DEFAULT_COMPARATOR);
        }

        // Sort by filename if the desired order cannot be read
        catch (GuacamoleException e) {
            logger.warn("The list of extensions specified via the \"{}\" property could not be parsed: {}", EXTENSION_PRIORITY.getName(), e.getMessage());
            logger.debug("Unable to parse \"{}\" property.", EXTENSION_PRIORITY.getName(), e);
            return ExtensionOrderProperty.DEFAULT_COMPARATOR;
        }

    }

    /**
     * Returns a list of all installed extensions in the order they should be
     * loaded. Extension load order is dictated by the "extension-priority"
     * property and by extension filename. Each extension within
     * GUACAMOLE_HOME/extensions is read and validated, but not fully loaded.
     * It is the responsibility of the caller to continue the load process with
     * the extensions in the returned list.
     *
     * @return
     *     A list of all installed extensions, ordered by load priority.
     */
    private List<Extension> getExtensions() {

        // Retrieve and validate extensions directory
        File extensionsDir = new File(environment.getGuacamoleHome(), EXTENSIONS_DIRECTORY);
        if (!extensionsDir.isDirectory())
            return Collections.emptyList();

        // Retrieve list of all extension files within extensions directory
        File[] extensionFiles = extensionsDir.listFiles(new FileFilter() {

            @Override
            public boolean accept(File file) {
                return file.isFile() && file.getName().endsWith(EXTENSION_SUFFIX);
            }

        });

        // Verify contents are accessible
        if (extensionFiles == null) {
            logger.warn("Although GUACAMOLE_HOME/" + EXTENSIONS_DIRECTORY + " exists, its contents cannot be read.");
            return Collections.emptyList();
        }

        // Read (but do not fully load) each extension within the extension
        // directory
        List<Extension> extensions = new ArrayList<>(extensionFiles.length);
        for (File extensionFile : extensionFiles) {

            logger.debug("Reading extension: \"{}\"", extensionFile.getName());

            try {

                // Load extension from file
                Extension extension = new Extension(getParentClassLoader(), extensionFile, temporaryFiles);

                // Validate Guacamole version of extension
                if (!isCompatible(extension.getGuacamoleVersion())) {
                    logger.debug("Declared Guacamole version \"{}\" of extension \"{}\" is not compatible with this version of Guacamole.",
                            extension.getGuacamoleVersion(), extensionFile.getName());
                    throw new GuacamoleServerException("Extension \"" + extension.getName() + "\" is not "
                            + "compatible with this version of Guacamole.");
                }

                extensions.add(extension);

            }
            catch (GuacamoleException e) {
                logger.error("Extension \"{}\" could not be loaded: {}", extensionFile.getName(), e.getMessage());
                logger.debug("Unable to load extension.", e);
            }

        }

        extensions.sort(getExtensionLoadOrder());
        return extensions;

    }

    /**
     * Loads all extensions within the GUACAMOLE_HOME/extensions directory, if
     * any, adding their static resource to the given resource collections.
     *
     * @param javaScriptResources
     *     A modifiable collection of static JavaScript resources which may
     *     receive new JavaScript resources from extensions.
     *
     * @param cssResources
     *     A modifiable collection of static CSS resources which may receive
     *     new CSS resources from extensions.
     *
     * @param toleratedAuthProviders
     *     The set of identifiers of all authentication providers whose
     *     internal failures should be tolerated during the authentication
     *     process. If the identifier of an authentication provider is within
     *     this set, errors during authentication will result in the
     *     authentication provider being ignored for that authentication
     *     attempt, with the authentication process proceeding as if that
     *     authentication provider were not present. By default, errors during
     *     authentication halt the authentication process entirely.
     */
    private void loadExtensions(Collection<Resource> javaScriptResources,
            Collection<Resource> cssResources,
            Set<String> toleratedAuthProviders) {

        // Advise of current extension load order and how the order may be
        // changed
        List<Extension> extensions = getExtensions();
        if (extensions.size() > 1) {
            logger.info("Multiple extensions are installed and will be "
                    + "loaded in order of decreasing priority:");

            for (Extension extension : extensions) {
                logger.info(" - [{}] \"{}\" ({})", extension.getNamespace(),
                        extension.getName(), extension.getFile());
            }

            logger.info("To change this order, set the \"{}\" property or "
                    + "rename the extension files. The default priority of "
                    + "extensions is dictated by the sort order of their "
                    + "filenames.", EXTENSION_PRIORITY.getName());
        }

        // Load all extensions
        for (Extension extension : extensions) {

            // Add any JavaScript / CSS resources
            javaScriptResources.addAll(extension.getJavaScriptResources().values());
            cssResources.addAll(extension.getCSSResources().values());

            // Attempt to load all authentication providers
            bindAuthenticationProviders(extension.getAuthenticationProviderClasses(), toleratedAuthProviders);

            // Attempt to load all listeners
            bindListeners(extension.getListenerClasses());

            // Add any translation resources
            serveLanguageResources(extension.getTranslationResources());

            // Add all HTML patch resources
            patchResourceService.addPatchResources(extension.getHTMLResources().values());

            // Add all static resources under namespace-derived prefix
            String staticResourcePrefix = "/app/ext/" + extension.getNamespace() + "/";
            serveStaticResources(staticResourcePrefix, extension.getStaticResources());

            // Serve up the small favicon if provided
            if(extension.getSmallIcon() != null)
                serve("/images/logo-64.png").with(new ResourceServlet(extension.getSmallIcon()));

            // Serve up the large favicon if provided
            if(extension.getLargeIcon()!= null)
                serve("/images/logo-144.png").with(new ResourceServlet(extension.getLargeIcon()));

            // Log successful loading of extension by name
            logger.info("Extension \"{}\" ({}) loaded.", extension.getName(), extension.getNamespace());

        }

    }
    
    @Override
    protected void configureServlets() {

        // Bind resource services
        bind(LanguageResourceService.class).toInstance(languageResourceService);
        bind(PatchResourceService.class).toInstance(patchResourceService);

        // Load initial language resources from servlet context
        languageResourceService.addLanguageResources(getServletContext());

        // Init JavaScript and CSS resources from extensions
        Collection<Resource> javaScriptResources = new ArrayList<Resource>();
        Collection<Resource> cssResources = new ArrayList<Resource>();

        // Veriffy that the possibly-cached index.html matches the current build
        javaScriptResources.add(new WebApplicationResource(getServletContext(), "/verifyCachedVersion.js"));

        // Load all extensions
        final Set<String> toleratedAuthProviders = getToleratedAuthenticationProviders();
        loadExtensions(javaScriptResources, cssResources, toleratedAuthProviders);

        // Always bind default file-driven auth last
        bindAuthenticationProvider(FileAuthenticationProvider.class, toleratedAuthProviders);

        // Dynamically generate app.js and app.css from extensions
        serve("/app.js").with(new ResourceServlet(new SequenceResource(javaScriptResources)));
        serve("/app.css").with(new ResourceServlet(new SequenceResource(cssResources)));

        // Dynamically serve all language resources
        for (Map.Entry<String, Resource> entry : languageResourceService.getLanguageResources().entrySet()) {

            // Get language key/resource pair
            String languageKey = entry.getKey();
            Resource resource = entry.getValue();

            // Serve resource within /translations
            serve("/translations/" + languageKey + ".json").with(new ResourceServlet(resource));
            
        }
        
    }

}
