/*
 *  Copyright (C) 2021-2022 Savoir-faire Linux Inc.
 *
 *  Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
 *
 *  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, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
 */

#import "Adapter.h"
#import "Utils.h"
#import "jamiNotificationExtension-Swift.h"

#import "jami/jami.h"
#import "jami/configurationmanager_interface.h"
#import "jami/callmanager_interface.h"
#import "jami/conversation_interface.h"
#import "jami/datatransfer_interface.h"

#define MSGPACK_DISABLE_LEGACY_NIL
#import "opendht/crypto.h"
#import "opendht/default_types.h"
#import "yaml-cpp/yaml.h"

#import "json/json.h"
#import "fstream"
#import "charconv"

@implementation Adapter

static id<AdapterDelegate> _delegate;

using namespace libjami;

struct PeerConnectionRequest : public dht::EncryptedValue<PeerConnectionRequest>
{
    static const constexpr dht::ValueType& TYPE = dht::ValueType::USER_DATA;
    static constexpr const char* key_prefix = "peer:";
    dht::Value::Id id = dht::Value::INVALID_ID;
    std::string ice_msg {};
    bool isAnswer {false};
    std::string connType {};
    MSGPACK_DEFINE_MAP(id, ice_msg, isAnswer, connType)
};

// Constants
const std::string fileSeparator = "/";
NSString* const certificates = @"certificates";
NSString* const crls = @"crls";
NSString* const ocsp = @"ocsp";
NSString* const nameCache = @"namecache";
NSString* const defaultNameServer = @"ns.jami.net";
std::string const nameServerConfiguration = "RingNS.uri";
NSString* const accountConfig = @"config.yml";

std::map<std::string, std::shared_ptr<CallbackWrapperBase>> confHandlers;
std::map<std::string, std::string> cachedNames;
std::map<std::string, std::string> nameServers;

#pragma mark Callbacks registration
- (void)registerSignals
{
    confHandlers.insert(exportable_callback<ConfigurationSignal::GetAppDataPath>(
        [](const std::string& name, std::vector<std::string>* ret) {
            if (name == "cache") {
                auto path = [Constants cachesPath];
                ret->push_back(std::string([path.path UTF8String]));
            } else {
                auto path = [Constants documentsPath];
                ret->push_back(std::string([path.path UTF8String]));
            }
        }));

    confHandlers.insert(exportable_callback<ConversationSignal::MessageReceived>(
        [weakDelegate = Adapter.delegate](const std::string& accountId,
            const std::string& conversationId,
            std::map<std::string, std::string> message) {
                id<AdapterDelegate> delegate = weakDelegate;
                if (delegate) {
                NSString* convId = [NSString stringWithUTF8String:conversationId.c_str()];
                NSString* account = [NSString stringWithUTF8String:accountId.c_str()];
                NSMutableDictionary* interaction = [Utils mapToDictionnary:message];
                [delegate newInteractionWithConversationId:convId
                                                         accountId:account
                                                           message:interaction];
            }
        }));

    confHandlers.insert(exportable_callback<DataTransferSignal::DataTransferEvent>(
        [weakDelegate = Adapter.delegate](const std::string& account_id,
            const std::string& conversation_id,
            const std::string& interaction_id,
            const std::string& file_id,
            int eventCode) {
                id<AdapterDelegate> delegate = weakDelegate;
                if (delegate) {
                NSString* accountId = [NSString stringWithUTF8String:account_id.c_str()];
                NSString* conversationId = [NSString stringWithUTF8String:conversation_id.c_str()];
                NSString* fileId = [NSString stringWithUTF8String:file_id.c_str()];
                NSString* interactionId = [NSString stringWithUTF8String:interaction_id.c_str()];
                [delegate dataTransferEventWithFileId:fileId
                                                withEventCode:eventCode
                                                    accountId:accountId
                                               conversationId:conversationId
                                                interactionId:interactionId];
            }
        }));

    confHandlers.insert(exportable_callback<ConversationSignal::ConversationSyncFinished>(
        [weakDelegate = Adapter.delegate](const std::string& account_id) {
            id<AdapterDelegate> delegate = weakDelegate;
            if (delegate) {
                NSString* accountId = [NSString stringWithUTF8String:account_id.c_str()];
                [delegate conversationSyncCompletedWithAccountId:accountId];
            }
        }));

    confHandlers.insert(exportable_callback<ConversationSignal::ConversationCloned>(
        [weakDelegate = Adapter.delegate](const std::string& account_id) {
            id<AdapterDelegate> delegate = weakDelegate;
            if (delegate) {
                NSString* accountId = [NSString stringWithUTF8String:account_id.c_str()];
                [delegate conversationClonedWithAccountId:accountId];
            }
        }));

    confHandlers.insert(exportable_callback<ConversationSignal::ConversationRequestReceived>([weakDelegate = Adapter.delegate](const std::string& accountId, const std::string& conversationId, std::map<std::string, std::string> metadata) {
        id<AdapterDelegate> delegate = weakDelegate;
        if (delegate) {
            NSString* accountIdStr = [NSString stringWithUTF8String:accountId.c_str()];
            NSString* convIdStr = [NSString stringWithUTF8String:conversationId.c_str()];
            NSMutableDictionary* info = [Utils mapToDictionnary: metadata];
            [delegate receivedConversationRequestWithAccountId: accountIdStr conversationId: convIdStr metadata:info];
        }
    }));
    registerSignalHandlers(confHandlers);
}

