/*
  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.commons.cli;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.ListIterator;
import java.util.Properties;

/**
 * {@code Parser} creates {@link CommandLine}s.
 *
 * @deprecated since 1.3, the two-pass parsing with the flatten method is not enough flexible to handle complex cases
 */
@Deprecated
public abstract class Parser implements CommandLineParser {
    /** CommandLine instance */
    protected CommandLine cmd;

    /** Current Options */
    private Options options;

    /** List of required options strings */
    private List requiredOptions;

    /**
     * Throws a {@link MissingOptionException} if all of the required options are not present.
     *
     * @throws MissingOptionException if any of the required Options are not present.
     */
    protected void checkRequiredOptions() throws MissingOptionException {
        // if there are required options that have not been processed
        if (!getRequiredOptions().isEmpty()) {
            throw new MissingOptionException(getRequiredOptions());
        }
    }

    /**
     * Subclasses must implement this method to reduce the {@code arguments} that have been passed to the parse method.
     *
     * @param opts The Options to parse the arguments by.
     * @param arguments The arguments that have to be flattened.
     * @param stopAtNonOption specifies whether to stop flattening when a non option has been encountered
     * @return a String array of the flattened arguments
     * @throws ParseException if there are any problems encountered while parsing the command line tokens.
     */
    protected abstract String[] flatten(Options opts, String[] arguments, boolean stopAtNonOption) throws ParseException;

    /**
     * Gets the options.
     *
     * @return the options.
     */
    protected Options getOptions() {
        return options;
    }

    /**
     * Gets the required options.
     *
     * @return the required options.
     */
    protected List getRequiredOptions() {
        return requiredOptions;
    }

    /**
     * Parses the specified {@code arguments} based on the specified {@link Options}.
     *
     * @param options the {@code Options}
     * @param arguments the {@code arguments}
     * @return the {@code CommandLine}
     * @throws ParseException if there are any problems encountered while parsing the command line tokens.
     */
    @Override
    public CommandLine parse(final Options options, final String[] arguments) throws ParseException {
        return parse(options, arguments, null, false);
    }

    /**
     * Parses the specified {@code arguments} based on the specified {@link Options}.
     *
     * @param options the {@code Options}
     * @param arguments the {@code arguments}
     * @param stopAtNonOption if {@code true} an unrecognized argument stops the parsing and the remaining arguments
     *        are added to the {@link CommandLine}s args list. If {@code false} an unrecognized argument triggers a
     *        ParseException.
     * @return the {@code CommandLine}
     * @throws ParseException if an error occurs when parsing the arguments.
     */
    @Override
    public CommandLine parse(final Options options, final String[] arguments, final boolean stopAtNonOption) throws ParseException {
        return parse(options, arguments, null, stopAtNonOption);
    }

    /**
     * Parse the arguments according to the specified options and properties.
     *
     * @param options the specified Options
     * @param arguments the command line arguments
     * @param properties command line option name-value pairs
     * @return the list of atomic option and value tokens
     * @throws ParseException if there are any problems encountered while parsing the command line tokens.
     * @since 1.1
     */
    public CommandLine parse(final Options options, final String[] arguments, final Properties properties) throws ParseException {
        return parse(options, arguments, properties, false);
    }

    /**
     * Parse the arguments according to the specified options and properties.
     *
     * @param options the specified Options
     * @param arguments the command line arguments
     * @param properties command line option name-value pairs
     * @param stopAtNonOption if {@code true} an unrecognized argument stops the parsing and the remaining arguments
     *        are added to the {@link CommandLine}s args list. If {@code false} an unrecognized argument triggers a
     *        ParseException.
     * @return the list of atomic option and value tokens
     * @throws ParseException if there are any problems encountered while parsing the command line tokens.
     * @since 1.1
     */
    public CommandLine parse(final Options options, final String[] arguments, final Properties properties, final boolean stopAtNonOption)
            throws ParseException {
        // clear out the data in options in case it's been used before (CLI-71)
        for (final Option opt : options.helpOptions()) {
            opt.clearValues();
        }
        // clear the data from the groups
        for (final OptionGroup group : options.getOptionGroups()) {
            group.setSelected(null);
        }
        // initialize members
        setOptions(options);
        cmd = CommandLine.builder().build();
        boolean eatTheRest = false;
        final List<String> tokenList = Arrays.asList(flatten(getOptions(), arguments == null ? new String[0] : arguments, stopAtNonOption));
        final ListIterator<String> iterator = tokenList.listIterator();
        // process each flattened token
        while (iterator.hasNext()) {
            final String token = iterator.next();
            if (token != null) {
                // the value is the double-dash
                if ("--".equals(token)) {
                    eatTheRest = true;
                } else if ("-".equals(token)) {
                    // the value is a single dash
                    if (stopAtNonOption) {
                        eatTheRest = true;
                    } else {
                        cmd.addArg(token);
                    }
                } else if (token.startsWith("-")) {
                    // the value is an option
                    if (stopAtNonOption && !getOptions().hasOption(token)) {
                        eatTheRest = true;
                        cmd.addArg(token);
                    } else {
                        processOption(token, iterator);
                    }
                } else {
                    // the value is an argument
                    cmd.addArg(token);
                    if (stopAtNonOption) {
                        eatTheRest = true;
                    }
                }
                // eat the remaining tokens
                if (eatTheRest) {
                    while (iterator.hasNext()) {
                        final String str = iterator.next();
                        // ensure only one double-dash is added
                        if (!"--".equals(str)) {
                            cmd.addArg(str);
                        }
                    }
                }
            }
        }
        processProperties(properties);
        checkRequiredOptions();
        return cmd;
    }

