text: #pragma once
  #include <list>
  #include <tinychain/tinychain.hpp>
  #include <tinychain/node.hpp>
  #include <metaverse/mgbubble/Mongoose.hpp>
  #include <metaverse/mgbubble/utility/Stream_buf.hpp>
  #include <metaverse/mgbubble/utility/Tokeniser.hpp>
  #include <metaverse/mgbubble/exception/Instances.hpp>
  
  
  namespace mgbubble{
  
  
  class RestServ : public Mgr<RestServ>
  {
  public:
      explicit RestServ(const char* webroot, tinychain::node& node):node_(node)
      {
          memset(&httpoptions_, 0x00, sizeof(httpoptions_));
          document_root_ = webroot;	
          httpoptions_.document_root = document_root_.c_str();
      }
      ~RestServ() noexcept {};
  
      void run() {
          for (;;)
              this->poll(1000);
      }
  
      // Copy.
      RestServ(const RestServ& rhs) = delete;
      RestServ& operator=(const RestServ& rhs) = delete;
  
      // Move.
      RestServ(RestServ&&) = delete;
      RestServ& operator=(RestServ&&) = delete;
  
      //reset
      void reset(HttpMessage& data) noexcept;
  
      //request
      void httpStatic (mg_connection& nc, HttpMessage data);
      void httpRequest (mg_connection& nc, HttpMessage data);
      void httpRpcRequest (mg_connection& nc, HttpMessage data);
      void websocketBroadcast (mg_connection& nc, const char* msg, size_t len);
      void websocketSend(mg_connection* nc, const char* msg, size_t len);
      void websocketSend(mg_connection& nc, WebsocketMessage ws);
  
      // http session
      bool user_auth(mg_connection& nc, HttpMessage data);
      mg_serve_http_opts& get_httpoptions(){return httpoptions_;}
      std::shared_ptr<Session> get_from_session_list(HttpMessage data);
      bool remove_from_session_list(HttpMessage data);
      std::shared_ptr<Session> push_session(HttpMessage data);
      bool check_sessions();
  
      std::pair<string_view,string_view> user_check(HttpMessage &data)
      {
         auto user = data.header("user");
         auto password = data.header("pass");
      
         if (user.empty() || password.empty()) {
        	    throw std::logic_error("authorisation required");
         }
         return std::make_pair(user, password);
      }
  
      
  private:
      enum : int {
        // Method values are represented as powers of two for simplicity.
        MethodGet = 1 << 0,
        MethodPost = 1 << 1,
        MethodPut = 1 << 2,
        MethodDelete = 1 << 3,
        // Method value mask.
        MethodMask = MethodGet | MethodPost | MethodPut | MethodDelete,
      
        // Subsequent bits represent matching components.
        MatchMethod = 1 << 4,
        MatchUri = 1 << 5,
        // Match result mask.
        MatchMask = MatchMethod | MatchUri
      };
  
      bool isSet(int bs) const noexcept { return (state_ & bs) == bs; }
  
      // http
      mg_serve_http_opts httpoptions_;
  #if MVS_DEBUG
      constexpr static const double SESSION_TTL = 900.0;
  #else
      constexpr static const double SESSION_TTL = 240.0;
  #endif
      std::list< std::shared_ptr<Session> > session_list_;
  
      // config
      static thread_local OStream out_;
      static thread_local Tokeniser<'/'> uri_;
      static thread_local int state_;
      //const char* const servername_{"Http-Metaverse"};
      std::string document_root_;
  
      tinychain::node& node_;
  };
  
  } // mgbubble
  