/*
 *  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 "upnp/mapping.h"
// #include "logger.h"
#include "igd.h"

namespace dhtnet {
namespace upnp {

Mapping::Mapping(PortType type, uint16_t portExternal, uint16_t portInternal, bool available)
    : type_(type)
    , externalPort_(portExternal)
    , internalPort_(portInternal)
    , internalAddr_()
    , igd_()
    , available_(available)
    , state_(MappingState::PENDING)
    , notifyCb_(nullptr)
    , autoUpdate_(false)
#if HAVE_LIBNATPMP
    , renewalTime_(sys_clock::now())
#endif
{}

Mapping::Mapping(const Mapping& other)
{
    std::lock_guard<std::mutex> lock(other.mutex_);

    internalAddr_ = other.internalAddr_;
    internalPort_ = other.internalPort_;
    externalPort_ = other.externalPort_;
    type_ = other.type_;
    igd_ = other.igd_;
    available_ = other.available_;
    state_ = other.state_;
    notifyCb_ = other.notifyCb_;
    autoUpdate_ = other.autoUpdate_;
#if HAVE_LIBNATPMP
    renewalTime_ = other.renewalTime_;
#endif
}

void
Mapping::updateFrom(const Mapping::sharedPtr_t& other)
{
    updateFrom(*other);
}

void
Mapping::updateFrom(const Mapping& other)
{
    if (type_ != other.type_) {
        // JAMI_ERR("The source and destination types must match");
        return;
    }

    internalAddr_ = std::move(other.internalAddr_);
    internalPort_ = other.internalPort_;
    externalPort_ = other.externalPort_;
    igd_ = other.igd_;
    state_ = other.state_;
}

void
Mapping::setAvailable(bool val)
{
    // JAMI_DBG("Changing mapping %s state from %s to %s",
    //          toString().c_str(),
    //          available_ ? "AVAILABLE" : "UNAVAILABLE",
    //          val ? "AVAILABLE" : "UNAVAILABLE");

    std::lock_guard<std::mutex> lock(mutex_);
    available_ = val;
}

void
Mapping::setState(const MappingState& state)
{
    std::lock_guard<std::mutex> lock(mutex_);
    state_ = state;
}

const char*
Mapping::getStateStr() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    return getStateStr(state_);
}

std::string
Mapping::toString(bool extraInfo) const
{
    std::lock_guard<std::mutex> lock(mutex_);
    std::ostringstream descr;
    descr << UPNP_MAPPING_DESCRIPTION_PREFIX << "-" << getTypeStr(type_);
    descr << ":" << std::to_string(internalPort_);

    if (extraInfo) {
        descr << " (state=" << getStateStr(state_)
              << ", auto-update=" << (autoUpdate_ ? "YES" : "NO") << ")";
    }

    return descr.str();
}

bool
Mapping::isValid() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    if (state_ == MappingState::FAILED)
        return false;
    if (internalPort_ == 0)
        return false;
    if (externalPort_ == 0)
        return false;
    if (not igd_ or not igd_->isValid())
        return false;
    IpAddr intAddr(internalAddr_);
    return intAddr and not intAddr.isLoopback();
}

bool
Mapping::hasValidHostAddress() const
{
    std::lock_guard<std::mutex> lock(mutex_);

    IpAddr intAddr(internalAddr_);
    return intAddr and not intAddr.isLoopback();
}

bool
Mapping::hasPublicAddress() const
{
    std::lock_guard<std::mutex> lock(mutex_);

    return igd_ and igd_->getPublicIp() and not igd_->getPublicIp().isPrivate();
}

Mapping::key_t
Mapping::getMapKey() const
{
    std::lock_guard<std::mutex> lock(mutex_);

    key_t mapKey = internalPort_;
    if (type_ == PortType::UDP)
        mapKey |= 1 << (sizeof(uint16_t) * 8);
    return mapKey;
}

PortType
Mapping::getTypeFromMapKey(key_t key)
{
    return (key >> (sizeof(uint16_t) * 8)) ? PortType::UDP : PortType::TCP;
}

std::string
Mapping::getExternalAddress() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    if (igd_)
        return igd_->getPublicIp().toString();
    return {};
}

void
Mapping::setExternalPort(uint16_t port)
{
    std::lock_guard<std::mutex> lock(mutex_);
    externalPort_ = port;
}

uint16_t
Mapping::getExternalPort() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    return externalPort_;
}

std::string
Mapping::getExternalPortStr() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    return std::to_string(externalPort_);
}

void
Mapping::setInternalAddress(const std::string& addr)
{
    std::lock_guard<std::mutex> lock(mutex_);
    internalAddr_ = addr;
}

std::string
Mapping::getInternalAddress() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    return internalAddr_;
}

void
Mapping::setInternalPort(uint16_t port)
{
    std::lock_guard<std::mutex> lock(mutex_);
    internalPort_ = port;
}

uint16_t
Mapping::getInternalPort() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    return internalPort_;
}

std::string
Mapping::getInternalPortStr() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    return std::to_string(internalPort_);
}

PortType
Mapping::getType() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    return type_;
}

const char*
Mapping::getTypeStr() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    return getTypeStr(type_);
}

bool
Mapping::isAvailable() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    return available_;
}

std::shared_ptr<IGD>
Mapping::getIgd() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    return igd_;
}

NatProtocolType
Mapping::getProtocol() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    if (igd_)
        return igd_->getProtocol();
    return NatProtocolType::UNKNOWN;
}
const char*
Mapping::getProtocolName() const
{
    if (igd_) {
        if (igd_->getProtocol() == NatProtocolType::NAT_PMP)
            return "NAT-PMP";
        if (igd_->getProtocol() == NatProtocolType::PUPNP)
            return "PUPNP";
    }
    return "UNKNOWN";
}

void
Mapping::setIgd(const std::shared_ptr<IGD>& igd)
{
    std::lock_guard<std::mutex> lock(mutex_);
    igd_ = igd;
}

MappingState
Mapping::getState() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    return state_;
}

Mapping::NotifyCallback
Mapping::getNotifyCallback() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    return notifyCb_;
}

void
Mapping::setNotifyCallback(NotifyCallback cb)
{
    std::lock_guard<std::mutex> lock(mutex_);
    notifyCb_ = std::move(cb);
}

void
Mapping::enableAutoUpdate(bool enable)
{
    std::lock_guard<std::mutex> lock(mutex_);
    autoUpdate_ = enable;
}

bool
Mapping::getAutoUpdate() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    return autoUpdate_;
}

#if HAVE_LIBNATPMP
sys_clock::time_point
Mapping::getRenewalTime() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    return renewalTime_;
}

void
Mapping::setRenewalTime(sys_clock::time_point time)
{
    std::lock_guard<std::mutex> lock(mutex_);
    renewalTime_ = time;
}
#endif

} // namespace upnp
} // namespace dhtnet
