/*
 *  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)
};

typedef NS_ENUM(NSInteger, NotificationType) { videoCall, audioCall, gitMessage, unknown };

// 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>(
        [&](const std::string& accountId,
            const std::string& conversationId,
            std::map<std::string, std::string> message) {
            if (Adapter.delegate) {
                NSString* convId = [NSString stringWithUTF8String:conversationId.c_str()];
                NSString* account = [NSString stringWithUTF8String:accountId.c_str()];
                NSMutableDictionary* interaction = [Utils mapToDictionnary:message];
                [Adapter.delegate newInteractionWithConversationId:convId
                                                         accountId:account
                                                           message:interaction];
            }
        }));

    confHandlers.insert(exportable_callback<DataTransferSignal::DataTransferEvent>(
        [&](const std::string& account_id,
            const std::string& conversation_id,
            const std::string& interaction_id,
            const std::string& file_id,
            int eventCode) {
            if (Adapter.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()];
                [Adapter.delegate dataTransferEventWithFileId:fileId
                                                withEventCode:eventCode
                                                    accountId:accountId
                                               conversationId:conversationId
                                                interactionId:interactionId];
            }
        }));

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

    confHandlers.insert(exportable_callback<ConversationSignal::ConversationRequestReceived>([&](const std::string& accountId, const std::string& conversationId, std::map<std::string, std::string> metadata) {
        if(Adapter.delegate) {
            NSString* accountIdStr = [NSString stringWithUTF8String:accountId.c_str()];
            NSString* convIdStr = [NSString stringWithUTF8String:conversationId.c_str()];
            NSMutableDictionary* info = [Utils mapToDictionnary: metadata];
            [Adapter.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) {
        setAccountActive(std::string([accountId UTF8String]), true);
        return true;
    }
#if DEBUG
    int flag = LIBJAMI_FLAG_CONSOLE_LOG | LIBJAMI_FLAG_DEBUG | LIBJAMI_FLAG_IOS_EXTENSION;
#else
    int flag = LIBJAMI_FLAG_IOS_EXTENSION;;
#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) {
        setAccountActive(account, active, true);
    }
}

- (NSDictionary<NSString*, NSString*>*)decrypt:(NSString*)keyPath
                                       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.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 {};
        }
        auto certPath = [[Constants documentsPath] URLByAppendingPathComponent:certificates].path.UTF8String;
        auto crlPath = [[Constants documentsPath] URLByAppendingPathComponent:crls].path.UTF8String;
        auto ocspPath = [[Constants documentsPath] URLByAppendingPathComponent:ocsp].path.UTF8String;
        std::string 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
