/*
 * Author:
 *   Sven Czarnian <devel@svcz.de>
 * Brief:
 *   Implements the communication file format
 * Copyright:
 *   2021 Sven Czarnian
 * License:
 *   GNU General Public License v3 (GPLv3)
 */

#include <fstream>

#include <gsl/gsl>

#include <aman/config/CommunicationFileFormat.h>
#include <aman/helper/String.h>

using namespace aman;

CommunicationFileFormat::CommunicationFileFormat() :
        FileFormat() { }

bool CommunicationFileFormat::parse(const std::string& filename, Communication& config) {
    config.valid = true;

    std::ifstream stream(filename);
    if (false == stream.is_open()) {
        this->m_errorMessage = "Unable to open the configuration file: " + filename;
        this->m_errorLine = 0;
        config.valid = false;
        return false;
    }

    std::string line;
    std::uint32_t lineOffset = 0;
    while (std::getline(stream, line)) {
        std::string value;

        lineOffset += 1;

        /* skip a new line */
        if (0 == line.length())
            continue;

        /* trimm the line and check if a comment line is used */
        std::string trimmed = String::trim(line);
        if (0 == trimmed.find_first_of('#', 0))
            continue;

        auto entry = String::splitString(trimmed, "=");
        if (2 > entry.size()) {
            this->m_errorLine = lineOffset;
            this->m_errorMessage = "Invalid configuration entry";
            config.valid = false;
            return false;
        }
        else if (2 < entry.size()) {
            for (std::size_t idx = 1; idx < entry.size() - 1; ++idx)
                value += gsl::at(entry, idx) + "=";
            value += entry.back();
        }
        else {
            value = gsl::at(entry, 1);
        }

        /* found an invalid line */
        if (0 == value.length()) {
            this->m_errorLine = lineOffset;
            this->m_errorMessage = "Invalid entry";
            config.valid = false;
            return false;
        }

        if ("URL" == gsl::at(entry, 0)) {
            config.url = gsl::at(entry, 1);
        }
        else if ("Port" == gsl::at(entry, 0)) {
            config.port = static_cast<std::uint16_t>(std::atoi(gsl::at(entry, 1).c_str()));
        }
        else if ("UID" == gsl::at(entry, 0)) {
            config.identifier = gsl::at(entry, 1);
        }
        else {
            this->m_errorLine = lineOffset;
            this->m_errorMessage = "Unknown entry: " + gsl::at(entry, 0);
            config.valid = false;
            return false;
        }
    }

    if (0 == lineOffset) {
        this->m_errorLine = 0;
        this->m_errorMessage = "No data found in " + filename;
        config.valid = false;
        return false;
    }

    return true;
}
