#ifndef _CONFIG_
#define _CONFIG_

#include "sys/sys"
#include "backenddef/backenddef"
#include "servertype/servertype"
#include "dispatchmode/dispatchmode"
#include "error/error"
#include "ThreadsAndMutexes/mutex/mutex"
#include "backendcheck/backendcheck"

using namespace std;

class Config {
public:
    Config ();

    // Init by cmdline
    void parsecmdline (int ac, char **av);

    // Accessors
    bool verbose() const 		{ return (verbose_flag); }
    void verbose (bool v)		{ verbose_flag = v; }

    bool debug() const			{ return (debug_flag); }
    void debug (bool d)			{ debug_flag = d; }

    unsigned quitafter() const		{ return (quit_after); }

    Servertype::Type stype() const 	{ return (styp.type()); }
    void stype(string const &s)		{ styp.type(s); }
    string stypestr() const  		{ return (styp.typestr()); }
    string const &sipaddr() const 	{ return (sip); }
    int sport() const 			{ return (lport); }

    int backends() const 		{ return (blist.size()); }

    /* PID file */
    void pidfile(string const &s);
    string const &pidfile() {
	return pid_file;
    }

    /* Client timeouts */
    unsigned client_read_timeout() const {
	return (c_timeout);
    }
    void client_read_timeout (unsigned c) {
	c_timeout = c;
    }
    unsigned client_write_timeout() const {
	return c_write_timeout;
    }
    void client_write_timeout(unsigned c) {
	c_write_timeout = c;
    }

    /* Back end timeouts */
    unsigned backend_read_timeout() const {
	return (b_timeout);
    }
    void backend_read_timeout (unsigned b) {
	b_timeout = b;
    }
    unsigned backend_write_timeout() const {
	return b_write_timeout;
    }
    void backend_write_timeout(unsigned b) {
	b_write_timeout = b;
    }

    unsigned wakeupsec() const		{ return (wakeup); }
    void wakeupsec (unsigned w)		{ wakeup = w; }

    unsigned checkupsec() const 	{ return (checkup); }
    void checkupsec (unsigned w)	{ checkup = w; }

    unsigned buffersize() const 	{ return (bufsize); }
    void buffersize (unsigned b);

    bool foregroundmode() const 	{ return (foreground_mode); }

    bool addxrversion() const 		{ return (add_xr_version); }
    void addxrversion (bool b);

    bool addxforwardedfor() const 	{ return (add_x_forwarded_for); }
    void addxforwardedfor (bool b);

    bool stickyhttp() const		{ return (sticky_http); }
    void stickyhttp(bool b);

    bool replacehostheader() const	{ return replace_host_header; }
    void replacehostheader(bool s)	{ replace_host_header = s; }

    unsigned maxconn() const		{ return (max_conn); }
    void maxconn (unsigned m);

    string const &externalalgorithm() const {
	return (external_algorithm);
    }

    bool prefixtimestamp() const	{ return (prefix_timestamp); }
    void prefixtimestamp (bool p);

    bool fastclose() const		{ return (fast_close); }
    void fastclose (bool f);

    bool usewebinterface() const	{ return use_webinterface; }
    string const &webinterfaceip() const {
	return webinterface_ip;
    }
    int webinterfaceport() const	{ return webinterface_port; }

    unsigned nserverheaders() const	{ return (serverheaders.size()); }
    string const &serverheader (unsigned n) {
	return (serverheaders[n]);
    }
    void addserverheader (string const &s);
    void removeserverheader (unsigned i);
    void changeserverheader (unsigned i, string const &s);

    string const &dumpdir() const	{ return (dump_dir); }
    void dumpdir (string s)		{ dump_dir = s; }