#pragma mark AdapterDelegate
+ (id<AdapterDelegate>)delegate
{
    return _delegate;
}

+ (void)setDelegate:(id<AdapterDelegate>)delegate
{
    _delegate = delegate;
}

- (bool)downloadFileWithFileId:(NSString*)fileId
                     accountId:(NSString*)accountId
                conversationId:(NSString*)conversationId
                 interactionId:(NSString*)interactionId
                  withFilePath:(NSString*)filePath
{
    return downloadFile(std::string([accountId UTF8String]),
                        std::string([conversationId UTF8String]),
                        std::string([interactionId UTF8String]),
                        std::string([fileId UTF8String]),
                        std::string([filePath UTF8String]));
}

- (BOOL)start:(NSString*)accountId
{
    [self registerSignals];
    if (initialized() == true) {
        reloadConversationsAndRequests(std::string([accountId UTF8String]));
        setAccountActive(std::string([accountId UTF8String]), true);
        return true;
    }
#if DEBUG
    int flag = LIBJAMI_FLAG_CONSOLE_LOG | LIBJAMI_FLAG_DEBUG | LIBJAMI_FLAG_IOS_EXTENSION | LIBJAMI_FLAG_NO_AUTOSYNC | LIBJAMI_FLAG_NO_LOCAL_AUDIO;
#else
    int flag = LIBJAMI_FLAG_IOS_EXTENSION | LIBJAMI_FLAG_NO_AUTOSYNC | LIBJAMI_FLAG_NO_LOCAL_AUDIO;
#endif
    if (![[NSThread currentThread] isMainThread]) {
        __block bool success;
        dispatch_sync(dispatch_get_main_queue(), ^{
            if (init(static_cast<InitFlag>(flag))) {
                success = start({});
            } else {
                success = false;
            }
        });
        return success;
    } else {
        if (init(static_cast<InitFlag>(flag))) {
            return start({});
        }
        return false;
    }
}

- (void)stop
{
    unregisterSignalHandlers();
    confHandlers.clear();
    [self setAccountsActive:false];
}

- (void)setAccountsActive:(BOOL)active
{
    auto accounts = getAccountList();
    for (auto account : accounts) {
        if (active) {
            reloadConversationsAndRequests(account);
        }
        setAccountActive(account, active, true);
    }
}

