void TpSessionChannel::onChannelDestroyed(QObject *obj)
{
    QDEBUG_FUNCTION_BEGIN
    Q_UNUSED(obj);

    qDebug() << "TpSessionChannel::onChannelDestroyed";
    //TpSessionChannel *call = (TpSessionChannel *) obj;
    emit channelDestroyed(this);
    QDEBUG_FUNCTION_END
}
// Channel
bool QSpiceChannel::objectDisposed()
{
    emit channelDestroyed();
    return true;
}
void WebSocketManager::processWsData(const QString &data)
{
    QJsonParseError error;
    QJsonDocument jsonDocument = QJsonDocument::fromJson(data.toLatin1(), &error);

    if (error.error != QJsonParseError::NoError)
        return;

    QString eventName = jsonDocument.object().value("name").toString();
    if (eventName == "CHANNEL_CREATE")
    {
        QJsonObject args = jsonDocument.object().value("args").toObject();
        QString callDirection = args.value("Call-Direction").toString();

        if (callDirection != "inbound") return; 

        QString callerNumber = args.value("Caller-ID-Number").toString();
        QString callId = args.value("Call-ID").toString();

        m_contactCallIdHash.insert(callerNumber, callId);

        m_createChannelHash.insert(callId, callerNumber);
        //QString calleeNumber = args.value("Callee-ID-Number").toString();

        if (m_contactsHash.contains(callerNumber))
        {
            ContactInfo *contactInfo = m_contactsHash.value(callerNumber);
            if (!contactInfo->isEmpty())
                emit channelCreated(contactInfo);
            return;
        }

        QByteArray hashTemplate(callerNumber.toLatin1());
        hashTemplate.append(":");
        hashTemplate.append(m_settings->value("md5_hash", kMd5Hash).toString());

        QByteArray hash = QCryptographicHash::hash(hashTemplate, QCryptographicHash::Md5).toHex();

        QNetworkRequest req;
        QString url(m_settings->value("info_url", kInfoUrl).toString());
        url.append(kCallerInfoQuery);
        req.setUrl(QUrl(url.arg(callerNumber).arg(hash.data())));
        QNetworkReply *reply = m_nam->get(req);
        reply->setProperty("caller_number", callerNumber);

        m_contactsHash.insert(callerNumber, new ContactInfo());

        connect(reply, &QNetworkReply::finished,
                this, &WebSocketManager::retrieveCallerInfoFinished);
    }
    else if (eventName == "CHANNEL_ANSWER")
    {
        QJsonObject args = jsonDocument.object().value("args").toObject();
        QString callDirection = args.value("Call-Direction").toString();

        if (callDirection != "inbound") return;

        QString callId = args.value("Call-ID").toString();
        QString calleeNumber = args.value("Callee-ID-Number").toString();
        if (!calleeNumber.isEmpty())
        {
            bool ok;
            qlonglong number = calleeNumber.toLongLong(&ok);
            Q_UNUSED(number);
            if (!ok)
                return;
        }

        QString callerNumber = m_contactCallIdHash.key(callId);

        if (m_contactsHash.contains(callerNumber))
        {
            ContactInfo *contactInfo = m_contactsHash.value(callerNumber);
            if (!contactInfo->isEmpty())
            {
                emit channelAnswered(contactInfo);
                m_contactCallIdHash.remove(callerNumber);
            }
        }
    }
    else if (eventName == "CHANNEL_DESTROY")
    {
        QJsonObject args = jsonDocument.object().value("args").toObject();
        //QString callerNumber = args.value("Caller-ID-Number").toString();
        QString callId = args.value("Call-ID").toString();

        if (m_createChannelHash.contains(callId))
        {
            QString number = m_createChannelHash.value(callId);
            m_createChannelHash.remove(callId);

            if (!m_createChannelHash.values().contains(number))
            {
                ContactInfo *contactInfo = m_contactsHash.value(number);
                m_contactsHash.remove(number);
                emit channelDestroyed(contactInfo);
            }
        }
    }
}