/*
 * steghide 0.5.1 - a steganography program
 * Copyright (C) 1999-2003 Stefan Hetzl <shetzl@chello.at>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */

#ifndef SH_ARGUMENTS_H
#define SH_ARGUMENTS_H

#include <string>
#include <vector>

#include "Arg.h"

// to include DEBUG if defined
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

/**
 * \class Arguments
 * \brief parsing and data representation of command-line arguments
 **/
class Arguments {
  public:
    Arguments(void){};

    /**
     * initialize this Arguments object with argc and argv
     **/
    Arguments(int argc, char *argv[]);

    /**
     * parse Argc and Argv filling the Arg* member variable for later access
     **/
    void parse(void);

    /**
     * is standard input used ? - according to the given arguments
     **/
    bool stdin_isused(void) const;

    /// the command to be executed in this session
    ArgCommand Command;
    /// the name of the command to be executed in this session (as supplied by the user)
    std::string CommandString;

    /// the embed file name, "" if stdin
    ArgString EmbFn;
    /// the extract file name, "" if stdout
    ArgString ExtFn;
    /// the cover file name, "" if stdin
    ArgString CvrFn;
    /// the stego file name, "" if stdout/stdin
    ArgString StgFn;
    /// the wordlist file name, "" if stdout/stdin
    ArgString WordlistFn;
    ArgString Passphrase;
    ArgBool Checksum;
    ArgInt Compression;
    ArgInt Threads;
    ArgBool EmbedEmbFn;
    ArgEncAlgo EncAlgo;
    ArgEncMode EncMode;
    ArgULong Radius;
    ArgFloat Goal;
    ArgBool Force;
    ArgBool SkipDefaultGuesses;
    ArgVerbosity Verbosity;
    ArgDebugCommand DebugCommand;
    ArgBool Check;
    ArgBool Accessible;
    ArgBool Color;
    ArgBool ContinueAfterFirstResult;
    ArgStringList FileList;
    ArgUInt DebugLevel;
    ArgUInt GmlGraphRecDepth;
    ArgUInt GmlStartVertex;

    std::string getPassphrase(bool doublecheck = false);

  private:
    typedef std::vector<std::string>::const_iterator ArgIt;

    static const int NoCompression = 0;

    static const EncryptionAlgorithm Default_EncAlgo;
    static const EncryptionMode Default_EncMode;
    static const bool Default_Checksum = true;
    static const int Default_Compression = 9; // slowest, but smallest
    static const bool Default_EmbedEmbFn = true;
    static const bool Default_Force = false;
    static const bool Default_SkipDefaultGuesses = false;
    static const VERBOSITY Default_Verbosity = NORMAL;
    static const unsigned long Default_Radius =
        0; // there is no default radius for all file formats
    static const unsigned int Max_Algorithm = 3;
    static constexpr float Default_Goal = 100.0;
    static const DEBUGCOMMAND Default_DebugCommand = NONE;
    static const bool Default_Check = false;
    static const bool Default_Accessible = false;
    static const bool Default_Color = true;
    static const bool Default_ContinueAfterFirstResult = false;
    static const unsigned int Default_DebugLevel = 0;
    static const unsigned int Default_GmlGraphRecDepth = 0;
    static const unsigned int Default_GmlStartVertex = 0;

    /**
     * parse the command
     *
     * Note: parse_Command is the only parse_* function that requires curarg to be a command.
     * (because the command is the only argument with a fixed position).
     **/
    void parse_Command(ArgIt &curarg);

    /**
     * Parse arguments based on their positions.
     * Will fully ignore any argument starting with -
     **/
    void parse_Positional(std::vector<std::string>);

    /**
     * Parse arguments starting with a -
     **/
    std::vector<std::string> parse_Arguments(ArgIt &curarg);

    /**
     * test if curarg points to an emb filename argument and if yes: parse it
     * \return true iff one or more arguments have been parsed
     **/
    bool parse_EmbFn(ArgIt &curarg);

    bool parse_Generic_String(ArgIt &curarg, std::vector<COMMAND> compatibleCommands,
                              ArgString *destArg);
    bool parse_Generic_Bool(ArgIt &curarg, std::vector<COMMAND> compatibleCommands,
                            ArgBool *destArg, bool ifMatch);

    bool parse_ExtFn(ArgIt &curarg);
    bool parse_CvrFn(ArgIt &curarg);
    bool parse_StgFn(ArgIt &curarg);
    bool parse_WordlistFn(ArgIt &curarg);
    bool parse_Passphrase(ArgIt &curarg);
    bool parse_Checksum(ArgIt &curarg);
    bool parse_Compression(ArgIt &curarg);
    bool parse_EmbedEmbFn(ArgIt &curarg);
    bool parse_Encryption(ArgIt &curarg);
    bool parse_Radius(ArgIt &curarg);
    bool parse_Goal(ArgIt &curarg);
    bool parse_Force(ArgIt &curarg);
    bool parse_Threading(ArgIt &curarg);
    bool parse_Verbosity(ArgIt &curarg);
    bool parse_Debug(ArgIt &curarg);

    void setDefaults(void);

    std::vector<std::string> TheArguments;
};

// gcc does not support the export keyword
#include "Arg.cc"

#endif /* ndef SH_ARGUMENTS_H */