- (NSDictionary<NSString*, NSString*>*)decrypt:(NSString*)keyPath
                                       accountId:(NSString*)accountId
                                       treated:(NSString*)treatedMessagesPath
                                         value:(NSDictionary*)value
{
    if (![[NSFileManager defaultManager] fileExistsAtPath:keyPath]) {
        return {};
    }

    NSData* data = [[NSFileManager defaultManager] contentsAtPath:keyPath];
    const uint8_t* bytes = (const uint8_t*) [data bytes];
    dht::crypto::PrivateKey dhtKey(bytes, [data length], "");

    Json::Value jsonValue = toJson(value);
    dht::Value dhtValue(jsonValue);

    if (!dhtValue.isEncrypted()) {
        return {};
    }
    try {
        dht::Sp<dht::Value> decrypted = dhtValue.decrypt(dhtKey);
        auto unpacked = msgpack::unpack((const char*) decrypted->data.data(), decrypted->data.size());
        auto peerCR = unpacked.get().as<PeerConnectionRequest>();
        if (peerCR.connType.empty()) {
            // this value is not a PeerConnectionRequest
            // check if it a TrustRequest
            auto conversationRequest = unpacked.get().as<dht::TrustRequest>();
            if (conversationRequest.confirm) {
                // request confirmation. We need to wait for conversation to clone
                return @{@"": @"application/clone"};
            }
            if (!conversationRequest.conversationId.empty()) {
                if (conversationRequest.service == "cx.ring") {
                    // return git message type to start daemon
                    return @{@"": @"application/im-gitmessage-id"};
                }
            }
            return {};
        }
        if (isMessageTreated(peerCR.id, [treatedMessagesPath UTF8String])) {
            return {};
        }

        std::string peerId = "";
        if (peerCR.connType == "videoCall" || peerCR.connType == "audioCall") {
            auto certPath = [[[Constants documentsPath] URLByAppendingPathComponent:accountId] URLByAppendingPathComponent:certificates].path.UTF8String;
            auto crlPath = [[[Constants documentsPath] URLByAppendingPathComponent:accountId] URLByAppendingPathComponent:crls].path.UTF8String;
            auto ocspPath = [[[Constants documentsPath] URLByAppendingPathComponent:accountId] URLByAppendingPathComponent:ocsp].path.UTF8String;
            peerId = getPeerId(decrypted->owner->getId().toString(),
                               certPath,
                               crlPath,
                               ocspPath);
        }
        return @{@(peerId.c_str()): @(peerCR.connType.c_str())};
    } catch (std::runtime_error error) {
    }
    return {};
}

-(NSString*)getNameFor:(NSString*)address accountId:(NSString*)accountId {
    return @(getName(std::string([address UTF8String]), std::string([accountId UTF8String])).c_str());
}

-(NSString*)nameServerForAccountId:(NSString*)accountId; {
    auto nameServer = getNameServer(std::string([accountId UTF8String]));
    return nameServer.empty() ? defaultNameServer : @(nameServer.c_str());
}

Json::Value
toJson(NSDictionary* value)
{
    Json::Value val;
    for (NSString* key in value.allKeys) {
        if ([[value objectForKey:key] isKindOfClass:[NSString class]]) {
            NSString* stringValue = [value objectForKey:key];
            val[key.UTF8String] = stringValue.UTF8String;
        } else if ([[value objectForKey:key] isKindOfClass:[NSNumber class]]) {
            NSNumber* number = [value objectForKey:key];
            if ([key isEqualToString:@"id"]) {
                unsigned long long int intValue = [number unsignedLongLongValue];
                val[key.UTF8String] = intValue;
            } else {
                int intValue = [number intValue];
                val[key.UTF8String] = intValue;
            }
        }
    }
    return val;
}

