/*
 *  Copyright (C) 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 <string>
#include <filesystem>
#include <unistd.h>
#include <fcntl.h>
#include <asio.hpp>

namespace dhtnet {

dht::crypto::Identity
loadIdentity(const std::filesystem::path& path)
{
    if (!std::filesystem::exists(path)) {
        std::filesystem::create_directory(path);
    }
    try {
        for (const auto& path : std::filesystem::directory_iterator(path)) {
            auto p = path.path();
            if (p.extension() == ".pem") {
                auto privateKey = std::make_unique<dht::crypto::PrivateKey>(fileutils::loadFile(p));
                auto certificate = std::make_unique<dht::crypto::Certificate>(
                    fileutils::loadFile(p.replace_extension(".crt")));
                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);
    fmt::print("Generated new identity: {}\n", id.first->getPublicKey().getId());
    dht::crypto::saveIdentity(id, path / "id");
    return id;
}

std::unique_ptr<ConnectionManager::Config>
connectionManagerConfig(const std::filesystem::path& path,
                        dht::crypto::Identity identity,
                        const std::string& bootstrap,
                        std::shared_ptr<Logger> logger,
                        std::shared_ptr<tls::CertificateStore> certStore,
                        std::shared_ptr<asio::io_context> ioContext,
                        std::shared_ptr<IceTransportFactory> iceFactory,
                        const std::string& turn_host,
                        const std::string& turn_user,
                        const std::string& turn_pass,
                        const std::string& turn_realm)
{
    std::filesystem::create_directories(path / "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 = [certStore](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);

    // 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 = path;
    config->logger = logger;
    if (!turn_host.empty())
        config->turnEnabled = true;
    config->turnServer = turn_host;
    config->turnServerUserName = turn_user;
    config->turnServerPwd = turn_pass;
    config->turnServerRealm = turn_realm;


    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;
                             // Write the data to the socket
                             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());
                             }
                         } else if (error == asio::error::eof) {
                                // Connection closed cleanly by peer.
                                socket->shutdown();
                         }else{
                            fmt::print(stderr, "Error reading from stdin: {}\n", 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