package de.renew.plugin.command;

import java.io.PrintStream;
import java.util.Properties;
import java.util.StringTokenizer;

import de.renew.plugin.IPlugin;
import de.renew.plugin.PluginManager;
import de.renew.plugin.PluginProperties;

/**
 * This command sets a system property.
 *
 * @author J&ouml;rn Schumacher
 */
public class SetPropertyCommand implements CLCommand {
    /**
     * The String identifying the command in the command line
     */
    public static final String COMMAND_NAME = "set";
    /**
     * Logger for logging purposes as specified by Apache Log4j
     */
    public static final org.apache.log4j.Logger LOGGER =
        org.apache.log4j.Logger.getLogger(SetPropertyCommand.class);

    /**
     * Default constructor for {@link SetPropertyCommand}.
     */
    public SetPropertyCommand() {}

    /**
     * Public method to call {@link #setProperty(String, PrintStream)} ensures only authorized calls are made
     * @param args {@inheritDoc}
     * @param response {@inheritDoc}
     **/
    @Override
    public void execute(String[] args, PrintStream response) {
        for (String arg : args) {
            setProperty(arg, response);
        }
    }

    /**
     * Globally sets the value of the given property to the specified value.
     * The property and its value are specified via <code>args</code>,
     *error messages go to <code>response</code>.
     * @param arg Property and the Value to be set for given property
     * @param response CL PrintStream of caller
     */
    protected void setProperty(String arg, PrintStream response) {
        StringTokenizer tokenizer = new StringTokenizer(arg, "=");
        String key;
        StringBuilder value = null;
        if (!tokenizer.hasMoreTokens()) {
            response.println("Usage: set property=value [property=value ...]");
            response.println("       Don't use spaces around the = sign!");
            return;
        }
        key = tokenizer.nextToken();
        if (!tokenizer.hasMoreTokens()) {
            response.println(
                "SetPropertyCommand: no argument given for variable " + arg
                    + ", it becomes unset.");
        } else {
            while (tokenizer.hasMoreTokens()) {
                if (value == null) {
                    value = new StringBuilder(tokenizer.nextToken());
                } else {
                    value.append("=").append(tokenizer.nextToken());
                }
            }
        }

        // set the property in the user properties
        Properties userProps = PluginProperties.getUserProperties();
        if (value == null) {
            userProps.remove(key);


            // iterate through all plugins and remove their property
            for (IPlugin p : PluginManager.getInstance().getPlugins()) {
                PluginProperties props = p.getProperties();
                props.remove(key);
            }
        } else {
            userProps.setProperty(key, value.toString());

            // iterate through all plugins and set their property
            for (IPlugin p : PluginManager.getInstance().getPlugins()) {
                PluginProperties props = p.getProperties();
                props.setProperty(key, value.toString());
            }
        }
    }

    @Override
    public String getDescription() {
        return "sets a system property (syntax key=value)";
    }

    @Override
    public String getArguments() {
        return "propertyNames";
    }
}