#ifndef CONFIG_READ_H
#define CONFIG_READ_H

#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <vector>

namespace p2c
{

//parse helper
static void split(const std::string& in, const char delim, std::vector<std::string> &out)
{
    std::stringstream ss(in);
    std::string token;
    out.clear();

    while(std::getline(ss, token, delim))
    {
        out.push_back(token);
    }
}

static bool read_config_file(const std::string&filename, std::map<std::string, std::map<std::string, std::string> >& data)
{
    size_t fp;
    std::ifstream ifs;
    std::stringstream ss;
    std::vector<std::string> tokens;
    std::string cur_group;

    ifs.open(filename);

    if (!ifs)
    {
        return false;
    }

    std::string line;
    // std::getline(ifs, line);

    do
    {
        std::getline(ifs, line);
        ss.clear();
        ss.str(line);


        if (line.empty() || line[0] == '#')
            continue;


        fp = line.find('[');
        if (fp != std::string::npos)
        {
            cur_group = line.substr(fp+1, line.find(']',fp+1)-1);
            continue;
        }

        std::map<std::string, std::string> &cur_group_map = data[cur_group];

        split(line, '=', tokens);

        cur_group_map[tokens[0]] = tokens[1];
    }
    while(ifs.good());

/*
    //replace all
    for (std::map<std::string, std::string>::iterator it = data.begin(); it != data.end(); ++it)
    {
        std::string& value = it->second;
        size_t p=0;
        while ( (p = value.find("${",p) ) != std::string::npos)
        {
            //find size of string-to-replace ( -(p+2) since we want to skip '${' )
            const size_t string_size = value.find('}') - (p+2);
            //create substring of string-to-replace
            const std::string replace_key = value.substr(p+2, string_size);
            //find substracted key in key-value-map
            std::map<std::string, std::string>::iterator replace_it = data.find(replace_key);

            if (replace_it != data.end()) //found key in map, replace it!
            {
                const std::string &replace_string = replace_it->second;
                //replace in value; +3 since we have to take '$}' and '}' into account
                value.replace(p, string_size+3, replace_string);
                p += replace_string.size();
            }
            else //could not find key; not in config!
            {
                std::cerr << "Config::read_config_file: [WARNING] Could not replace \"" << replace_key << "\"." << std::endl;
                p += 2;
            }
        }
    }
*/
    ifs.close();

    return true;
}

static bool write_config_from_data(std::map<std::string, std::map<std::string, std::string> >& data,
                                   std::string filename)
{
    std::ofstream of(filename);
    if (!of)
    {
        printf("[ERROR] Cannot open filename %s for config write\n", filename.c_str());
        return false;
    }

    for (auto& group : data)
    {
        of << "[" << group.first << "]" << std::endl;

        for (auto& config_item : group.second)
        {
            of << config_item.first << "=" << config_item.second << std::endl;
        }

        of << std::endl;
    }

    of.close();

    return true;
}

template <typename T>
static void set_config_value(std::map<std::string, std::map<std::string, std::string> >& data,
                             std::string group, std::string name, T value)
{
    std::stringstream ss;
    ss << value;
    data[group][name] = ss.str();
}

}

#endif // CONFIG_READ_H
