#ifndef DISPATCHERS_H
#define DISPATCHERS_H

#include "session_common.h"

/*
Item of the day:
class Result {
    // holds unique_ptr or shared_ptr to the "dispatcher"
    // when I'm done -- delete the result, cleaning up
    // the dispatcher

}

 How does this call another?
 How does it return a result?

possibly:  io_service::post( DONE );  !

 */

class Session;

class Dispatch {
protected:
  Session *sess;
  notifyFunc notify_;

public:
  Dispatch(Session *);
  virtual ~Dispatch();

  void setNotify(notifyFunc nf);
  void notify(void);

  virtual void activate(void) = 0;
  virtual void deactivate(void) = 0;

  const std::string &get_prompt(void);
  void to_server(const std::string &send);
  void to_client(const std::string &send);
};



class InputDispatch : public Dispatch {
private:
  DispatchSettings ds;

public:
  InputDispatch(Session *);

  std::string prompt;
  size_t max_length;
  std::string input;

  void activate(void) override;
  void deactivate(void) override;

  // optional here
  void server_line(const std::string &line);
  // void server_prompt(const std::string &prompt);
  void client_input(const std::string &cinput);
};


/**
 * The main/first proxy Dispatcher.
 * 
 * Don't follow this as an example.  On disable,
 * it resets everything back to nothing active.
 * (Which is likely not what you want.)
 * 
 */

class MainDispatch : public Dispatch {
private:
  InputDispatch id;

public:
  MainDispatch(Session *);
  ~MainDispatch();

  void activate(void) override;
  void deactivate(void) override;

  void have_input(void);

  void server_line(const std::string &line);
  void server_prompt(const std::string &prompt);
  // void client_input(const std::string &input);

private:
  int count;
  std::string old_prompt;
};



class MenuDispatch : public Dispatch {
public:
  MenuDispatch(Session *);

  void activate(void) override;
  void deactivate(void) override;

  // optional here
  void server_line(const std::string &line);
  void server_prompt(const std::string &prompt);
  void client_input(const std::string &input);
};



class CoreDispatch : public Dispatch {
public:
  CoreDispatch(Session *);

  void activate(void) override;
  void deactivate(void) override;

  // optional here
  void server_line(const std::string &line);
  void server_prompt(const std::string &prompt);
  void client_input(const std::string &input);
};

#include "session.h"

#endif