#ifndef LAYER_H
#define LAYER_H
#include <string>
#include <map>
#include <vector>

typedef std::map<std::string, std::string> Params;
class OCTETSTRING;

class Layer {
  std::vector<Layer*> upperLayers;
  std::vector<Layer*> lowerLayers;
  public:
    Layer(){}
  public:
    void addUpperLayer(Layer*);
    void removeUpperLayer(Layer*);

    virtual void sendData(const OCTETSTRING& data, const Params& params);
    virtual void receiveData(const OCTETSTRING& data, const Params& info);

  protected:
    void toAllLayers(std::vector<Layer*>&layers, const OCTETSTRING& data, const Params& info);
    inline void receiveToAllLayers(const OCTETSTRING& data, const Params& info) { toAllLayers(upperLayers, data, info); }
    inline void sendToAllLayers(const OCTETSTRING& data, const Params& info)  { toAllLayers(lowerLayers, data, info); }
};

template <typename TPort> class TLayer : public Layer {
  typedef std::vector<TPort*> TPortList;
  TPortList upperPorts;
  public:
    TLayer(){}
    void addUpperPort(TPort*);
    void removeUpperPort(TPort*);
/*
    template <typename Msg> void receiveToAllPorts(Msg* m, const Param& param) {
      for(TPortList::iterator it=upperPorts.begin(); it<upperPorts.end(); ++it){
        (*it)->receiveMsg(m, param);
      }
    }
*/
};

class LayerFactory {
  public:
   LayerFactory(){}
   virtual Layer * createLayer(const std::string & type, const std::string &  param) = 0;
};

class StackFactory {
   static StackFactory * _instance;
   std::map<std::string,LayerFactory*> _fs;
  public:
   static StackFactory * getInstance();

   void registerLayerFactory(const std::string & type, LayerFactory * f);
   Layer* createLayerStack(const char*);
};

#endif