//-*-c++-*
/**
 Author: David Auber
 Email : auber@labri.fr
 Last modification : 26/09/2001
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by  
 the Free Software Foundation; either version 2 of the License, or     
 (at your option) any later version.
*/

#ifndef TULIP_PROPERTYPROXYCONTAINER_H
#define TULIP_PROPERTYPROXYCONTAINER_H

#include <typeinfo>
#include <map>
#include <set>
#include <stack>
#include "SuperGraph.h"
#include "Iterator.h"
#include "PluginContext.h"
#include "PluginProgress.h"
//#include "Types.h"
//#include "TemplateFactory.h"




class PProxy;

/**
   This class is a pool of PropertyProxy, It also manages the inheritance
   of PropertyProxy beetween views.
*/
class PropertyProxyContainer
{
public:
  PProxy* currentPropertyProxy;
  SuperGraph *superGraph;
  ///
  virtual ~PropertyProxyContainer(){};
  /**
     Return true if the propertyProxy is in the pool, or 
     in a ascendant SuperGraph
  */
  virtual  bool existProxy(const std::string&)=0;
  /**Return true if the propertyProxy is in the pool*/
  virtual  bool existLocalProxy(const std::string&)=0;
  /**Add a PropertyProxy in the pool*/
  virtual  void setLocalProxy(const std::string&,PProxy *)=0;
  /**Return a pointer to a propertyProxy which is in the pool or
     in a pool of an ascendant SuperGraph*/
  virtual  PProxy* getProxy(const std::string&)=0;
  /**Return a pointer to a propertyProxy which is in the pool*/
  virtual  PProxy* getLocalProxy(const std::string&)=0;
  /**Remove a PropertyProxy from the pool*/
  virtual  void delLocalProxy(const std::string&)=0;
  ///
  virtual void update() =0;
  /**Used to inform the pool that a node doesn't belong anymore to the
     associated SuperGraph*/
  virtual void erase(const node )=0;
  /**Used to inform the pool that an edge doesn't belong anymore to the
     associated SuperGraph*/
  virtual void erase(const edge )=0;
  /**Return an iterator on the local properties*/
  virtual Iterator<std::string>* getLocalProperties()=0;
  /**Return an iterator on the inherited properties*/
  virtual Iterator<std::string>* getInheritedProperties()=0;
};

//========================================================================================
/**The following functions enbables to restore the type of PropertyProxy in the pool*/
/**Return a pointer to a propertyProxy which is in the pool.
   The real type of the propertyproxy is tested with the template parameter.
   If the propertyProxy is in the pool the cached value return true else false.
   The resultBool value indicate if the check algorithm of the associated property was ok;
   The resultStr is the error message which has been return by the Property.*/
template<class Proxytype>
Proxytype* getLocalProxy(SuperGraph *supergraph,const std::string &st,bool &cached ,bool &resultBool ,std::string &resultStr,PluginProgress *plugProgress=0,DataSet *dataSet=0);
/**Return a pointer to a propertyProxy which is in the pool.
   The real type of the propertyproxy is tested with the template parameter.
   If the propertyProxy is not the pool it creates a new one and return it.*/
template<class Proxytype>
Proxytype* getLocalProxy(SuperGraph *supergraph,const std::string &st);
/**Return a pointer to a propertyProxy which is in the pool or in the pool of an ascendant.
   The real type of the propertyproxy is tested with the template parameter.
   If the propertyProxy is in the pool the cached value return true else false.
   The resultBool value indicate if the check algorithm of the associated property was ok;
   The resultStr is the error message which has been return by the Property.*/
template<class Proxytype>
Proxytype* getProxy(SuperGraph *supergraph,const std::string &st,bool &cached,bool &resultBool ,std::string &resultStr,PluginProgress *plugProgress=0,DataSet *dataSet=0);
/**Return a pointer to a propertyProxy which is in the pool or in the pool of an ascendant
   The real type of the propertyproxy is tested with the template parameter.
   If the propertyProxy is not the pool it creates a new one and return it.*/
template<class Proxytype>
Proxytype* getProxy(SuperGraph *supergraph,const std::string &st);
//======================================================================================
class PropertyProxyContainerImpl;
//======================================================================================
class LocalPropertiesIterator: public Iterator<std::string>
{
public:
  LocalPropertiesIterator(PropertyProxyContainerImpl *ppc);
  std::string next();
  bool hasNext();
private:
  PropertyProxyContainerImpl *ppc;
  std::map<std::string,PProxy*>::iterator it,itEnd;
};
//======================================================================================
class InheritedPropertiesIterator: public Iterator<std::string>
{
  struct ltstr
  {
    bool operator()(const std::string &s1, const std::string &s2) const
    {return s1.compare(s2) < 0;}
  };
public:
  InheritedPropertiesIterator(PropertyProxyContainer *ppc);
  std::string next();
  bool hasNext();
private:
  PropertyProxyContainer *ppc;
  std::set<std::string,ltstr> inhList; 
  std::set<std::string,ltstr>::iterator it,itEnd;
};
//======================================================================================
/**
   Implemantation of the interface PropertyProxyContainer.
 */
class PropertyProxyContainerImpl: public PropertyProxyContainer
{
  friend class LocalPropertiesIterator;

private:
  ///
  std::map<std::string,PProxy*> propertyProxyMap;

public:
  ///
  explicit  PropertyProxyContainerImpl(SuperGraph*);
  ///
  ~PropertyProxyContainerImpl();
  //======================================================================================
  bool existProxy(const std::string&);
  bool existLocalProxy(const std::string&);
  void setProxy(const std::string&,PProxy *);
  void setLocalProxy(const std::string&,PProxy *);
  PProxy* getProxy(const std::string&);
  PProxy* getLocalProxy(const std::string&);
  void delProxy(const std::string&);
  void delLocalProxy(const std::string&);
  void erase(const node );
  void erase(const edge );
  //======================================================================================
  Iterator<std::string>* getLocalProperties();
  Iterator<std::string>* getInheritedProperties();
  ///
  void update();
};

#include "./cxx/PropertyProxyContainer.cxx"
#endif