    /**
     * Process the argument values for the specified Option {@code opt} using the values retrieved from the specified
     * iterator {@code iter}.
     *
     * @param opt The current Option
     * @param iter The iterator over the flattened command line Options.
     * @throws ParseException if an argument value is required and it is has not been found.
     */
    public void processArgs(final Option opt, final ListIterator<String> iter) throws ParseException {
        // loop until an option is found
        while (iter.hasNext()) {
            final String str = iter.next();
            // found an Option, not an argument
            if (getOptions().hasOption(str) && str.startsWith("-")) {
                iter.previous();
                break;
            }
            // found a value
            try {
                opt.processValue(Util.stripLeadingAndTrailingQuotes(str));
            } catch (final RuntimeException exp) {
                iter.previous();
                break;
            }
        }
        if (opt.getValues() == null && !opt.hasOptionalArg()) {
            throw new MissingArgumentException(opt);
        }
    }

    /**
     * Process the Option specified by {@code arg} using the values retrieved from the specified iterator
     * {@code iter}.
     *
     * @param arg The String value representing an Option
     * @param iter The iterator over the flattened command line arguments.
     * @throws ParseException if {@code arg} does not represent an Option
     */
    protected void processOption(final String arg, final ListIterator<String> iter) throws ParseException {
        final boolean hasOption = getOptions().hasOption(arg);
        // if there is no option throw an UnrecognizedOptionException
        if (!hasOption) {
            throw new UnrecognizedOptionException("Unrecognized option: " + arg, arg);
        }
        // get the option represented by arg
        final Option opt = (Option) getOptions().getOption(arg).clone();
        // update the required options and groups
        updateRequiredOptions(opt);
        // if the option takes an argument value
        if (opt.hasArg()) {
            processArgs(opt, iter);
        }
        // set the option on the command line
        cmd.addOption(opt);
    }

    /**
     * Sets the values of Options using the values in {@code properties}.
     *
     * @param properties The value properties to be processed.
     * @throws ParseException if there are any problems encountered while processing the properties.
     */
    protected void processProperties(final Properties properties) throws ParseException {
        if (properties == null) {
            return;
        }
        for (final Enumeration<?> e = properties.propertyNames(); e.hasMoreElements();) {
            final String option = e.nextElement().toString();
            final Option opt = options.getOption(option);
            if (opt == null) {
                throw new UnrecognizedOptionException("Default option wasn't defined", option);
            }
            // if the option is part of a group, check if another option of the group has been selected
            final OptionGroup group = options.getOptionGroup(opt);
            final boolean selected = group != null && group.getSelected() != null;
            if (!cmd.hasOption(option) && !selected) {
                // get the value from the properties instance
                final String value = properties.getProperty(option);
                if (opt.hasArg()) {
                    if (Util.isEmpty(opt.getValues())) {
                        try {
                            opt.processValue(value);
                        } catch (final RuntimeException exp) { // NOPMD
                            // if we cannot add the value don't worry about it
                        }
                    }
                } else if (!("yes".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value) || "1".equalsIgnoreCase(value))) {
                    // if the value is not yes, true or 1 then don't add the
                    // option to the CommandLine
                    continue;
                }
                cmd.addOption(opt);
                updateRequiredOptions(opt);
            }
        }
    }

    /**
     * Sets the options.
     *
     * @param options the options.
     */
    protected void setOptions(final Options options) {
        this.options = options;
        this.requiredOptions = new ArrayList<>(options.getRequiredOptions());
    }

    /**
     * Removes the option or its group from the list of expected elements.
     *
     * @param opt
     */
    private void updateRequiredOptions(final Option opt) throws ParseException {
        // if the option is a required option remove the option from
        // the requiredOptions list
        if (opt.isRequired()) {
            getRequiredOptions().remove(opt.getKey());
        }
        // if the option is in an OptionGroup make that option the selected
        // option of the group
        if (getOptions().getOptionGroup(opt) != null) {
            final OptionGroup group = getOptions().getOptionGroup(opt);
            if (group.isRequired()) {
                getRequiredOptions().remove(group);
            }
            group.setSelected(opt);
        }
    }

}
