// src/backend/policy_parameters.hh - Copyright 2005, 2006, University
//               of Padova, dept. of Pure and Applied
//               Mathematics
//
// This file is part of SGPEMv2.
//
// This 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.
//
// SGPEMv2 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SGPEMv2; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

#ifndef POLICY_PARAMETERS_HH
#define POLICY_PARAMETERS_HH 1

#include "config.h"

#include <map>
#include <stdexcept>

#include "glibmm/ustring.h"

namespace sgpem
{

  class SG_DLLEXPORT PolicyParametersException : public std::runtime_error
  {
  public:
    PolicyParametersException(char* msg): std::runtime_error(msg) {}
  };



  /** \brief Represents all configurable parameters of a single scheduling policy.

    Represents all configurable parameters of a single scheduling policy. Is is used by the user
    interface: it serves to know which parameters the user will be asked for.
    Each Policy object owns only one instance of this class.
  */
  class SG_DLLEXPORT PolicyParameters
  {
  public:

    // -------------------------------------------------------------------------
    
    /** \brief This class represents a sigle parameter of type \c T

        This class is useful only to store informations about each parameter. No checks
        on the values entered are done.
    */
    template<typename T>
    class SG_DLLEXPORT Parameter
    {
    public:

      /** \brief Constructs the parameter
          \param name The name of the parameter. This string will be used to refer to this parameter, thus it MUST
          be uniqe (one string identifies \b only ONE parameter)
          \param value The initial value of this parameter
          \param lower_bound The lower limitation of the value which can be set with set_int(...).
          \param upper_bound The upper limitation of the value which can be set with set_int(...).
          \param required Denotes if this parameter is required by the policy.
          \param default_value The initial value of this parameter. (If not specified it's set to 0).
      */
      Parameter(Glib::ustring name, const T& value, 
                const T& lower_bound, const T& upper_bound, 
                const bool& required,  const T& default_value = 0);

      /** \returns The name of the parameter (its UNIQUE key)
       */
      Glib::ustring get_name() const;

      /** \returns The lower bound
       */
      T    get_lower_bound() const;

      /** \returns The upper bound
       */
      T    get_upper_bound() const;

      /** \returns TRUE if this parameter is required
       */
      bool   is_required() const;

      /** \returns Its default value
       */
      T    get_default() const;

      /** \returns Its actual value
       */
      T    get_value() const;

      /** \brief Changes the value of the parameter.
          \warning NO CHECK is done whether the value repects its bounds!!
      */
      void    set_value(const T&);

    private:
      Glib::ustring _name;
      T    _value;
      T    _lower_bound;
      T    _upper_bound;
      bool   _is_required;
      T    _default;
    };


    // ------------------------------------------------------------------

    //#######################################
    //########## methods to CREATE PARAMETERS
    //#######################################

    /**\brief Registers an INTEGER parameter.

     This method adds an INTEGER parameter to the list of parameters represented by this class.

     \warning If a parameter named \e name already exists it will be replaced by this one.
     \param name The name of the parameter. This string will be used to refer to this parameter
      in the methods set_int(...), get_int(...) and get_registered_int_parameters(...).
     \param lower_bound The lower limitation of the value which can be set with set_int(...).
     \param upper_bound The upper limitation of the value which can be set with set_int(...).
     \param required Denotes if this parameter is required by the policy.
     \param default_value The initial value of this parameter. (If not specified it's set to 0).
    */
    void register_int(Glib::ustring name, const int& lower_bound, const int& upper_bound, const bool& required, const int& default_value = 0);

    /**\brief Registers a FLOAT parameter.

     This method adds a FLOAT parameter to the list of parameters represented by this class.

     \warning If a parameter named \e name already exists it will be replaced by this one.
     \param name The name of the parameter. This string will be used to refer to this parameter
      in the methods set_float(...), get_float(...) and get_registered_float_parameters(...).
     \param lower_bound The lower limitation of the value which can be set with set_int(...).
     \param upper_bound The upper limitation of the value which can be set with set_int(...).
     \param required Denotes if this parameter is required by the policy.
     \param default_value The initial value of this parameter. (If not specified it's set to 0.0f).
    */
    void register_float(Glib::ustring name, const float& lower_bound, const float& upper_bound, const bool& required, const float& default_value = 0.0f);

