/*
 * Copyright (c) 1999 Johnny C. Lam.
 * All rights reserved.
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  The author makes no representations
 * about the suitability of this software for any purpose.  It is
 * provided "as is" without express or implied warranty.
 */

/* -*- C++ -*- */

#ifndef GENETICS_COMMAND_LINE_H_INCLUDED
#define GENETICS_COMMAND_LINE_H_INCLUDED

#ifndef STD_IOSFWD_INCLUDED
#include <iosfwd>
#define STD_IOSFWD_INCLUDED
#endif

#ifndef DP_SINGLETON_INCLUDED
#include <singleton>
#define DP_SINGLETON_INCLUDED
#endif

#ifndef STD_STRING_INCLUDED
#include <string>
#define STD_STRING_INCLUDED
#endif

#ifndef PATH_CRITERION_FACTORY_H
#include "path_criterion_factory.h"
#endif

#ifndef PATH_STRATEGY_FACTORY_H
#include "path_strategy_factory.h"
#endif

#ifndef SEGMENT_PROBABILITY_FACTORY_H
#include "segment_factory.h"
#endif

class CmdArg;

class CommandLine : public Singleton<CommandLine> {
public:
    typedef SegmentProbabilityFactory::choice_type segment_type;
    typedef PathStrategyFactory::choice_type path_strategy_type;
    typedef PathCriterionFactory::choice_type criterion_type;

    enum options_t {
	VERBOSE = 0,
	SEGMENT,
	LEFT_MASK, RIGHT_MASK, SSM, IBD,
	P_MUTATION, P_RECOMBINATION,
	DIST_FNAME, STR_FNAME, RECOMB_FNAME, NO_RECOMB_SUM,
	MAX_LATENT_DEPTH, PATH_STRATEGY,
	NUM_ODH, CRITERION, COMPONENTS_FNAME,
	ALLELE_FREQ, NUM_NORMALS,
	ROOT_PRIOR_FNAME,
	NO_CLADES, EXCLUDE_NORMALS,
	DISEASE, DISEASED_FNAME, NORMAL_FNAME,
	NUM_OPTIONS
    };

public:
    template <class InputIterator>
    void Parse(int, char* [],
	       InputIterator, InputIterator,
	       InputIterator, InputIterator);

    template <class InputIterator>
    void Write(std::ostream&, InputIterator, InputIterator) const;
    
    unsigned int	Verbose() const;
    segment_type	Segment() const;
    unsigned int	LeftMask() const;
    unsigned int	RightMask() const;
    double		Ssm() const;
    double		Ibd() const;
    double		PMutation() const;
    double		PRecombination() const;
    const string&	DistFname() const;
    const string&	StrFname() const;
    const string&	RecombFname() const;
    bool		NoRecombSum() const;
    unsigned int	MaxLatentDepth() const;
    path_strategy_type	PathStrategy() const;
    bool		AlleleFreq() const;
    unsigned int	NumNormals() const;
    const string&	RootPriorFname() const;
    bool		NoClades() const;
    bool		ExcludeNormals() const;
    const string&	NormalFname() const;
    unsigned int	Disease() const;
    const string&	DiseasedFname() const;
    unsigned int	NumOdh() const;
    criterion_type	Criterion() const;
    const string&	ComponentsFname() const;

protected:
    ~CommandLine() {}
    CommandLine();

    friend class Singleton<CommandLine>;
    
private:
    void Initialize();

public:
    struct Arg {
	virtual ~Arg() = 0;
	virtual CmdArg* cmdarg() = 0;
	virtual void assign() = 0;
	virtual void require() = 0;
	virtual bool given() const = 0;
	virtual bool value_given() const = 0;
	virtual void write(std::ostream&) const = 0;
    };

private:
    auto_ptr<Arg> _options[NUM_OPTIONS];

    unsigned int	_verbose;
    segment_type	_segment;
    unsigned int	_left_mask;
    unsigned int	_right_mask;
    double		_ssm;
    double		_p_mutation;
    double		_p_recombination;
    double		_ibd;
    string		_dist_fname;
    string		_str_fname;
    string		_recomb_fname;
    bool		_no_recomb_sum;
    unsigned int	_max_latent_depth;
    path_strategy_type	_path_strategy;
    bool		_allele_freq;
    unsigned int	_num_normals;
    string		_root_prior_fname;
    bool		_no_clades;
    bool		_exclude_normals;
    string		_normal_fname;
    unsigned int	_disease;
    string		_diseased_fname;
    unsigned int	_num_odh;
    criterion_type	_criterion;
    string		_components_fname;
};

#include "commandline_imp.h"

#endif /* GENETICS_COMMAND_LINE_H_INCLUDED */
