/*
 *  Copyright (C) 2004-2023 Savoir-faire Linux Inc.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <https://www.gnu.org/licenses/>.
 */
#include "certstore.h"
#include "connectionmanager.h"
#include "common.h"
#include "fileutils.h"
#include "ice_transport.h"

#include <opendht/crypto.h>
#include <iostream>
#include <string>
#include <filesystem>
#include <unistd.h>
#include <fcntl.h>
#include <asio.hpp>

namespace dhtnet {

dht::crypto::Identity
loadIdentity(bool isServer)
{
    std::string idDir = std::string(getenv("HOME")) + "/.dhtnetTools";
    if (isServer){

        if (!std::filesystem::exists(idDir)) {
            std::filesystem::create_directory(idDir);
        }

        try {
            std::filesystem::directory_iterator endIter;
            for (std::filesystem::directory_iterator iter(idDir); iter != endIter; ++iter) {
                if (iter->path().extension() == ".pem") {
                    auto privateKey = std::make_unique<dht::crypto::PrivateKey>(
                        fileutils::loadFile(std::filesystem::path(iter->path())));
                    // Generate certificate
                    auto certificate = std::make_unique<dht::crypto::Certificate>(
                        dht::crypto::Certificate::generate(*privateKey, "dhtnc"));
                    // return
                    return dht::crypto::Identity(std::move(privateKey), std::move(certificate));
                }
            }
        } catch (const std::exception& e) {
            fmt::print(stderr, "Error loadind key from .dhtnetTools: {}\n", e.what());
        }
    }
    auto ca = dht::crypto::generateIdentity("ca");
    auto id = dht::crypto::generateIdentity("dhtnc", ca);
    idDir += "/id";
    if (isServer)
        dht::crypto::saveIdentity(id, idDir);
    return id;
}

std::unique_ptr<ConnectionManager::Config>
connectionManagerConfig(dht::crypto::Identity identity,
                  const std::string& bootstrap_ip_add,
                  const std::string& bootstrap_port,
                  std::shared_ptr<Logger> logger,
                  tls::CertificateStore& certStore,
                  std::shared_ptr<asio::io_context> ioContext,
                  IceTransportFactory& iceFactory)
{
    std::filesystem::create_directories(std::string(getenv("HOME")) + "/.dhtnetTools/certstore");

    // DHT node creation: To make a connection manager at first a DHT node should be created

    dht::DhtRunner::Config dhtConfig;
    dhtConfig.dht_config.id = identity;
    dhtConfig.threaded = true;
    dhtConfig.peer_discovery = false;
    dhtConfig.peer_publish = false;
    dht::DhtRunner::Context dhtContext;
    dhtContext.identityAnnouncedCb = [logger](bool ok) {
        if (logger)
            logger->debug("Identity announced {}\n", ok);
    };
    dhtContext.certificateStore = [&](const dht::InfoHash& pk_id) {
        std::vector<std::shared_ptr<dht::crypto::Certificate>> ret;
        if (auto cert = certStore.getCertificate(pk_id.toString()))
            ret.emplace_back(std::move(cert));
        return ret;
    };
    auto runner = std::make_shared<dht::DhtRunner>();
    runner->run(dhtConfig, std::move(dhtContext));
    runner->bootstrap(bootstrap_ip_add, bootstrap_port);

    // DHT node creation end:
    // ConnectionManager creation:
    auto config = std::make_unique<ConnectionManager::Config>();
    config->dht = runner;
    config->id = identity;
    config->ioContext = ioContext;
    config->certStore = &certStore;
    config->factory = &iceFactory;
    config->cachePath = std::string(getenv("HOME")) + "/.dhtnetTools";

    return std::move(config);
}
template <typename T>
void readFromPipe(std::shared_ptr<ChannelSocket> socket, T input, Buffer buffer)
{
    asio::async_read(*input,
                     asio::buffer(*buffer),
                     asio::transfer_at_least(1),
                     [socket, input, buffer](const asio::error_code& error, size_t bytesRead) {
                         if (!error) {
                             // Process the data received in the buffer
                             std::error_code ec;
                             // print the data to stdout
                             socket->write(buffer->data(), bytesRead, ec);
                             if (!ec) {
                                 // Continue reading more data
                                 readFromPipe(socket, input, buffer);
                             } else {
                                fmt::print(stderr, "Error writing to socket: {}\n", ec.message());
                                // logger->error("Error writing to socket: {}", ec.message());
                             }
                         } else if(error != asio::error::eof) {
                            fmt::print(stderr, "Error reading from stdin: {}\n", error.message());
                            //  logger->error("Error reading from stdin: {}", error.message());
                         }
                     });
}

template void readFromPipe(std::shared_ptr<ChannelSocket> socket, std::shared_ptr<asio::posix::stream_descriptor> input, Buffer buffer);
template void readFromPipe(std::shared_ptr<ChannelSocket> socket, std::shared_ptr<asio::ip::tcp::socket> input, Buffer buffer);




} // namespace dhtnet