//============================================================================
// Copyright 2009-2020 ECMWF.
// This software is licensed under the terms of the Apache Licence version 2.0
// which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
// In applying this licence, ECMWF does not waive the privileges and immunities
// granted to it by virtue of its status as an intergovernmental organisation
// nor does it submit to any jurisdiction.
//
//============================================================================

#include "TriggerTableModel.hpp"

#include "IconProvider.hpp"
#include "ServerHandler.hpp"
#include "VAttribute.hpp"
#include "VAttributeType.hpp"
#include "VIcon.hpp"
#include "VNode.hpp"

#include <QDebug>

TriggerTableModel::TriggerTableModel(Mode mode,QObject *parent) :
          QAbstractItemModel(parent),
          tc_(nullptr),      
          mode_(mode)
{
}

TriggerTableModel::~TriggerTableModel()
= default;


void TriggerTableModel::clearData()
{
    beginResetModel();
    tc_=nullptr;
    endResetModel();
}

void TriggerTableModel::beginUpdate()
{
	beginResetModel();
}

void TriggerTableModel::endUpdate()
{
	endResetModel();
}


void TriggerTableModel::setTriggerCollector(TriggerTableCollector *tc)
{
    //beginResetModel();
    tc_ = tc;
    //endResetModel();
}

bool TriggerTableModel::hasData() const
{
    if(tc_)
		return tc_->size() > 0;
	else
		return false;
}

int TriggerTableModel::columnCount( const QModelIndex& /*parent */) const
{
     return 1;
}

int TriggerTableModel::rowCount( const QModelIndex& parent) const
{
	if(!hasData())
		return 0;

	//Parent is the root:
	if(!parent.isValid())
	{
		return tc_->size();
	}

	return 0;
}

Qt::ItemFlags TriggerTableModel::flags ( const QModelIndex & index) const
{
	return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}

QVariant TriggerTableModel::data( const QModelIndex& index, int role ) const
{   
    if(!index.isValid() || !hasData() || (role < Qt::UserRole &&
        role != Qt::DisplayRole && role != Qt::BackgroundRole && role != Qt::TextAlignmentRole &&
        role != Qt::ToolTipRole && role != Qt::ForegroundRole))
    {
		return QVariant();
	}

	int row=index.row();
    if(row < 0 || row >= static_cast<int>(tc_->size()))
		return QVariant();

    //QString id=columns_->id(index.column());

    const std::vector<TriggerTableItem*>& items=tc_->items();
	VItem *t=items[row]->item();
    Q_ASSERT(t);

    if(index.column() == 0)
    {
        if(VAttribute* a=t->isAttribute())
        {
            if(role == Qt::DisplayRole)
            {
                QStringList d=a->data();
                if(VNode* pn=a->parent())
                    d.append(QString::fromStdString(pn->absNodePath()));
                return d;
            }
            else if(role ==  Qt::ToolTipRole)
            {
                return a->toolTip();
            }

        }
        else if(VNode* vnode=t->isNode())
        {
            if(role == Qt::DisplayRole)
            {
                return QString::fromStdString(vnode->absNodePath());
            }
            else if(role == Qt::BackgroundRole)
            {
                if(vnode->isSuspended())
                {
                    QVariantList lst;
                    lst << vnode->stateColour() << vnode->realStateColour();
                    return lst;
                }
                else
                    return vnode->stateColour() ;
            }
            else if(role == Qt::ForegroundRole)
                return vnode->stateFontColour();

            else if(role == Qt::ToolTipRole)
            {
                QString txt=vnode->toolTip();
                //txt+=VIcon::toolTip(vnode,icons_);
                return txt;
            }
            else if(role == IconRole)
            {
                return VIcon::pixmapList(vnode,nullptr);
            }
            else if(role  == NodeTypeRole)
            {
                 if(vnode->isTask()) return 2;
                 else if(vnode->isSuite()) return 0;
                 else if(vnode->isFamily()) return 1;
                 else if(vnode->isAlias()) return 3;
                 return 0;
            }
            else if(role  == NodeTypeForegroundRole)
            {
                return vnode->typeFontColour();
            }
            else if(role  == NodePointerRole)
            {
                 return qVariantFromValue((void *) vnode);
            }

            else if(role  == Qt::TextAlignmentRole)
            {
                return( mode_==NodeMode)?Qt::AlignCenter:Qt::AlignLeft;
            }

        }
    }

    //We express the table cell background colour through the UserRole. The
    //BackgroundRole is already used for the node rendering
    if(role == Qt::UserRole && mode_ != NodeMode)
    {
        const std::set<TriggerCollector::Mode>&  modes=items[row]->modes();
        if(modes.find(TriggerCollector::Normal) != modes.end())
            return QVariant();
        else
            return QColor(233,242,247);
    }

	return QVariant();
}

QVariant TriggerTableModel::headerData( const int section, const Qt::Orientation orient , const int role ) const
{
	if ( orient != Qt::Horizontal)
            return QAbstractItemModel::headerData( section, orient, role );

	return QVariant();
}

QModelIndex TriggerTableModel::index( int row, int column, const QModelIndex & parent ) const
{
	if(!hasData() || row < 0 || column < 0)
	{
		return {};
	}

	//When parent is the root this index refers to a node or server
	if(!parent.isValid())
	{
		return createIndex(row,column);
	}

	return {};

}

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

VInfo_ptr TriggerTableModel::nodeInfo(const QModelIndex& index)
{
	//For invalid index no info is created.
	if(!index.isValid())
	{
		VInfo_ptr res;
		return res;
	}

    if(index.row() >=0 && index.row() <= static_cast<int>(tc_->items().size()))
	{
        TriggerTableItem* d=tc_->items()[index.row()];
        return VInfo::createFromItem(d->item());
    }

    VInfo_ptr res;
	return res;
}

QModelIndex TriggerTableModel::itemToIndex(TriggerTableItem *item)
{
    if(item)
    {
         for(std::size_t i=0; i < tc_->items().size(); i++)
             if(tc_->items()[i] == item)
                 return index(i,0);
    }

    return {};
}

TriggerTableItem* TriggerTableModel::indexToItem(const QModelIndex& index) const
{
    if(!hasData())
        return nullptr;

    int row=index.row();
    if(row < 0 || row >= static_cast<int>(tc_->size()))
        return nullptr;

    const std::vector<TriggerTableItem*>& items=tc_->items();
    return items[row];
}

void TriggerTableModel::nodeChanged(const VNode* node, const std::vector<ecf::Aspect::Type>&)
{
    if(!hasData())
        return;

    int num=tc_->items().size();
    for(int i=0; i < num; i++)
    {
        if(VItem* item=tc_->items()[i]->item())
        {
            if(VNode* n=item->isNode())
            {
                if(n == node)
                {
                    QModelIndex idx=index(i,0);
                    Q_EMIT dataChanged(idx,idx);
                }
            }

            else if(VAttribute* a=item->isAttribute())
            {
                if(a->parent() == node)
                {                                                                              
                    QModelIndex idx=index(i,0);
                    Q_EMIT dataChanged(idx,idx);
                }
            }
        }
    }
}