    unsigned softmaxconnrate() const	{ return soft_maxconnrate; }
    void softmaxconnrate(unsigned n)	{ soft_maxconnrate = n; }
    unsigned hardmaxconnrate() const	{ return hard_maxconnrate; }
    void hardmaxconnrate(unsigned n)	{ hard_maxconnrate = n; }
    unsigned defertime() const		{ return defer_time; }
    void defertime(unsigned n)		{ defer_time = n; }
    unsigned connrate_time() const	{ return connrate_timeinterval; }
    void connrate_time(unsigned n)	{ connrate_timeinterval = n; }

    unsigned dnscachetimeout() const 	{ return dns_cache_timeout; }
    void dnscachetimeout(unsigned t)	{ dns_cache_timeout = t; }
    
    unsigned nallow() const		{ return (allowlist.size()); }
    unsigned ndeny() const		{ return (denylist.size()); }
    void addallow (string a);
    void adddeny (string d);
    void changeallow(string &a, unsigned index);
    void changedeny(string &a, unsigned index);
    void deleteallow(unsigned index);
    void deletedeny(unsigned index);
    
    int ipstoretimeout() const		{ return (ipstore_timeout); }
    void ipstoretimeout(int t);
    struct in_addr allow(unsigned n) const {
        return (allowlist[n]);
    }
    struct in_addr deny(unsigned n) const {
        return (denylist[n]);
    }

    BackendDef const &backend (int i) const {
	return (blist[i]);
    }
    Dispatchmode::Mode dispatchmode() const {
	return (dmode.mode());
    }
    string dispatchmodestr() const {
	return (dmode.modestr());
    }
    bool removereservations() const {
	return remove_reservations;
    }
    void removereservations(bool b) {
	remove_reservations = b;
    }

    string const &softmaxconnexcess() const {
	return soft_maxconn_excess_prog;
    }
    void softmaxconnexcess(string const &s) {
	soft_maxconn_excess_prog = s;
    }
    string const &hardmaxconnexcess() const {
	return hard_maxconn_excess_prog;
    }
    void hardmaxconnexcess(string const &s) {
	hard_maxconn_excess_prog = s;
    }

    void onstart(string s)		{ on_start = s; }
    string const &onstart() const	{ return on_start; }
    void onend(string s)		{ on_end = s; }
    string const &onend() const		{ return on_end; }
    void onfail(string s)		{ on_fail = s; }
    string const &onfail() const	{ return on_fail; }

    /* Restart of program */
    void restart();

private:
    void setbackend (string const &s, string const &hostmatch,
		     string const &urlmatch,
		     BackendCheck const &bc);
    void setwebinterface (string s);
    void setserver (string s);
    void setdispatchmode (string s);
    int  setinteger (string s) const;

    static string pid_file;
    static bool verbose_flag;
    static int lport;
    static Servertype styp;
    static string sip;
    static vector<BackendDef> blist;
    static Dispatchmode dmode;
    static unsigned c_timeout, c_write_timeout;
    static unsigned b_timeout, b_write_timeout;
    static unsigned wakeup;
    static unsigned checkup;
    static unsigned bufsize;
    static bool foreground_mode;
    static bool add_xr_version;
    static bool debug_flag;
    static bool add_x_forwarded_for;
    static bool sticky_http;
    static bool replace_host_header;
    static unsigned max_conn;
    static string external_algorithm;
    static bool prefix_timestamp;
    static vector<string> serverheaders;
    static vector<struct in_addr> allowlist;
    static vector<struct in_addr> denylist;
    static bool fast_close;
    static int ipstore_timeout;
    static bool use_webinterface;
    static string webinterface_ip;
    static int webinterface_port;
    static string dump_dir;
    static unsigned soft_maxconnrate;
    static unsigned hard_maxconnrate;
    static unsigned defer_time;
    static unsigned connrate_timeinterval;
    static unsigned quit_after;
    static string soft_maxconn_excess_prog;
    static string hard_maxconn_excess_prog;
    static unsigned dns_cache_timeout;
    static string on_start, on_end, on_fail;
    static bool remove_reservations;
    static char **org_argv;
};

extern Config config;

#endif