    /**\brief Registers a STRING parameter.

     This method adds a STRING parameter to the list of parameters represented by this class.
     Note that there are no limitations to the value thath this parameter can assume.

     \warning If a parameter named \e name already exists it will be replaced by this one.
     \param name The name of the parameter. This string will be used to refer to this parameter
      in the methods set_string(...), get_string(...) and get_registered_string_parameters(...).
     \param required Denotes if this parameter is required by the policy.
     \param default_value The initial value of this parameter. (If not specified it's set to the empty string).
    */
    void register_string(Glib::ustring name, const bool& required, const Glib::ustring& default_value = "");


    /**\brief Deletes all registered parameters.
    */
    void clear();


    //#############################################
    //###### methods to RETRIEVE CREATED PARAMETERS
    //#############################################

    /** \brief Permits to retrieve all registered INTEGER parameters
     \returns a map of INTEGER parameters identfied by their name
    */
    std::map<Glib::ustring, Parameter<int> >    get_registered_int_parameters() const;

    /** \brief Permits to retrieve all registered FLOAT parameters
     \returns a map of FLOAT parameters identfied by their name
    */
    std::map<Glib::ustring, Parameter<float> >    get_registered_float_parameters() const;

    /** \brief Permits to retrieve all registered STRING parameters
     \returns a map of STRING parameters identfied by their name
    */
    std::map<Glib::ustring, Parameter<Glib::ustring> >  get_registered_string_parameters() const;


    //#############################################
    //###### methods to SET the VALUE of PARAMETERS
    //#############################################

    /** \brief Sets the value of a registred INTEGER parameter

     Permits to change the value of a parameter identified by "name"

     \returns TRUE if the specified "name" maps to a registered parameter and if "value" doesn't
      exceed the bounds proper to that parameter
     \returns FALSE if the parameter named "name" is not found or if "value" exceeds the bounds
    */
    bool  set_int(Glib::ustring name, const int& value);

    /** \brief Sets the value of a registred FLOAT parameter

     Permits to change the value of a parameter identified by "name"

     \returns TRUE if the specified "name" maps to a registered parameter and if "value" doesn't
      exceed the bounds proper to that parameter
     \returns FALSE if the parameter named "name" is not found or if "value" exceeds the bounds
    */
    bool  set_float(Glib::ustring name, const float& value);

    /** \brief Sets the value of a registred STRING parameter

     Permits to change the value of a parameter identified by "name"

     \returns TRUE if the specified "name" maps to a registered parameter and if "value" doesn't
      exceed the bounds proper to that parameter
     \returns FALSE if the parameter named "name" is not found or if "value" exceeds the bounds
    */
    bool  set_string(Glib::ustring name, const Glib::ustring& value);


    //#############################################
    //###### methods to GET the VALUE of PARAMETERS
    //#############################################

    /** \brief Returns the value of an INTEGER parameter
     \returns the INTEGER value of the parameter named \e name
     \throws PolicyParametersException if the parameter named \e name has not been registered
    */
    int     get_int(Glib::ustring name) const;

    /** \brief Returns the value of an FLOAT parameter
     \returns the FLOAT value of the parameter named \e name
     \throws PolicyParametersException if the parameter named \e name has not been registered
    */
    float     get_float(Glib::ustring name) const;

    /** \brief Returns the value of an STRING parameter
     \returns the STRING value of the parameter named \e name
     \throws PolicyParametersException if the parameter named \e name has not been registered
    */
    Glib::ustring   get_string(Glib::ustring name) const;



  private:
    std::map<Glib::ustring, Parameter<int> >   int_map;
    std::map<Glib::ustring, Parameter<float> >   float_map;
    std::map<Glib::ustring, Parameter<Glib::ustring> > string_map;
  };

}//~ namespace sgpem

#endif