std::string getName(std::string addres, std::string accountId)
{
    auto name = cachedNames.find(addres);
    if (name != cachedNames.end()) {
        return name->second;
    }

    auto ns = getNameServer(accountId);
    NSURL *url = [NSURL URLWithString: @(ns.c_str())];
    NSString* host = [url host];
    NSString* nameServer = host.length == 0 ? defaultNameServer : host;
    std::string namesPath = [[[Constants cachesPath] URLByAppendingPathComponent: nameCache] URLByAppendingPathComponent: nameServer].path.UTF8String;

    msgpack::unpacker pac;
    // read file
    std::ifstream file = std::ifstream(namesPath, std::ios_base::in);
    if (!file.is_open()) {
        return "";
    }
    std::string line;
    while (std::getline(file, line)) {
        pac.reserve_buffer(line.size());
        memcpy(pac.buffer(), line.data(), line.size());
        pac.buffer_consumed(line.size());
    }

    // load values
    msgpack::object_handle oh;
    if (pac.next(oh))
        oh.get().convert(cachedNames);
    auto cacheRes = cachedNames.find(addres);
    return cacheRes != cachedNames.end() ? cacheRes->second : std::string {};
}

std::string getNameServer(std::string accountId) {
    auto it = nameServers.find(accountId);
    if (it != nameServers.end()) {
        return it->second;
    }
    std::string nameServer {};
    auto accountConfigPath = [[[Constants documentsPath] URLByAppendingPathComponent: @(accountId.c_str())] URLByAppendingPathComponent: accountConfig].path.UTF8String;
    try {
        std::ifstream file = std::ifstream(accountConfigPath, std::ios_base::in);
        YAML::Node node = YAML::Load(file);
        file.close();
        nameServer = node[nameServerConfiguration].as<std::string>();
        if (!nameServer.empty()) {
            nameServers.insert(std::pair<std::string, std::string>(accountId, nameServer));
        }
    } catch (const std::exception& e) {}
    return nameServer;
}

#pragma mark functions copied from the daemon

#define LIKELY(expr)   (expr)
#define UNLIKELY(expr) (expr)

/*
 * Check whether a Unicode (5.2) char is in a valid range.
 *
 * The first check comes from the Unicode guarantee to never encode
 * a point above 0x0010ffff, since UTF-16 couldn't represent it.
 *
 * The second check covers surrogate pairs (category Cs).
 *
 * @param Char the character
 */
#define UNICODE_VALID(Char) ((Char) < 0x110000 && (((Char) &0xFFFFF800) != 0xD800))

#define CONTINUATION_CHAR \
    if ((*(unsigned char*) p & 0xc0) != 0x80) /* 10xxxxxx */ \
        goto error; \
    val <<= 6; \
    val |= (*(unsigned char*) p) & 0x3f;

template<typename ID = dht::Value::Id>
bool
isMessageTreated(ID messageId, const std::string& path)
{
    std::ifstream file = std::ifstream(path, std::ios_base::in);
    if (!file.is_open()) {
        return false;
    }
    std::set<ID, std::less<>> treatedMessages;
    std::string line;
    while (std::getline(file, line)) {
        if constexpr (std::is_same<ID, std::string>::value) {
            treatedMessages.emplace(std::move(line));
        } else if constexpr (std::is_integral<ID>::value) {
            ID vid;
            if (auto [p, ec] = std::from_chars(line.data(), line.data() + line.size(), vid, 16);
                ec == std::errc()) {
                treatedMessages.emplace(vid);
            }
        }
    }
    return treatedMessages.find(messageId) != treatedMessages.end();
}

std::string
getPeerId(const std::string& key,
          const std::string& certPath,
          const std::string& crlPath,
          const std::string& ocspPath)
{
    std::map<std::string, std::shared_ptr<dht::crypto::Certificate>> certs;
    auto dir_content = readDirectory(certPath);
    unsigned n = 0;
    for (const auto& f : dir_content) {
        try {
            auto crt = std::make_shared<dht::crypto::Certificate>(
                loadFile(certPath + fileSeparator + f));
            auto id = crt->getId().toString();
            auto longId = crt->getLongId().toString();
            if (id != f && longId != f)
                throw std::logic_error("Certificate id mismatch");
            while (crt) {
                id = crt->getId().toString();
                longId = crt->getLongId().toString();
                certs.emplace(std::move(id), crt);
                certs.emplace(std::move(longId), crt);
                loadRevocations(*crt, crlPath, ocspPath);
                crt = crt->issuer;
                ++n;
            }
        } catch (const std::exception& e) {
        }
    }
    auto cit = certs.find(key);
    if (cit == certs.cend()) {
        return {};
    }
    dht::InfoHash peer_account_id;
    if (not foundPeerDevice(cit->second, peer_account_id)) {
        return {};
    }
    return peer_account_id.toString();
}

