/***************************************************************************
                          cmdlineoptions.h  -  description
                             -------------------
    begin                : Sun Nov 25 2001
    copyright            : (C) 2001-2007 by Andre Simon
    email                : andre.simon1@gmx.de
 ***************************************************************************/


/*
This file is part of Highlight.

Highlight 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 3 of the License, or
(at your option) any later version.

Highlight 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 Highlight.  If not, see <http://www.gnu.org/licenses/>.
*/


#ifndef CMDLINEOPTIONS_H
#define CMDLINEOPTIONS_H

#ifdef _WIN32
#include <windows.h>
#endif

#include <string>
#include <map>
#include <set>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>

#include "stringtools.h"
#include "enums.h"


#define OPT_ADDCONFDIR     "add-config-dir"
#define OPT_ADDDATADIR     "add-data-dir"
#define OPT_ANCHORS        "anchors"
#define OPT_ANCHOR_FN      "anchor-filename"
#define OPT_ANCHOR_PFX     "anchor-prefix"
#define OPT_ANSI           "ansi"
#define OPT_BABEL          "babel"
#define OPT_BASE_FONT      "font"
#define OPT_BASE_FONT_SIZE "font-size"
#define OPT_BATCHREC       "batch-recursive"
#define OPT_CLASSNAME      "class-name"
#define OPT_DATADIR        "data-dir"
#define OPT_DELTABS        "replace-tabs"
#define OPT_DOC_TITLE      "doc-title"
#define OPT_ENCLOSE_PRE    "enclose-pre"
#define OPT_ENCODING       "encoding"
#define OPT_FILLZEROES     "zeroes"
#define OPT_FORCE_OUTPUT   "force"
#define OPT_FORMAT         "reformat"
#define OPT_FRAGMENT       "fragment"
#define OPT_HELP           "help"
#define OPT_HTML           "html"
#define OPT_IN             "input"
#define OPT_INC_STYLE      "include-style"
#define OPT_INDEXFILE      "print-index"
#define OPT_INLINE_CSS     "inline-css"
#define OPT_KW_CASE        "kw-case"
#define OPT_LATEX          "latex"
#define OPT_LINENO         "linenumbers"
#define OPT_LINE_LEN       "line-length"
#define OPT_LISTLANGS      "list-langs"
#define OPT_LISTTHEMES     "list-themes"
#define OPT_LNR_LEN        "line-number-length"
#define OPT_LNR_START      "line-number-start"
#define OPT_MARK_LINES     "mark-line"
#define OPT_ORDERED_LIST   "ordered-list"
#define OPT_OUT            "output"
#define OPT_OUTDIR         "outdir"
#define OPT_RTF_PAGE_SIZE  "page-size"
#define OPT_RTF_CHAR_STYLES "char-styles"
#define OPT_PRINT_CONFIG   "print-config"
#define OPT_PROGRESSBAR    "progress"
#define OPT_QUIET          "quiet"
#define OPT_REPLACE_QUOTES "replace-quotes"
#define OPT_RTF            "rtf"
#define OPT_STYLE          "style"
#define OPT_STYLE_IN       "style-infile"
#define OPT_STYLE_OUT      "style-outfile"
#define OPT_SYNTAX         "syntax"
#define OPT_TEST_INPUT     "validate-input"
#define OPT_TEX            "tex"
#define OPT_VERBOSE        "verbose"
#define OPT_VERSION        "version"
#define OPT_WRAP           "wrap"
#define OPT_WRAPSIMPLE     "wrap-simple"
#define OPT_XHTML          "xhtml"
#define OPT_XML            "xml"
#define OPT_XTERM256       "xterm256"
#define OPT_SVG            "svg"
#define OPT_SVG_WIDTH      "width"
#define OPT_SVG_HEIGHT     "height"
#define OPT_SKIP_UNKNOWN   "skip"
#define OPT_CTAGS_FILE     "ctags-file"
#define OPT_PRETTY_SYMBOLS "pretty-symbols"
#define OPT_EOL_DELIM_CR   "delim-cr"
#define OPT_BBCODE         "bbcode"
#define OPT_START_NESTED   "start-nested"
#define OPT_PRINT_STYLE    "print-style"
#define OPT_NO_TRAILING_NL "no-trailing-nl"

// Improve CLI option compatibility with GNU source-highlight
#define OPT_COMPAT_DOC       "doc"
#define OPT_COMPAT_NODOC     "no-doc"
#define OPT_COMPAT_TAB       "tab"
#define OPT_COMPAT_CSS       "css"
#define OPT_COMPAT_OUTDIR    "output-dir"
#define OPT_COMPAT_FAILSAFE  "failsafe"
#define OPT_COMPAT_OUTFORMAT "out-format"
#define OPT_COMPAT_SRCLANG   "src-lang"
#define OPT_COMPAT_LINENUM   "line-number"
#define OPT_COMPAT_LINEREF   "line-number-ref"

