//
//  ServerConfiguration.cpp
//  eagle0_server
//
//  Created by Dan Crosby on 1/21/18.
//  Copyright © 2018 none. All rights reserved.
//

#include "ServerConfiguration.hpp"

#include <algorithm>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <sstream>

#include "src/main/cpp/net/eagle0/common/FilesystemUtils.hpp"

#pragma GCC diagnostic push
#ifdef __clang__
#pragma GCC diagnostic ignored "-Wexit-time-destructors"
#endif
const std::string ServerConfiguration::kShardokGrpcAddress = "shardokGrpcAddress";
const std::string ServerConfiguration::kEagleInterfaceGrpcAddress = "eagleInterfaceGrpcAddress";
const std::string ServerConfiguration::kEagleGrpcAddress = "eagleGrpcAddress";
const std::string ServerConfiguration::kSslCertPath = "sslCertPath";
const std::string ServerConfiguration::kSslPrivateKeyPath = "sslPrivateKeyPath";
const std::string ServerConfiguration::kAuthTokenPath = "authTokenPath";
#pragma GCC diagnostic pop

std::unordered_map<std::string, std::string> DefaultValues();

std::unordered_map<std::string, std::string> DefaultValues() {
    // Check environment variables for Docker deployment
    // Docker containers should set SHARDOK_EAGLE_INTERFACE_ADDRESS=0.0.0.0:40042
    // to listen on all interfaces for container networking
    const char* eagleInterfaceAddr = getenv("SHARDOK_EAGLE_INTERFACE_ADDRESS");
    const char* shardokAddr = getenv("SHARDOK_GRPC_ADDRESS");

    return std::unordered_map<std::string, std::string>{
            {ServerConfiguration::kShardokGrpcAddress, shardokAddr ? shardokAddr : "localhost"},
            {ServerConfiguration::kEagleInterfaceGrpcAddress,
             eagleInterfaceAddr ? eagleInterfaceAddr : "localhost:40042"}};
}

ServerConfiguration::ServerConfiguration(const std::string& filePath) {
    if (!FilesystemUtils::FileExistsAtPath(filePath)) {
        std::cerr << "Config file not found at " << filePath << '\n';
        configValues = DefaultValues();
        return;
    }
    std::ifstream istr(filePath);

    std::string line;
    while (std::getline(istr, line)) {
        std::ranges::replace(line, '=', ' ');
        std::istringstream lineStream(line);

        std::string key;
        std::string value;
        if (!(lineStream >> key >> value)) { continue; }

        configValues[key] = value;
    }
}

int ServerConfiguration::intForKey(const std::string& key, const int defaultValue) {
    const auto foundVal = configValues.find(key);
    if (foundVal == configValues.end()) { return defaultValue; }
    return std::stoi(foundVal->second);
}

std::string ServerConfiguration::stringForKey(
        const std::string& key,
        const std::string& defaultValue) {
    const auto foundVal = configValues.find(key);
    if (foundVal == configValues.end()) { return defaultValue; }
    return foundVal->second;
}