void
loadRevocations(dht::crypto::Certificate& crt,
                const std::string& crlPath,
                const std::string& ocspPath)
{
    auto dir = crlPath + fileSeparator + crt.getId().toString();
    for (const auto& crl : readDirectory(dir)) {
        try {
            crt.addRevocationList(
                std::make_shared<dht::crypto::RevocationList>(loadFile(dir + fileSeparator + crl)));
        } catch (const std::exception& e) {
        }
    }
    auto ocsp_dir = ocspPath + fileSeparator + crt.getId().toString();
    for (const auto& ocsp : readDirectory(ocsp_dir)) {
        try {
            std::string ocsp_filepath = ocsp_dir + fileSeparator + ocsp;
            auto serial = crt.getSerialNumber();
            if (dht::toHex(serial.data(), serial.size()) != ocsp)
                continue;
            dht::Blob ocspBlob = loadFile(ocsp_filepath);
            crt.ocspResponse = std::make_shared<dht::crypto::OcspResponse>(ocspBlob.data(),
                                                                           ocspBlob.size());
        } catch (const std::exception& e) {
        }
    }
}

bool
foundPeerDevice(const std::shared_ptr<dht::crypto::Certificate>& crt, dht::InfoHash& account_id)
{
    if (not crt)
        return false;

    auto top_issuer = crt;
    while (top_issuer->issuer)
        top_issuer = top_issuer->issuer;

    if (top_issuer == crt) {
        return false;
    }
    dht::crypto::TrustList peer_trust;
    peer_trust.add(*top_issuer);
    if (not peer_trust.verify(*crt)) {
        return false;
    }
    if (crt->ocspResponse and crt->ocspResponse->getCertificateStatus() != GNUTLS_OCSP_CERT_GOOD) {
        return false;
    }
    account_id = crt->issuer->getId();
    return true;
}

std::vector<std::string>
readDirectory(const std::string& dir)
{
    NSError* error;
    NSFileManager* fileMgr = [NSFileManager defaultManager];
    NSArray* files = [fileMgr contentsOfDirectoryAtPath:@(dir.c_str()) error:&error];

    std::vector<std::string> vector;
    for (NSString* fileName in files) {
        vector.push_back([fileName UTF8String]);
    }
    return vector;
}

std::vector<uint8_t>
loadFile(const std::string& path)
{
    if (![[NSFileManager defaultManager] fileExistsAtPath:@(path.c_str())]) {
        return {};
    }
    NSData* data = [[NSFileManager defaultManager] contentsAtPath:@(path.c_str())];
    return [Utils vectorOfUInt8FromData:data];
}

std::string
utf8_make_valid(const std::string& name)
{
    ssize_t remaining_bytes = name.size();
    ssize_t valid_bytes;
    const char* remainder = name.c_str();
    const char* invalid;
    char* str = NULL;
    char* pos = nullptr;

    while (remaining_bytes != 0) {
        if (utf8_validate_c_str(remainder, remaining_bytes, &invalid))
            break;

        valid_bytes = invalid - remainder;

        if (str == NULL)
            // If every byte is replaced by U+FFFD, max(strlen(string)) == 3 * name.size()
            str = new char[3 * remaining_bytes];

        pos = str;

        strncpy(pos, remainder, valid_bytes);
        pos += valid_bytes;

        /* append U+FFFD REPLACEMENT CHARACTER */
        pos[0] = '\357';
        pos[1] = '\277';
        pos[2] = '\275';

        pos += 3;

        remaining_bytes -= valid_bytes + 1;
        remainder = invalid + 1;
    }

    if (str == NULL)
        return std::string(name);

    strncpy(pos, remainder, remaining_bytes);
    pos += remaining_bytes;

    std::string answer(str, pos - str);
    assert(utf8_validate_c_str(answer.c_str(), -1, NULL));

    delete[] str;

    return answer;
}

