#ifndef _DB_MYSQL_DIFFSQLGEN_GRANT_H_
#define _DB_MYSQL_DIFFSQLGEN_GRANT_H_

#include "grtpp_module_cpp.h"
#include "grts/structs.db.mysql.h"
#include "db_mysql_params.h"

static std::string get_type_str_for_grant(const db_DatabaseObjectRef &obj)
{
  if (db_TableRef::can_wrap(obj))
    return "TABLE";

  if (db_ViewRef::can_wrap(obj))
    return "TABLE";

  if (db_mysql_RoutineRef::can_wrap(obj))
    return db_mysql_RoutineRef::cast_from(obj)->routineType();

  return "";
}

inline void MYSQLMODULEDBMYSQL_PUBLIC_FUNC gen_grant_sql(const db_UserRef &user, db_RoleRef &role, std::list<std::string> &out)
{
  db_RoleRef parentRole = role->parentRole();
  if (parentRole.is_valid())
    gen_grant_sql(user, parentRole, out);

  for(size_t i= 0, count= role->privileges().count(); i < count; ++i)
  {
    db_RolePrivilegeRef priv= role->privileges().get(i);
    for(size_t i= 0, count= priv->privileges().count(); i < count; ++i)
    {
      std::string privilege_str= priv->privileges().get(i);
      std::string object_str;
      db_DatabaseObjectRef object = priv->databaseObject();
      if (object.is_valid())
        object_str= get_type_str_for_grant(object) +" "+ dbmysql::full_name(object);
      else
        object_str= *priv->databaseObjectType() +" "+ *priv->databaseObjectName();

      out.push_back( "grant "+ privilege_str +" on "+ object_str +" to "+ *user->name());
    }
  }
}

inline void MYSQLMODULEDBMYSQL_PUBLIC_FUNC gen_grant_sql(const db_UserRef &user, std::list<std::string> &out)
{
  for(size_t i= 0, count= user->roles().count(); i < count; ++i)
  {
    db_RoleRef role= user->roles().get(i);
    gen_grant_sql(user, role, out);
  }
}


inline void MYSQLMODULEDBMYSQL_PUBLIC_FUNC gen_grant_sql(const db_CatalogRef &catalog, std::list<std::string> &out)
{
  for(size_t i= 0, count= catalog->users().count(); i < count; ++i)
  {
    db_UserRef user= catalog->users().get(i);
    gen_grant_sql(user, out);
  }
}


#endif // _DB_MYSQL_DIFFSQLGEN_H_
