#line 1971 "/home/travis/build/felix-lang/felix/src/packages/web.fdoc"
  include "web/__init__";
  
  class ServerConfig {
    open HTTPHandler;
    open Logger;
    open SimpleConfig;
    open Assoc_list;
  
    struct server_config {
          delay : double;
          port : int;
          server_root : string;
          document_root : string;
          handlers: list[http_handler];
          log:log_message->void;
          params:list[string*string];
          file_name:string;
          application:string;
    };
  
  
  
    ctor server_config(handlers:list[http_handler]) =>
      server_config(0.05,8080,".","./html",handlers,
      logger(console_logger(INFO)+console_logger(ERROR)),Empty[string*string],"","");
  
    ctor server_config(handlers:list[http_handler],app:string) =>
      server_config(0.05,8080,".","./html",handlers,
      logger(console_logger(INFO)+console_logger(ERROR)),Empty[string*string],"",app);
  
  
    fun basic_server_config(handlers:list[http_handler]):server_config = {
      var cfg = server_config(handlers);
      match enhance_with_config_file(
       enhance_with_command_line_arguments(cfg)) with
      |Some(cfg),_ => return cfg;
      |None,m => return cfg;
      endmatch;
  
    }
  
    fun basic_server_config(handlers:list[http_handler],application:string,default_config:string):server_config = {
      var config = server_config(handlers,application);
      match enhance_with_config_file(
        enhance_with_command_line_arguments(config)) with
      |Some(cfg),_ => return cfg;
      |None,m =>  set_params(&config,read_config_text(default_config));
                   return config;
      endmatch;
  
   }
  
    fun enhance_with_command_line_arguments(var config:server_config):server_config = {
      var cfg:server_config = config;
      var arg = "";
      var argno = 1;
      while argno<System::argc do
        arg = System::argv argno;
        println$ "ARG=" + arg;
        if prefix(arg,"--document_root=") do
          cfg.document_root = arg.[16 to];
        elif prefix(arg,"--server_root=") do
          cfg.server_root = arg.[14 to];
        elif prefix(arg,"--port=") do
          cfg.port = atoi arg.[7 to];
        elif prefix(arg,"--config=") do
          cfg.file_name = arg.[9 to];
          if( not (FileStat::fileexists(cfg.file_name))) do
            proc_fail("unable to open config file:"+cfg.file_name);
          done
        elif prefix(arg,"--debug") do
          var dbg_log:list[log_handler];
          if prefix(arg,"--debug=") do
            val file:string =  str(arg.[8 to]);
            dbg_log = simple_logger(Logger::log("log",file,size(0),0ui),DEBUG);
          else
            dbg_log = console_logger(DEBUG);
          done;
          cfg.log = logger(console_logger(INFO)+console_logger(ERROR)+dbg_log);
        elif prefix(arg,"--help") do
          println("Usage: "+(System::argv 0)+""" [OPTION]
    --document-root=PATH    Path to document root directory defaults to ./html
    --server-root=PATH      Path to server root direcory defaults to cwd
    --port=PORT             Port to listen on
    --debug                 Logs DEBUG messages to STDOUT
    --debug=FILE            Logs DEBUG to log/FILE
  """);
          System::exit(0);
        done
        ++argno;
      done
      return (cfg);
    }
  
    private fun tolower: char->char = "(char)::std::tolower($1)" requires Cxx_headers::cctype ;
    private fun toupper: char->char = "(char)::std::toupper($1)" requires Cxx_headers::cctype ;
  
  
    fun enhance_with_config_file(config:server_config):opt[server_config]*string = {
      var cfg = config;
      val config_file_default = Filename::join("config","server_config.cfg");
      val enviro_config = Env::getenv((map toupper cfg.application)+"_CFG","");
      if cfg.file_name == "" do
          if enviro_config  == "" do
              var cwd_config = Filename::join(".",config_file_default);
              if FileStat::fileexists(cwd_config) do
                  cfg.file_name = cwd_config;
              else
                  var home = Env::getenv("HOME","");
                  if home == "" do
                     return None[server_config],"Unable to open configuration file HOME environment variable undefined.";
                  else
                      var home_config = Filename::join(home,
                      Filename::join(".felix",Filename::join(cfg.application,config_file_default)));
                      if FileStat::fileexists(home_config) do
                          cfg.file_name = home_config;
                      else
                          return None[server_config],("Unable to open configurationfile:" + home_config);
                      done
                  done
              done
          else
              if FileStat::fileexists(enviro_config) do
                  cfg.file_name = enviro_config;
              else
                  return None[server_config],("Unable to open configurationfile:" + enviro_config);
              done
          done
      else
          if not(FileStat::fileexists(cfg.file_name)) do
              return None[server_config], ("Unable to open configurationfile:" + cfg.file_name);
          done
      done
      set_params(&cfg,read_config(cfg.file_name));
      return Some(cfg),("Configuration file " + cfg.file_name + " read.");
    }
  
    proc set_params(cfg:&server_config,params:list[string^2]) {
      *cfg.params = params;
      match find (fun (a:string,b:string) => eq(a,b)) params "port" with
        |Some s => *cfg.port = int(s);
        |_ => {}();
      endmatch;
      match find (fun (a:string,b:string) => eq(a,b)) params "server_root" with
        |Some s => *cfg.server_root = s;
        |_ => {}();
      endmatch;
      match find (fun (a:string,b:string) => eq(a,b)) params "document_root" with
        |Some s => *cfg.document_root = s;
        |_ => {}();
      endmatch;
      match find (fun (a:string,b:string) => eq(a,b)) params "delay" with
        |Some s => *cfg.delay = double(s);
        |_ => {}();
      endmatch;
  
    }
  
    fun strtod: string -> double = "strtod($1.data(),0)";
  
  
    instance Str[server_config] {
      fun str (cfg : server_config):string =>
         "Config file:" + cfg.file_name "\n" +
         (fold_left (fun(i:string) (c:string^2):string =>
           (i + c.(0) + " = " + c.(1) + "\n") ) "" (cfg.params));
    }
  
  }