bool
utf8_validate_c_str(const char* str, ssize_t max_len, const char** end)
{
    const char* p;

    if (max_len < 0)
        p = fast_validate(str);
    else
        p = fast_validate_len(str, max_len);

    if (end)
        *end = p;

    if ((max_len >= 0 && p != str + max_len) || (max_len < 0 && *p != '\0'))
        return false;
    else
        return true;
}

static const char*
fast_validate(const char* str)
{
    char32_t val = 0;
    char32_t min = 0;
    const char* p;

    for (p = str; *p; p++) {
        if (*(unsigned char*) p < 128)
            /* done */;
        else {
            const char* last;

            last = p;

            if ((*(unsigned char*) p & 0xe0) == 0xc0) { /* 110xxxxx */
                if (UNLIKELY((*(unsigned char*) p & 0x1e) == 0))
                    goto error;

                p++;

                if (UNLIKELY((*(unsigned char*) p & 0xc0) != 0x80)) /* 10xxxxxx */
                    goto error;
            } else {
                if ((*(unsigned char*) p & 0xf0) == 0xe0) { /* 1110xxxx */
                    min = (1 << 11);
                    val = *(unsigned char*) p & 0x0f;
                    goto TWO_REMAINING;
                } else if ((*(unsigned char*) p & 0xf8) == 0xf0) { /* 11110xxx */
                    min = (1 << 16);
                    val = *(unsigned char*) p & 0x07;
                } else
                    goto error;

                p++;
                CONTINUATION_CHAR;
            TWO_REMAINING:
                p++;
                CONTINUATION_CHAR;
                p++;
                CONTINUATION_CHAR;

                if (UNLIKELY(val < min))
                    goto error;

                if (UNLIKELY(!UNICODE_VALID(val)))
                    goto error;
            }

            continue;

        error:
            return last;
        }
    }

    return p;
}

static const char*
fast_validate_len(const char* str, ssize_t max_len)
{
    char32_t val = 0;
    char32_t min = 0;
    const char* p;

    assert(max_len >= 0);

    for (p = str; ((p - str) < max_len) && *p; p++) {
        if (*(unsigned char*) p < 128)
            /* done */;
        else {
            const char* last;

            last = p;

            if ((*(unsigned char*) p & 0xe0) == 0xc0) { /* 110xxxxx */
                if (UNLIKELY(max_len - (p - str) < 2))
                    goto error;

                if (UNLIKELY((*(unsigned char*) p & 0x1e) == 0))
                    goto error;

                p++;

                if (UNLIKELY((*(unsigned char*) p & 0xc0) != 0x80)) /* 10xxxxxx */
                    goto error;
            } else {
                if ((*(unsigned char*) p & 0xf0) == 0xe0) { /* 1110xxxx */
                    if (UNLIKELY(max_len - (p - str) < 3))
                        goto error;

                    min = (1 << 11);
                    val = *(unsigned char*) p & 0x0f;
                    goto TWO_REMAINING;
                } else if ((*(unsigned char*) p & 0xf8) == 0xf0) { /* 11110xxx */
                    if (UNLIKELY(max_len - (p - str) < 4))
                        goto error;

                    min = (1 << 16);
                    val = *(unsigned char*) p & 0x07;
                } else
                    goto error;

                p++;
                CONTINUATION_CHAR;
            TWO_REMAINING:
                p++;
                CONTINUATION_CHAR;
                p++;
                CONTINUATION_CHAR;

                if (UNLIKELY(val < min))
                    goto error;

                if (UNLIKELY(!UNICODE_VALID(val)))
                    goto error;
            }

            continue;

        error:
            return last;
        }
    }

    return p;
}

@end