using namespace std;

/// handle command line options

class CmdLineOptions
{
	public:

		/**Constructor
		 \param argc Argument count
		 \param argv Argument strings
		*/
		CmdLineOptions ( const int argc, const char *argv[] );
		~CmdLineOptions();

		/** \return Single output file name*/
		const string &getSingleOutFilename();

		/** \return Single input file name*/
		const string &getSingleInFilename() const;

		/** \return Output directory*/
		const string& getOutDirectory() ;

		/** \return Style output file name*/
		const string getStyleOutFilename() const;

		/** \return Style input file name*/
		const string& getStyleInFilename() const;

		/** \return Char set*/
		const string& getEncoding() const;

		/** \return SVG width*/
		const string& getSVGWidth() const;

		/** \return SVG height*/
		const string& getSVGHeight() const;

		/** \return Number of spaces to replace a tab*/
		int getNumberSpaces() const;

		/** \return True if version information should be printed*/
		bool printVersion() const;

		/** \return True if help information should be printed*/
		bool printHelp() const;

		/** \return True if debug information should be printed*/
		bool printDebugInfo() const;

		/** \return True if configuration information should be printed*/
		bool printConfigInfo() const;

		/** \return True if Style definition should be included in output*/
		bool includeStyleDef() const;

		/** \return True if line numbers should be printed*/
		bool printLineNumbers() const;

		/** \return True if CR is eol delimiter */
		bool useCRDelimiter() const;

		/** \return colour theme name */
		string getThemeName() const ;

		/** gibt true zurck, falls deutsche Hilfe ausgegeben werden soll */
		int helpLanguage() const;

		/** \return True if batch mode is active*/
		bool enableBatchMode() const;

		/** \return True if output shluld be fragmented*/
		bool fragmentOutput() const;

		/** \return output file suffix */
		string getOutFileSuffix() const;

		/** \return True if anchors should be attached to line numbers*/
		bool attachLineAnchors() const;

		/** \return True if list of installed themes should be printed*/
		bool showThemes() const;

		/** \return True if list of installed language definitions should be printed*/
		bool showLangdefs() const;

		/** \return True if loutput directory is given*/
		bool outDirGiven() const;

		/** \return True if refomatting is enabled*/
//    bool formattingEnabled();

		/** \return True if a new data directory is given*/
		bool dataDirGiven() const;

		/** \return True if an additional data directory is given*/
		bool additionalDataDirGiven() const;

		/** \return True if index file should be printed*/
		bool printIndexFile() const;

		/** \return True if quotes should be replaced by /dq in LaTeX*/
		bool replaceQuotes() const;

		/** \return True if shorthands of LaTeX Babel package should be disabled*/
		bool disableBabelShorthands() const;

		/** \return True if input file name should be used as anchor name */
		bool useFNamesAsAnchors() const;

		/** \return Data directory*/
		const string &getDataDir() const;

		/** \return Additional data directory*/
		const string &getAdditionalDataDir() const;

		/** \return Additional config data directory*/
		const string &getAdditionalConfDir() const;

		/** \return  path of user config file*/
		const string &getConfigFilePath() const;

		/** \return True if language syntax is given*/
		bool syntaxGiven() const;

		/** \return True if quiet mode is active*/
		bool quietMode() const;

		/** \return True if progress bar should be printed in batch mode */
		bool printProgress() const;

		/** \return True if line numbers are filled with leading zeroes */
		bool fillLineNrZeroes() const;

		/** \return programming syntax */
		const string &getLanguage() const ;

		/** \return Wrapping style*/
		highlight::WrapMode getWrappingStyle() const;

		/** \return List of input file names*/
		const vector <string> & getInputFileNames() const;

		/** \return Map of marked lines*/
		const map <int,string> &getMarkLines();

		/** \return indentation and reformatting scheme*/
		string getIndentScheme() const;

		/** \return RTF page size */
		const string &getPageSize() const;

		/** \return Output file format */
		highlight::OutputType getOutputType() const;

		/** \return True if chosen output format supports referenced style files */
		bool formatSupportsExtStyle();

		/** \return True if style output path was defined by user*/
		bool styleOutPathDefined() const
		{
			return opt_stylepath_explicit;
		}

		/** \return True if encoding specification should be omitted in output*/
		bool omitEncoding() const;

