/********************************************************************
 KWin - the KDE window manager
 This file is part of the KDE project.

Copyright (C) 2009 Martin Gräßlin <kde@martin-graesslin.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 2 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, see <http://www.gnu.org/licenses/>.
*********************************************************************/
// own
#include "desktopmodel.h"
// tabbox
#include "clientmodel.h"
#include "tabboxconfig.h"
#include "tabboxhandler.h"

#include <math.h>

namespace KWin
{
namespace TabBox
{

DesktopModel::DesktopModel(QObject* parent)
    : QAbstractItemModel(parent)
{
}

DesktopModel::~DesktopModel()
{
}

QVariant DesktopModel::data(const QModelIndex& index, int role) const
{
    if (!index.isValid())
        return QVariant();

    int desktopIndex = index.row() * columnCount() + index.column();
    if (desktopIndex >= m_desktopList.count())
        return QVariant();
    switch(role) {
    case Qt::DisplayRole:
    case DesktopNameRole:
        return tabBox->desktopName(m_desktopList[ desktopIndex ]);
    case DesktopRole:
        return m_desktopList[ desktopIndex ];
    case ClientModelRole:
        return qVariantFromValue((void*)m_clientModels[ m_desktopList[ desktopIndex ] ]);
    default:
        return QVariant();
    }
}

int DesktopModel::columnCount(const QModelIndex& parent) const
{
    Q_UNUSED(parent)
    int count = 1;
    switch(tabBox->config().layout()) {
    case TabBoxConfig::HorizontalLayout:
        count = m_desktopList.count();
        break;
    case TabBoxConfig::VerticalLayout:
        count = 1;
        break;
    case TabBoxConfig::HorizontalVerticalLayout:
        count = qRound(sqrt(float(m_desktopList.count())));
        if (count * count < m_desktopList.count())
            count++;
        // TODO: pager layout?
        break;
    }
    return qMax(count, 1);
}

int DesktopModel::rowCount(const QModelIndex& parent) const
{
    Q_UNUSED(parent)
    int count = 1;
    switch(tabBox->config().layout()) {
    case TabBoxConfig::HorizontalLayout:
        count = 1;
        break;
    case TabBoxConfig::VerticalLayout:
        count = m_desktopList.count();
        break;
    case TabBoxConfig::HorizontalVerticalLayout:
        count = qRound(sqrt(float(m_desktopList.count())));
        // TODO: pager layout?
        break;
    }
    return qMax(count, 1);
}

QModelIndex DesktopModel::parent(const QModelIndex& child) const
{
    Q_UNUSED(child)
    return QModelIndex();
}

QModelIndex DesktopModel::index(int row, int column, const QModelIndex& parent) const
{
    Q_UNUSED(parent)
    int index = row * columnCount() + column;
    if (index > m_desktopList.count() || m_desktopList.isEmpty())
        return QModelIndex();
    return createIndex(row, column);
}

QModelIndex DesktopModel::desktopIndex(int desktop) const
{
    if (desktop > m_desktopList.count())
        return QModelIndex();
    int index = m_desktopList.indexOf(desktop);
    int row = index / columnCount();
    int column = index % columnCount();
    return createIndex(row, column);
}

void DesktopModel::createDesktopList()
{
    m_desktopList.clear();
    qDeleteAll(m_clientModels);
    m_clientModels.clear();

    switch(tabBox->config().desktopSwitchingMode()) {
    case TabBoxConfig::MostRecentlyUsedDesktopSwitching: {
        int desktop = tabBox->currentDesktop();
        do {
            m_desktopList.append(desktop);
            ClientModel* clientModel = new ClientModel(this);
            clientModel->createClientList(desktop);
            m_clientModels.insert(desktop, clientModel);
            desktop = tabBox->nextDesktopFocusChain(desktop);
        } while (desktop != tabBox->currentDesktop());
        break;
    }
    case TabBoxConfig::StaticDesktopSwitching: {
        for (int i = 1; i <= tabBox->numberOfDesktops(); i++) {
            m_desktopList.append(i);
            ClientModel* clientModel = new ClientModel(this);
            clientModel->createClientList(i);
            m_clientModels.insert(i, clientModel);
        }
        break;
    }
    }
    reset();
}

} // namespace Tabbox
} // namespace KWin