
/*-----------------------------------------------------------------------------------------------*/
/* badgeCount_signaling.cpp                                                                      */
/* copyright (c) innovaphone 2018                                                                */
/*                                                                                               */
/*-----------------------------------------------------------------------------------------------*/

#include <platform.h>
#include "sdk/common/os/iomux.h"
#include "sdk/common/interface/task.h"
#include "sdk/common/interface/webserver_plugin.h"
#include "sdk/common/interface/database.h"
#include "sdk/common/interface/json_api.h"
#include "common/ilib/json.h"
#include "common/ilib/str.h"
#include "sdk/common/lib/appwebsocket.h"
#include "sdk/common/lib/app_updates.h"
#include "sdk/common/lib/badgecount_signaling.h"

#define DBG_SIGNALING(x) debug->printf x
#define DBG_PRESENCE(x) debug->printf x

/*-----------------------------------------------------------------------------------------------*/
/* BadgeCountSignaling                                                                           */
/*-----------------------------------------------------------------------------------------------*/

BadgeCountSignaling::BadgeCountSignaling(class UBadgeCountSignaling * user, class AppUpdatesSession * session)
{
    DBG_SIGNALING(("BadgeCountSignaling::BadgeCountSignaling"));
    this->user = user;
    this->session = session;
    char sb[1000];
    class json_io send(sb);
    word base = send.add_object(0xffff, 0);
    send.add_string(base, "mt", "Register");
    send.add_string(base, "api", "PbxSignal");
    send.add_string(base, "flags", "NO_MEDIA_CALL");

    session->AppWebsocketMessageSend(send, sb);
    session->RegisterJsonApi(this);

    calls = 0;
    call = 0;
}

BadgeCountSignaling::~BadgeCountSignaling()
{
    DBG_SIGNALING(("BadgeCountSignaling::~BadgeCountSignaling"));
    while (calls) delete calls;
    session->UnRegisterJsonApi(this);
}

