/*
    kopetechatsessionmanager.cpp - Creates chat sessions

    Copyright (c) 2002-2003 by Duncan Mac-Vicar Prett <duncan@kde.org>

    Kopete    (c) 2002-2003 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This library is free software; you can redistribute it and/or         *
    * modify it under the terms of the GNU Lesser General Public            *
    * License as published by the Free Software Foundation; either          *
    * version 2 of the License, or (at your option) any later version.      *
    *                                                                       *
    *************************************************************************
*/

#include "kopetechatsessionmanager.h"
#include "kopeteviewmanager.h"

#include <kapplication.h>

#include "ui/kopeteview.h"
#include "kopetecontact.h"
#include <QList>

namespace Kopete {
class ChatSessionManager::Private
{
public:
    QList <ChatSession *> sessions;
//	UI::ChatView *activeView;
};

ChatSessionManager *ChatSessionManager::s_self = nullptr;

ChatSessionManager *ChatSessionManager::self()
{
    if (!s_self) {
        s_self = new ChatSessionManager(kapp);
    }

    return s_self;
}

ChatSessionManager::ChatSessionManager(QObject *parent)
    : QObject(parent)
    , d(new Private())
{
    s_self = this;
}

ChatSessionManager::~ChatSessionManager()
{
    s_self = nullptr;
    QList<ChatSession *>::ConstIterator it;
    for (it = d->sessions.constBegin(); it != d->sessions.constEnd(); ++it) {
        qCDebug(LIBKOPETE_LOG) << "Unloading KMM: Why this KMM isn't yet unloaded?";
        (*it)->deleteLater();
    }
    delete d;
}

ChatSession *ChatSessionManager::findChatSession(const Contact *user, ContactPtrList chatContacts, Protocol *protocol)
{
    ChatSession *result = nullptr;
    QList<ChatSession *>::ConstIterator it;
    int i;

    for (it = d->sessions.constBegin(); it != d->sessions.constEnd() && !result; ++it) {
        ChatSession *cs = (*it);
        if (cs->protocol() == protocol && user == cs->myself()) {
            QList<Contact *> contactlist = cs->members();

            // set this to false if chatContacts doesn't contain current cs's contact list
            bool halfMatch = true;

            for (i = 0; i != contactlist.size() && halfMatch; i++) {
                if (!chatContacts.contains(contactlist[i])) {
                    halfMatch = false;
                }
            }

            // If chatContacts contains current cs's contactlist, try the other way around
            if (halfMatch) {
                bool fullMatch = true;
                for (i = 0; i != chatContacts.size() && fullMatch; i++) {
                    if (!contactlist.contains(chatContacts[i])) {
                        fullMatch = false;
                    }
                }
                // We have a winner
                if (fullMatch) {
                    result = cs;
                }
            }
        }
    }
    return result;
}

ChatSession *ChatSessionManager::create(
    const Contact *user, ContactPtrList chatContacts, Protocol *protocol, Kopete::ChatSession::Form form)
{
    ChatSession *result = findChatSession(user, chatContacts, protocol);
    if (!result) {
        result = new ChatSession(user, chatContacts, protocol, form);
        registerChatSession(result);
    }
    return result;
}

void ChatSessionManager::slotReadMessage()
{
    emit readMessage();
}

void ChatSessionManager::registerChatSession(ChatSession *result)
{
    d->sessions.append(result);

    /*
     * There's no need for a slot here... just add a public remove()
     * method and call from KMM's destructor
     */
    connect(result, SIGNAL(messageAppended(Kopete::Message&,Kopete::ChatSession*)),
            SIGNAL(aboutToDisplay(Kopete::Message&)));
    connect(result, SIGNAL(messageSent(Kopete::Message&,Kopete::ChatSession*)),
            SIGNAL(aboutToSend(Kopete::Message&)));
    connect(result, SIGNAL(messageReceived(Kopete::Message&,Kopete::ChatSession*)),
            SIGNAL(aboutToReceive(Kopete::Message&)));

    connect(result, SIGNAL(messageAppended(Kopete::Message&,Kopete::ChatSession*)),
            SIGNAL(display(Kopete::Message&,Kopete::ChatSession*)));

    emit chatSessionCreated(result);
}

void ChatSessionManager::removeSession(ChatSession *session)
{
    qCDebug(LIBKOPETE_LOG);
    d->sessions.removeAll(session);
}

QList<ChatSession *> ChatSessionManager::sessions()
{
    return d->sessions;
}

KopeteView *ChatSessionManager::createView(ChatSession *kmm, const QString &requestedPlugin)
{
    KopeteView *newView = KopeteViewManager::viewManager()->view(kmm, requestedPlugin);
    if (!newView) {
        qCDebug(LIBKOPETE_LOG) << "View not successfuly created";
        return nullptr;
    }

    QObject *viewObject = dynamic_cast<QObject *>(newView);
    if (viewObject) {
        connect(viewObject, SIGNAL(activated(KopeteView*)),
                this, SIGNAL(viewActivated(KopeteView*)));
        connect(viewObject, SIGNAL(closing(KopeteView*)),
                this, SIGNAL(viewClosing(KopeteView*)));
    } else {
        qCWarning(LIBKOPETE_LOG) << "Failed to cast view to QObject *";
    }

    emit viewCreated(newView);
    return newView;
}

void ChatSessionManager::postNewEvent(MessageEvent *e)
{
    emit newEvent(e);
}

KopeteView *ChatSessionManager::activeView()
{
    return KopeteViewManager::viewManager()->activeView();
}
} //END namespace Kopete

// vim: set noet ts=4 sts=4 sw=4:
