/*
 *  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 "dsh.h"
#include "../common.h"
#include <opendht/log.h>
#include <opendht/crypto.h>

#include <asio/io_context.hpp>
#include <sys/types.h>
#include <sys/wait.h>
namespace dhtnet {

const int READ_END = 0;
const int WRITE_END = 1;

void
create_pipe(int apipe[2])
{
#ifdef __APPLE__
    if (pipe(apipe) < 0)
        perror("pipe");

    if (fcntl(apipe[0], F_SETFD, FD_CLOEXEC) < 0)
        perror("unable to set pipe FD_CLOEXEC");

    if (fcntl(apipe[1], F_SETFD, FD_CLOEXEC) < 0)
        perror("unable to set pipe FD_CLOEXEC");
#else
    if (pipe2(apipe, O_CLOEXEC) == -1) {
        perror("pipe2");
        exit(EXIT_FAILURE);
    }
#endif
}

void
child_proc(const int in_pipe[2],
           const int out_pipe[2],
           const int error_pipe[2],
           const std::string& name)
{
    // close unused write end of input pipe and read end of output pipe
    close(in_pipe[WRITE_END]);
    close(out_pipe[READ_END]);
    close(error_pipe[READ_END]);

    // replace stdin with input pipe
    if (dup2(in_pipe[READ_END], STDIN_FILENO) == -1) {
        perror("dup2: error replacing stdin");
        exit(EXIT_FAILURE);
    }

    // replace stdout with output pipe
    if (dup2(out_pipe[WRITE_END], STDOUT_FILENO) == -1) {
        perror("dup2: error replacing stdout");
        exit(EXIT_FAILURE);
    }
    // replace stderr with error pipe
    if (dup2(error_pipe[WRITE_END], STDERR_FILENO) == -1) {
        perror("dup2: error replacing stderr");
        exit(EXIT_FAILURE);
    }

    // prepare arguments
    const char* args[] = {name.c_str(), NULL};
    // execute subprocess
    execvp(args[0], const_cast<char* const*>(args));

    // if execv returns, an error occurred
    perror("execvp");
    exit(EXIT_FAILURE);
}

dhtnet::Dsh::Dsh(const std::filesystem::path& path,
                 dht::crypto::Identity identity,
                 const std::string& bootstrap,
                 const std::string& turn_host,
                 const std::string& turn_user,
                 const std::string& turn_pass,
                 const std::string& turn_realm,
                 bool anonymous)
    :logger(dht::log::getStdLogger())
    , ioContext(std::make_shared<asio::io_context>()),
    iceFactory(std::make_shared<IceTransportFactory>(logger)),
    certStore(std::make_shared<tls::CertificateStore>(path / "certstore", logger)),
    trustStore(std::make_shared<tls::TrustStore>(*certStore))
{
    ioContext = std::make_shared<asio::io_context>();
    ioContextRunner = std::thread([context = ioContext, logger = logger] {
        try {
            auto work = asio::make_work_guard(*context);
            context->run();
        } catch (const std::exception& ex) {
            if (logger)
                logger->error("Error in ioContextRunner: {}", ex.what());
        }
    });
    auto ca = identity.second->issuer;
    trustStore->setCertificateStatus(ca->getId().toString(), tls::TrustStore::PermissionStatus::ALLOWED);
    // Build a server
    auto config = connectionManagerConfig(path,
                                          identity,
                                          bootstrap,
                                          logger,
                                          certStore,
                                          ioContext,
                                          iceFactory);
    // create a connection manager
    connectionManager = std::make_unique<ConnectionManager>(std::move(config));

    connectionManager->onDhtConnected(identity.first->getPublicKey());
    connectionManager->onICERequest([this,identity,anonymous](const DeviceId& deviceId ) { // handle ICE request
        return trustStore->isAllowed(*certStore->getCertificate(deviceId.toString()), anonymous);
    });

    std::mutex mtx;
    std::unique_lock<std::mutex> lk {mtx};

    connectionManager->onChannelRequest(
        [&](const std::shared_ptr<dht::crypto::Certificate>&, const std::string& name) {
            // handle channel request
            if (logger)
                logger->debug("Channel request received");
            return true;
        });

    connectionManager->onConnectionReady([&](const DeviceId&,
                                             const std::string& name,
                                             std::shared_ptr<ChannelSocket> socket) {
        // handle connection ready
        try {
            // Create a pipe for communication with the  subprocess
            // create pipes
            int in_pipe[2], out_pipe[2], error_pipe[2];
            create_pipe(in_pipe);
            create_pipe(out_pipe);
            create_pipe(error_pipe);

            ioContext->notify_fork(asio::io_context::fork_prepare);

            // Fork to create a child process
            pid_t pid = fork();
            if (pid == -1) {
                perror("fork");
                return EXIT_FAILURE;
            } else if (pid == 0) { // Child process
                ioContext->notify_fork(asio::io_context::fork_child);
                child_proc(in_pipe, out_pipe, error_pipe, name);
                return EXIT_SUCCESS; // never reached
            } else {
                ioContext->notify_fork(asio::io_context::fork_parent);

                // close unused read end of input pipe and write end of output pipe
                close(in_pipe[READ_END]);
                close(out_pipe[WRITE_END]);
                close(error_pipe[WRITE_END]);

                asio::io_context& ioContextRef = *ioContext;
                // create stream descriptors
                auto inStream
                    = std::make_shared<asio::posix::stream_descriptor>(ioContextRef.get_executor(),
                                                                       in_pipe[WRITE_END]);
                auto outStream
                    = std::make_shared<asio::posix::stream_descriptor>(ioContextRef.get_executor(),
                                                                       out_pipe[READ_END]);
                auto errorStream
                    = std::make_shared<asio::posix::stream_descriptor>(ioContextRef.get_executor(),
                                                                       error_pipe[READ_END]);

                if (socket) {
                    socket->setOnRecv([this, socket, inStream](const uint8_t* data, size_t size) {
                        auto data_copy = std::make_shared<std::vector<uint8_t>>(data, data + size);
                        // write on pipe to sub child
                        std::error_code ec;
                        asio::async_write(*inStream,
                                          asio::buffer(*data_copy),
                                          [data_copy, this](const std::error_code& error,
                                                            std::size_t bytesWritten) {
                                              if (error) {
                                                  if (logger)
                                                      logger->error("Write error: {}",
                                                                    error.message());
                                              }
                                          });
                        return size;
                    });

                    // read from pipe to sub child

                    // Create a buffer to read data into
                    auto buffer = std::make_shared<std::vector<uint8_t>>(BUFFER_SIZE);

                    // Create a shared_ptr to the stream_descriptor
                    readFromPipe(socket, outStream, buffer);
                    readFromPipe(socket, errorStream, buffer);

                    return EXIT_SUCCESS;
                }
            }

        } catch (const std::exception& e) {
            if (logger)
                logger->error("Error: {}", e.what());
        }
        return 0;
    });
}

dhtnet::Dsh::Dsh(const std::filesystem::path& path,
                 dht::crypto::Identity identity,
                 const std::string& bootstrap,
                 dht::InfoHash peer_id,
                 const std::string& binary,
                 const std::string& turn_host,
                 const std::string& turn_user,
                 const std::string& turn_pass,
                 const std::string& turn_realm)
    : Dsh(path, identity, bootstrap, turn_host, turn_user, turn_pass, turn_realm, false)
{
    // Build a client
    std::condition_variable cv;
    connectionManager->connectDevice(
        peer_id, binary, [&](std::shared_ptr<ChannelSocket> socket, const dht::InfoHash&) {
            if (socket) {
                socket->setOnRecv([this, socket](const uint8_t* data, size_t size) {
                    std::cout.write((const char*) data, size);
                    std::cout.flush();
                    return size;
                });
                // Create a buffer to read data into
                auto buffer = std::make_shared<std::vector<uint8_t>>(BUFFER_SIZE);

                // Create a shared_ptr to the stream_descriptor
                auto stdinPipe = std::make_shared<asio::posix::stream_descriptor>(*ioContext,
                                                                                  ::dup(
                                                                                      STDIN_FILENO));
                readFromPipe(socket, stdinPipe, buffer);

                socket->onShutdown([this]() {
                    if (logger)
                        logger->debug("Exit program");
                    ioContext->stop();
                });
            }
        });

    connectionManager->onConnectionReady([&](const DeviceId&,
                                             const std::string& name,
                                             std::shared_ptr<ChannelSocket> socket_received) {
        if (logger)
            logger->debug("Connected!");
    });
}

void
dhtnet::Dsh::run()
{
    ioContext->run();
}

dhtnet::Dsh::~Dsh()
{
    ioContext->stop();
    ioContextRunner.join();
}

} // namespace dhtnet