void BadgeCountSignaling::Message(class json_io & msg, word base, const char * mt, const char * src)
{
    DBG_SIGNALING(("BadgeCountSignaling::Message(%s)", mt));
    session->AppWebsocketMessageComplete();

    if (!strcmp(mt, "Signaling")) {
        int call = msg.get_int(base, "call");
        class btree * b = calls->btree_find((void *)(intp)call);
        word handle = msg.get_object(base, "sig");
        const char * type = (handle != 0xffff) ? msg.get_string(handle, "type") : 0;
        if (call && type) {
            if (b) {
                DBG_SIGNALING(("%i:%s", call, type));
                ((class BadgeCountCall *)b)->Signaling(msg, handle, src, type);
                return;
            }
            else {
                if (type && !strcmp(type, "setup")) {
                    const char * cg = msg.get_string(msg.get_object(handle, "cg"), "sip");
                    const char * cd = msg.get_string(msg.get_object(handle, "cd"), "sip");
                    DBG_SIGNALING(("%i:%s(%s->%s)", call, type, cg, cd));

                    if (cg && cd) {
                        word fty = msg.get_array(handle, "fty");
                        for (word f = 0; msg.get_object(fty, f) != 0xffff;) {
                            const char * ftype = msg.get_string(f, "type");

                            if (ftype) {

                                if (!strcmp(ftype, "presence_subscribe")) {
                                    for (unsigned i = 0; cd[i]; i++) {
                                        if (cd[i] == '@') {
                                            ((char *)cd)[i] = 0;
                                            break;
                                        }
                                    }
                                    for (unsigned i = 0; cd[i]; i++) {
                                        if (cd[i] == '~') {
                                            ((char *)cd)[i] = 0;
                                            break;
                                        }
                                    }
                                    user->CreateBadgeCountPresenceMonitor(this, call, cg, cd);
                                    return;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

void BadgeCountSignaling::JsonApiConnectionClosed()
{
    DBG_SIGNALING(("BadgeCountSignaling::JsonApiConnectionClosed()"));
    delete this;
}

int BadgeCountSignaling::nextCall()
{
    do {
        call++;
        if (call == 1000000) call = 1;
    } while (calls->btree_find((void *)(intp)call));
    return call;
}

/*-----------------------------------------------------------------------------------------------*/
/* BadgeCountCall                                                                                */
/*-----------------------------------------------------------------------------------------------*/

BadgeCountCall::BadgeCountCall(class BadgeCountSignaling * signaling, int call)
{
    DBG_SIGNALING(("BadgeCountCall::BadgeCountCall(%x:%i)", signaling, call));
    this->signaling = signaling;
    this->call = call;

    signaling->calls = signaling->calls->btree_put(this);
}

BadgeCountCall::~BadgeCountCall()
{
    DBG_SIGNALING(("BadgeCountCall::~BadgeCountCall(%x:%i)", signaling, call));
    signaling->calls = signaling->calls->btree_get(this);
}

void BadgeCountCall::SendConn()
{
    char sb[5000];
    class json_io send(sb);
    char b[1000];
    char * tmp = b;
    word base = send.add_object(0xffff, 0);
    send.add_string(base, "mt", "Signaling");
    send.add_string(base, "api", "PbxSignal");
    send.add_int(base, "call", call, tmp);
    word handle = send.add_object(base, "sig");
    send.add_string(handle, "type", "conn");
    signaling->session->AppWebsocketMessageSend(send, sb);
    state = 10;
}

void BadgeCountCall::SendRel()
{
    char sb[5000];
    class json_io send(sb);
    char b[1000];
    char * tmp = b;
    word base = send.add_object(0xffff, 0);
    send.add_string(base, "mt", "Signaling");
    send.add_string(base, "api", "PbxSignal");
    send.add_int(base, "call", call, tmp);
    word handle = send.add_object(base, "sig");
    send.add_string(handle, "type", "rel");
    signaling->session->AppWebsocketMessageSend(send, sb);
    state = 0;
}

/*-----------------------------------------------------------------------------------------------*/
/* BadgeCountPresenceMonitor                                                                     */
/*-----------------------------------------------------------------------------------------------*/

BadgeCountPresenceMonitor::BadgeCountPresenceMonitor(class BadgeCountSignaling * signaling, int call) : BadgeCountCall(signaling, call)
{
    DBG_PRESENCE(("%i:BadgeCountPresenceMonitor(%s)", call, signaling->session->app));

    SendConn();
}

BadgeCountPresenceMonitor::~BadgeCountPresenceMonitor()
{
    DBG_PRESENCE(("%i:~BadgeCountPresenceMonitor()", call));
}

void BadgeCountPresenceMonitor::Signaling(class json_io & msg, word base, const char * src, const char * type)
{
    if (!strcmp(type, "rel")) {
        state = 0;
        delete this;
    }
}

void BadgeCountPresenceMonitor::SendBadge(ulong64 count)
{
    DBG_PRESENCE(("%i:~BadgeCountPresenceMonitor::SendBadge(%llu)", call, count));
    char sb[500];
    class json_io send(sb);
    char b[100];
    char * tmp = b;
    word base = send.add_object(0xffff, 0);
    send.add_string(base, "mt", "Signaling");
    send.add_string(base, "api", "PbxSignal");
    send.add_int(base, "call", call, tmp);
    word sig = send.add_object(base, "sig");
    send.add_string(sig, "type", "facility");
    word fty = send.add_array(sig, "fty");
    word handle = send.add_object(fty, 0);
    send.add_string(handle, "type", "presence_notify");
    send.add_string(handle, "status", "open");
    if (count) send.add_printf(handle, "note", tmp, "#badge:%llu", count);
    send.add_string(handle, "contact", "app:");
    signaling->session->SendUpdate(send, sb);
}

