/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed 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 com.android.tradefed.config;

import com.android.tradefed.config.proxy.TradefedDelegator;
import com.android.tradefed.util.keystore.IKeyStoreClient;

import java.io.PrintStream;
import java.util.List;
import java.util.Set;

/**
 * Factory for creating {@link IConfiguration}s
 */
public interface IConfigurationFactory {

    /**
     * A convenience method which calls {@link #createConfigurationFromArgs(String[], List)}
     * with a {@code null} second argument.  Thus, it will throw {@link ConfigurationException} if
     * any unconsumed arguments remain.
     *
     * @see #createConfigurationFromArgs(String[], List)
     */
    public IConfiguration createConfigurationFromArgs(String[] args) throws ConfigurationException;

    /**
     * Create the {@link IConfiguration} from command line arguments.
     * <p/>
     * Expected format is "CONFIG [options]", where CONFIG is the built-in configuration name or
     * a file path to a configuration xml file.
     *
     * @param args the command line arguments
     * @param unconsumedArgs a List which will be populated with the arguments that were not
     *                       consumed by the Objects associated with the specified config. If this
     *                       is {@code null}, then the implementation will throw
     *                       {@link ConfigurationException} if any unprocessed args remain.
     *
     * @return the loaded {@link IConfiguration}. The delegate object {@link Option} fields have
     *         been populated with values in args.
     * @throws ConfigurationException if configuration could not be loaded
     */
    public IConfiguration createConfigurationFromArgs(String[] args, List<String> unconsumedArgs)
            throws ConfigurationException;

    /**
     * Create the {@link IConfiguration} from command line arguments with a key store.
     * <p/>
     * Expected format is "CONFIG [options]", where CONFIG is the built-in configuration name or
     * a file path to a configuration xml file.
     *
     * @param args the command line arguments
     * @param unconsumedArgs a List which will be populated with the arguments that were not
     *                       consumed by the Objects associated with the specified config. If this
     *                       is {@code null}, then the implementation will throw
     *                       {@link ConfigurationException} if any unprocessed args remain.
     * @param keyStoreClient a {@link IKeyStoreClient} which is used to obtain sensitive info in
     *                       the args.
     *
     * @return the loaded {@link IConfiguration}. The delegate object {@link Option} fields have
     *         been populated with values in args.
     * @throws ConfigurationException if configuration could not be loaded
     */
    public IConfiguration createConfigurationFromArgs(String[] args, List<String> unconsumedArgs,
            IKeyStoreClient keyStoreClient) throws ConfigurationException;

    /**
     * Create a configuration that only contains a set of selected objects.
     *
     * @param arrayArgs The command line arguments
     * @param keyStoreClient A {@link IKeyStoreClient} which is used to obtain sensitive info in the
     *     args.
     * @param allowedObjects The set of allowed objects to be created
     * @return The loaded {@link IConfiguration}.
     * @throws ConfigurationException if configuration could not be loaded
     */
    public IConfiguration createPartialConfigurationFromArgs(
            String[] arrayArgs,
            IKeyStoreClient keyStoreClient,
            Set<String> allowedObjects,
            TradefedDelegator delegator)
            throws ConfigurationException;

    /**
     * Create a {@link IGlobalConfiguration} from command line arguments.
     * <p/>
     * Expected format is "CONFIG [options]", where CONFIG is the built-in configuration name or
     * a file path to a configuration xml file.
     *
     * @param args the command line arguments
     * @param nonGlobalArgs a list which will be populated with the arguments that weren't
     *                      processed as global arguments
     * @return the loaded {@link IGlobalConfiguration}. The delegate object {@link Option} fields
     *         have been populated with values in args.
     * @throws ConfigurationException if configuration could not be loaded
     */
    public IGlobalConfiguration createGlobalConfigurationFromArgs(String[] args,
            List<String> nonGlobalArgs) throws ConfigurationException;

    /**
     * Prints help output for this factory.
     * <p/>
     * Prints a generic help info, and lists all available configurations.
     *
     * @param out the {@link PrintStream} to dump output to
     */
    public void printHelp(PrintStream out);

    /**
     * Prints help output for the {@link IConfiguration} specified in command line arguments,
     * <p/>
     * If 'args' refers to a known configuration, a {@link IConfiguration} object will be created
     * from XML, and help for that {@link IConfiguration} will be outputted. Note all other 'args'
     * values will be ignored (ie the help text will describe the current values of {@link Option}s
     * as loaded from XML, and will not reflect option's values set by the command line args.
     * <p/>
     * If 'args' does not reference a known {@link IConfiguration}, the generic
     * {@link #printHelp(PrintStream)} help will be displayed.
     * <p/>
     *
     * @param args the command line arguments
     * @param importantOnly if <code>true</code>, print an abbreviated help listing only the
     * important details
     * @param out the {@link PrintStream} to dump output to
     */
    public void printHelpForConfig(String[] args, boolean importantOnly, PrintStream out);

    /**
     * Dumps the contents of the configuration to the given {@link PrintStream}
     *
     * @param configName the configuration name
     * @param out the {@link PrintStream} to dump output to
     */
    public void dumpConfig(String configName, PrintStream out);

    /**
     * Return the list of names of all the configs found in the JARs on the classpath.
     * Does not attempt to load any of the configs, so it is possible to have non working config
     * in this list.
     */
    public List<String> getConfigList();

    /**
     * Variation of {@link #getConfigList()} where can specify whether or not we also want to load
     * the configuration from the environment.
     *
     * @param subPath name of the sub-directories to look in for configuration. If null, will have
     *     the same behavior as {@link #getConfigList()}.
     * @param loadFromEnv True if we should load the configuration in the environment variable.
     */
    public List<String> getConfigList(String subPath, boolean loadFromEnv);
}
