#include "endian.hpp"
#include "slp.hpp"
#include "slp_meta.hpp"

#include <arpa/inet.h>
#include <dirent.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <string.h>

#include <algorithm>
#include <bitset>

namespace slp
{
namespace handler
{

namespace internal
{

static constexpr auto SERVICE_DIR = "/etc/slp/services/";

buffer prepareHeader(const Message& req)
{
    uint8_t length =
        slp::header::MIN_LEN +        /* 14 bytes for header     */
        req.header.langtag.length() + /* Actual length of lang tag */
        slp::response::SIZE_ERROR;    /*  2 bytes for error code */

    buffer buff(length, 0);

    buff[slp::header::OFFSET_VERSION] = req.header.version;

    // will increment the function id from 1 as reply
    buff[slp::header::OFFSET_FUNCTION] = req.header.functionID + 1;

    std::copy_n(&length, slp::header::SIZE_LENGTH,
                buff.data() + slp::header::OFFSET_LENGTH);

    auto flags = endian::to_network(req.header.flags);

    std::copy_n((uint8_t*)&flags, slp::header::SIZE_FLAGS,
                buff.data() + slp::header::OFFSET_FLAGS);

    std::copy_n(req.header.extOffset.data(), slp::header::SIZE_EXT,
                buff.data() + slp::header::OFFSET_EXT);

    auto xid = endian::to_network(req.header.xid);

    std::copy_n((uint8_t*)&xid, slp::header::SIZE_XID,
                buff.data() + slp::header::OFFSET_XID);

    uint16_t langtagLen = req.header.langtag.length();
    langtagLen = endian::to_network(langtagLen);
    std::copy_n((uint8_t*)&langtagLen, slp::header::SIZE_LANG,
                buff.data() + slp::header::OFFSET_LANG_LEN);

    std::copy_n((uint8_t*)req.header.langtag.c_str(),
                req.header.langtag.length(),
                buff.data() + slp::header::OFFSET_LANG);
    return buff;
}

std::tuple<int, buffer> processSrvTypeRequest(const Message& req)
{
    /*
       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |      Service Location header (function = SrvTypeRply = 10)    |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |           Error Code          |    length of <srvType-list>   |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                       <srvtype--list>                         \
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    */

    buffer buff;

    // read the slp service info from conf and create the service type string
    slp::handler::internal::ServiceList svcList =
        slp::handler::internal::readSLPServiceInfo();
    if (svcList.size() <= 0)
    {
        buff.resize(0);
        std::cerr << "SLP unable to read the service info\n";
        return std::make_tuple((int)slp::Error::INTERNAL_ERROR, buff);
    }

    std::string service;
    bool firstIteration = true;
    for_each(svcList.cbegin(), svcList.cend(),
             [&service, &firstIteration](const auto& svc) {
        if (firstIteration == true)
        {
            service = svc.first;
            firstIteration = false;
        }
        else
        {
            service += ",";
            service += svc.first;
        }
    });

    buff = prepareHeader(req);

    /* Need to modify the length and the function type field of the header
     * as it is dependent on the handler of the service */

    std::cout << "service=" << service.c_str() << "\n";

    // See if total response size exceeds our max
    uint32_t totalLength =
        buff.size() +                 /* 14 bytes header + length of langtag */
        slp::response::SIZE_ERROR +   /* 2 byte err code */
        slp::response::SIZE_SERVICE + /* 2 byte srvtype len */
        service.length();
    if (totalLength > slp::MAX_LEN)
    {
        std::cerr << "Message response size exceeds maximum allowed: "
                  << totalLength << " / " << slp::MAX_LEN << std::endl;
        buff.resize(0);
        return std::make_tuple((int)slp::Error::PARSE_ERROR, buff);
    }

    uint8_t length = buff.size() + /* 14 bytes header + length of langtag */
                     slp::response::SIZE_ERROR +   /* 2 byte err code */
                     slp::response::SIZE_SERVICE + /* 2 byte srvtype len */
                     service.length();

    buff.resize(length);

    std::copy_n(&length, slp::header::SIZE_LENGTH,
                buff.data() + slp::header::OFFSET_LENGTH);

    /* error code is already set to 0 moving to service type len */

    uint16_t serviceTypeLen = service.length();
    serviceTypeLen = endian::to_network(serviceTypeLen);

    std::copy_n((uint8_t*)&serviceTypeLen, slp::response::SIZE_SERVICE,
                buff.data() + slp::response::OFFSET_SERVICE_LEN);

    /* service type data */
    std::copy_n((uint8_t*)service.c_str(), service.length(),
                (buff.data() + slp::response::OFFSET_SERVICE));

    return std::make_tuple(slp::SUCCESS, buff);
}

std::tuple<int, buffer> processSrvRequest(const Message& req)
{
    /*
          Service Reply
          0                   1                   2                   3
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         |        Service Location header (function = SrvRply = 2)       |
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         |        Error Code             |        URL Entry count        |
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         |       <URL Entry 1>          ...       <URL Entry N>          \
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

         URL Entry
          0                   1                   2                   3
          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         |   Reserved    |          Lifetime             |   URL Length  |
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         |URL len, contd.|            URL (variable length)              \
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         |# of URL auths |            Auth. blocks (if any)              \
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    */

    buffer buff;
    // Get all the services which are registered
    slp::handler::internal::ServiceList svcList =
        slp::handler::internal::readSLPServiceInfo();
    if (svcList.size() <= 0)
    {
        buff.resize(0);
        std::cerr << "SLP unable to read the service info\n";
        return std::make_tuple((int)slp::Error::INTERNAL_ERROR, buff);
    }

    // return error if serice type doesn't match
    auto& svcName = req.body.srvrqst.srvType;
    auto svcIt = svcList.find(svcName);
    if (svcIt == svcList.end())
    {
        buff.resize(0);
        std::cerr << "SLP unable to find the service=" << svcName << "\n";
        return std::make_tuple((int)slp::Error::INTERNAL_ERROR, buff);
    }
    // Get all the interface address
    auto ifaddrList = slp::handler::internal::getIntfAddrs();
    if (ifaddrList.size() <= 0)
    {
        buff.resize(0);
        std::cerr << "SLP unable to read the interface address\n";
        return std::make_tuple((int)slp::Error::INTERNAL_ERROR, buff);
    }

    buff = prepareHeader(req);
    // Calculate the length and resize the buffer
    uint8_t length = buff.size() + /* 14 bytes header + length of langtag */
                     slp::response::SIZE_ERROR +    /* 2 bytes error code */
                     slp::response::SIZE_URL_COUNT; /* 2 bytes srvtype len */

    buff.resize(length);

    // Populate the url count
    uint16_t urlCount = ifaddrList.size();
    urlCount = endian::to_network(urlCount);

    std::copy_n((uint8_t*)&urlCount, slp::response::SIZE_URL_COUNT,
                buff.data() + slp::response::OFFSET_URL_ENTRY);

    // Find the service
    const slp::ConfigData& svc = svcIt->second;
    // Populate the URL Entries
    auto pos = slp::response::OFFSET_URL_ENTRY + slp::response::SIZE_URL_COUNT;
    for (const auto& addr : ifaddrList)
    {
        std::string url = svc.name + ':' + svc.type + "//" + addr + ',' +
                          svc.port;

        // See if total response size exceeds our max
        uint32_t totalLength = buff.size() + slp::response::SIZE_URL_ENTRY +
                               url.length();
        if (totalLength > slp::MAX_LEN)
        {
            std::cerr << "Message response size exceeds maximum allowed: "
                      << totalLength << " / " << slp::MAX_LEN << std::endl;
            buff.resize(0);
            return std::make_tuple((int)slp::Error::PARSE_ERROR, buff);
        }

        buff.resize(buff.size() + slp::response::SIZE_URL_ENTRY + url.length());

        uint8_t reserved = 0;
        uint16_t auth = 0;
        uint16_t lifetime = endian::to_network<uint16_t>(slp::LIFETIME);
        uint16_t urlLength = url.length();

        std::copy_n((uint8_t*)&reserved, slp::response::SIZE_RESERVED,
                    buff.data() + pos);

        pos += slp::response::SIZE_RESERVED;

        std::copy_n((uint8_t*)&lifetime, slp::response::SIZE_LIFETIME,
                    buff.data() + pos);

        pos += slp::response::SIZE_LIFETIME;

        urlLength = endian::to_network(urlLength);
        std::copy_n((uint8_t*)&urlLength, slp::response::SIZE_URLLENGTH,
                    buff.data() + pos);
        pos += slp::response::SIZE_URLLENGTH;

        std::copy_n((uint8_t*)url.c_str(), url.length(), buff.data() + pos);
        pos += url.length();

        std::copy_n((uint8_t*)&auth, slp::response::SIZE_AUTH,
                    buff.data() + pos);
        pos += slp::response::SIZE_AUTH;
    }
    uint8_t packetLength = buff.size();
    std::copy_n((uint8_t*)&packetLength, slp::header::SIZE_VERSION,
                buff.data() + slp::header::OFFSET_LENGTH);

    return std::make_tuple((int)slp::SUCCESS, buff);
}

std::list<std::string> getIntfAddrs()
{
    std::list<std::string> addrList;

    struct ifaddrs* ifaddr;
    // attempt to fill struct with ifaddrs
    if (getifaddrs(&ifaddr) == -1)
    {
        return addrList;
    }

    slp::deleted_unique_ptr<ifaddrs> ifaddrPtr(
        ifaddr, [](ifaddrs* addr) { freeifaddrs(addr); });

    ifaddr = nullptr;

    for (ifaddrs* ifa = ifaddrPtr.get(); ifa != nullptr; ifa = ifa->ifa_next)
    {
        // walk interfaces
        if (ifa->ifa_addr == nullptr)
        {
            continue;
        }

        // get only INET interfaces not ipv6
        if (ifa->ifa_addr->sa_family == AF_INET)
        {
            // if loopback, or not running ignore
            if ((ifa->ifa_flags & IFF_LOOPBACK) ||
                !(ifa->ifa_flags & IFF_RUNNING))
            {
                continue;
            }

            char tmp[INET_ADDRSTRLEN] = {0};

            inet_ntop(AF_INET,
                      &(((struct sockaddr_in*)(ifa->ifa_addr))->sin_addr), tmp,
                      sizeof(tmp));
            addrList.emplace_back(tmp);
        }
    }

    return addrList;
}

slp::handler::internal::ServiceList readSLPServiceInfo()
{
    using namespace std::string_literals;
    slp::handler::internal::ServiceList svcLst;
    slp::ConfigData service;
    struct dirent* dent = nullptr;

    // Open the services dir and get the service info
    // from service files.
    // Service File format would be "ServiceName serviceType Port"
    DIR* dir = opendir(SERVICE_DIR);
    // wrap the pointer into smart pointer.
    slp::deleted_unique_ptr<DIR> dirPtr(dir, [](DIR* dir) {
        if (!dir)
        {
            closedir(dir);
        }
    });
    dir = nullptr;

    if (dirPtr.get())
    {
        while ((dent = readdir(dirPtr.get())) != NULL)
        {
            if (dent->d_type == DT_REG) // regular file
            {
                auto absFileName = std::string(SERVICE_DIR) + dent->d_name;
                std::ifstream readFile(absFileName);
                readFile >> service;
                service.name = "service:"s + service.name;
                svcLst.emplace(service.name, service);
            }
        }
    }
    return svcLst;
}
} // namespace internal

std::tuple<int, buffer> processRequest(const Message& msg)
{
    int rc = slp::SUCCESS;
    buffer resp(0);
    std::cout << "SLP Processing Request="
              << std::bitset<8>(msg.header.functionID) << "\n";

    switch (msg.header.functionID)
    {
        case (uint8_t)slp::FunctionType::SRVTYPERQST:
            std::tie(rc,
                     resp) = slp::handler::internal::processSrvTypeRequest(msg);
            break;
        case (uint8_t)slp::FunctionType::SRVRQST:
            std::tie(rc, resp) = slp::handler::internal::processSrvRequest(msg);
            break;
        default:
            rc = (uint8_t)slp::Error::MSG_NOT_SUPPORTED;
    }
    return std::make_tuple(rc, resp);
}

buffer processError(const Message& req, uint8_t err)
{
    if (req.header.functionID != 0)
    {
        std::cout << "Processing Error for function: "
                  << std::bitset<8>(req.header.functionID) << std::endl;
    }

    /*  0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |        Service Location header (function = SrvRply = 2)       |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |        Error Code             |        URL Entry count        |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |       <URL Entry 1>          ...       <URL Entry N>          \
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/

    // There has been some sort of issue processing the request from
    // the client. Can not assume the input request buffer is valid
    // so just create an empty buffer with the non-variable size
    // fields set and the error code
    uint8_t length = slp::header::MIN_LEN +     /* 14 bytes for header     */
                     slp::response::SIZE_ERROR; /*  2 bytes for error code */

    buffer buff(length, 0);

    static_assert(sizeof(err) == 1, "Errors should be 1 byte.");

    buff[slp::header::OFFSET_VERSION] = req.header.version;

    // will increment the function id from 1 as reply
    buff[slp::header::OFFSET_FUNCTION] = req.header.functionID + 1;

    std::copy_n(&length, slp::header::SIZE_LENGTH,
                buff.data() + slp::header::OFFSET_LENGTH);

    auto flags = endian::to_network(req.header.flags);

    std::copy_n((uint8_t*)&flags, slp::header::SIZE_FLAGS,
                buff.data() + slp::header::OFFSET_FLAGS);

    std::copy_n(req.header.extOffset.data(), slp::header::SIZE_EXT,
                buff.data() + slp::header::OFFSET_EXT);

    auto xid = endian::to_network(req.header.xid);

    std::copy_n((uint8_t*)&xid, slp::header::SIZE_XID,
                buff.data() + slp::header::OFFSET_XID);

    // This is an invalid header from user so just fill in 0 for langtag
    uint16_t langtagLen = 0;
    std::copy_n((uint8_t*)&langtagLen, slp::header::SIZE_LANG,
                buff.data() + slp::header::OFFSET_LANG_LEN);

    // Since this is network order, the err should go in the 2nd byte of the
    // error field.
    buff[slp::header::MIN_LEN + 1] = err;

    return buff;
}
} // namespace handler
} // namespace slp