		/** \return True if output should be generated if languege type is unknown*/
		bool forceOutput() const;

		/** \return True if line numbers should be replaced by ordered list (HTML) */
		bool orderedList() const;

		/** \return True if a base font has been given */
		bool hasBaseFont() const ;

		/** \return True if input should be validated */
		bool validateInput() const ;

		/** \return True if CSS should be outputted within tag elements */
		bool inlineCSS() const ;

		/** \return True if fragmented html output should be enclosed with pre tags */
		bool enclosePreTag() const ;

		/** \return True if RTF output should include character styles */
		bool includeCharStyles() const ;

		/** \return True if LaTeX output should includ fancier symbols */
		bool prettySymbols() const;

		/** \return True if style should be printed */
		bool printOnlyStyle() const;

		/** \return The given base font, empty string by default */
		const string& getBaseFont() const ;

		/** \return Document title */
		const string& getDocumentTitle() const ;

		/** \return anchor prefix */
		const string& getAnchorPrefix() const ;

		/** \return class name */
		const string& getClassName() const ;

		/** \return ctags file name */
		const string& getTagsFile() const ;

		/** \return True if a base font size has been given */
		bool hasBaseFontSize() const ;
		
		/** \return True if trailing nl should be omitted */
		bool disableTrailingNL() const ;

		/** \return The given base font size, empty string by default */
		const string& getBaseFontSize() const ;

		/** \return name of nested syntax which starts the input */
		const string& getStartNestedLang() const ;

		/** \return line number width */
		int getNumberWidth();

		/** \return line length */
		int getLineLength();

		/** \return Line number start count */
		int getNumberStart();

		/** \return Keyword Case (upper, lower, unchanged) */
		StringTools::KeywordCase getKeywordCase() const;

		bool isSkippedExt ( const string& ext )
		{
			return ignoredFileTypes.count ( ext );
		}

	private:

		int numberSpaces;   // number of spaces which replace a tab
		int lineNrWidth;    // width of line number (left padding)
		int lineLength;    // length of line before wrapping
		int lineNrStart;    // line number start count
		highlight::WrapMode wrappingStyle; // line wrapping mode
		highlight::OutputType outputType;
		StringTools::KeywordCase keywordCase;

		// name of single output file
		string outFilename,
		// output directory
		outDirectory,
		// programming syntax which will be loaded
		syntax,
		// name of colour theme
		styleName,
		// name of external style file
		styleOutFilename,
		// name of file to be included in external style file
		styleInFilename,
		// used to define data directories at runtime
		dataDir, additionalDataDir, additionalConfigDir;
		// name of indenation scheme
		string indentScheme,
		pageSize, startNestedLang;

		string baseFont, baseFontSize;
		string docTitle, className;
		string markLinesArg;
		string skipArg;
		string svg_height, svg_width;
		string ctagsFile;

		bool opt_syntax;
		bool opt_include_style;
		bool opt_help;
		bool opt_version ;
		bool opt_verbose;
		bool opt_print_config;
		bool opt_linenumbers;
		bool opt_style;
		bool opt_batch_mode;
		bool opt_fragment;
		bool opt_attach_line_anchors;
		bool opt_show_themes;
		bool opt_show_langdefs;
		bool opt_asformat_output;
		bool opt_printindex;
		bool opt_quiet;
		bool opt_replacequotes;
		bool opt_babel;
		bool opt_print_progress;
		bool opt_fill_zeroes;
		bool opt_stylepath_explicit;
		bool opt_force_output;
		bool opt_ordered_list;
		bool opt_fnames_as_anchors;
		bool opt_validate;
		bool opt_inline_css;
		bool opt_enclose_pre;
		bool opt_char_styles;
		bool opt_pretty_symbols;
		bool opt_delim_CR;
		bool opt_print_style;
		bool opt_no_trailing_nl;

		bool configFileRead;

		string anchorPrefix;

		string helpLang, encodingName;
		string configFilePath;

		/** list of all input file names */
		vector <string> inputFileNames;

		/** list lines which should be marked and supplied with help string */
		map <int, string> markLines;

		/** list of file types which should be ignored */
		set <string> ignoredFileTypes;

		/** load highlight configuration file */
		void loadConfigurationFile();

		/** \return file suffix */
		string getFileSuffix ( const string & fileName ) const;

		/** \return directory name of path */
		string getDirName ( const string & path );

		/** get all entries in the directory defined by wildcard */
		void readDirectory ( const string & wildcard );

		/** \return Boolean value of paramVal */
		bool getFlag ( const string& paramVal );

		/** \return Valid path name */
		string validateDirPath ( const string & path );
};

#endif
