#include "../interprocess/shared_memory/profinet_shared_data.hpp"
#include <cstring>

using namespace boost::interprocess;

/**
 * @brief Расчет размера данных для выделения памяти
 * 
 * @param data_settings 
 * @return uint32_t 
 */
static uint32_t calc_mem_size(ProfinetData_Map& data_settings)
{
    uint32_t size = 0;
    for (int i = 0; i < data_settings.mods_nbr; ++i)
    {
        auto& submods = data_settings.p_mods[i].p_submods;
        
        for (int j = 0; j < data_settings.p_mods[i].submods_nbr; ++j)
        {
            auto& submod = submods[j];

            size+= submod.cyc_indata_len + submod.cyc_outdata_len;

            auto& params = submod.p_params;

            for (int k = 0; k < submod.params_nbr; ++k)
            {
                size+= params[i].length;
            }
        }
    }

    return size + sizeof(ProfinetData_Map);
}

ProfinetData_Map * ProfinetSharedData::Create(std::string mem_name)
{
    /// Если память уже выделена, удаляем
    shared_memory_object::remove(mem_name.c_str());
    /// Для начала выделяем 65к байт. Потом вызывается функция checkMemorySize и размер моджет быть увеличен
    shmem_ = managed_shared_memory{create_only, mem_name.c_str(), 65536};
    mem_name_ = mem_name;
    ///Создаем данные в разделяемой памяти
    p_profinet_data_ = shmem_.construct<ProfinetData_Map>("ProfinetData_Map")();
    return p_profinet_data_;
}

void ProfinetSharedData::checkMemorySize(uint32_t required_mem_size)
{
    uint32_t free_size = shmem_.get_size();

    if (required_mem_size < free_size)
        return;

    /// Увеличиваем память
    managed_shared_memory::grow(mem_name_.c_str(), required_mem_size - free_size);
    
    /// Заново открываем память(может измениться указатель)
    shmem_ = managed_shared_memory{open_only, mem_name_.c_str()};

    /// Заново находим или создаем структуру ProfinetData_Map
    p_profinet_data_ = shmem_.find_or_construct<ProfinetData_Map>("ProfinetData_Map")();
}

