import six


def check_pg_num(pool, pg_num, size, num_osds=0, max_pgs_per_osd=200, pools={}):
    """
    Returns empty string only if the Pool PG numbers are correct for the OSDs.
    Otherwise returns an error message like the one Ceph would return.
    """
    # The original check in C++ from the Ceph source code is:
    #
    # int OSDMonitor::check_pg_num(int64_t pool, int pg_num, int size, ostream *ss)
    # {
    #   auto max_pgs_per_osd = g_conf->get_val<uint64_t>("mon_max_pg_per_osd");
    #   auto num_osds = std::max(osdmap.get_num_in_osds(), 3u); // assume min cluster size 3
    #   auto max_pgs = max_pgs_per_osd * num_osds;
    #   uint64_t projected = 0;
    #   if (pool < 0) {
    #     projected += pg_num * size;
    #   }
    #   for (const auto& i : osdmap.get_pools()) {
    #     if (i.first == pool) {
    #       projected += pg_num * size;
    #     } else {
    #       projected += i.second.get_pg_num() * i.second.get_size();
    #     }
    #   }
    #   if (projected > max_pgs) {
    #     if (pool >= 0) {
    #       *ss << "pool id " << pool;
    #     }
    #     *ss << " pg_num " << pg_num << " size " << size
    # 	<< " would mean " << projected
    # 	<< " total pgs, which exceeds max " << max_pgs
    # 	<< " (mon_max_pg_per_osd " << max_pgs_per_osd
    # 	<< " * num_in_osds " << num_osds << ")";
    #     return -ERANGE;
    #   }
    #   return 0;
    # }
    msg = ""
    max_pgs = max_pgs_per_osd * num_osds
    projected = 0
    if len(pool) < 0:
        projected = projected + (pg_num * size)
    for pool_name, pool_sizes in six.iteritems(pools):
        if pool_name == pool:
            projected = projected + (pg_num * size)
        else:
            projected = projected + (int(pool_sizes['pg_num']) * int(pool_sizes['size']))
    if projected > max_pgs:
        msg = "Cannot add pool: " + str(pool) + \
              " pg_num " + str(pg_num) + " size " + str(size) + \
              " would mean " + str(projected) + \
              " total pgs, which exceeds max " + str(max_pgs) + \
              " (mon_max_pg_per_osd " + str(max_pgs_per_osd) + \
              " * num_in_osds " + str(num_osds) + ")"
    return msg