#include "multiverseitem.h"
#include "multiversemodel.h"

#include <QFont>
#include <QMetaEnum>
#include <QMetaType>


/**
 * @brief MultiverseItem::MultiverseItem
 * @param universe
 * @param parent
 */
MultiverseItem::MultiverseItem(MultiverseItem* parent,
                               QSacnUniverse* universe,
                               discoveredUniverse *discovery)
  : universe_(universe)
  , discovery_(discovery)
  , parentItem_(parent)
  , override_data_(QVariant())
{
  createChildren();

  if(parent)
    parent->appendChild(this);
}


/**
 * @brief MultiverseItem::~MultiverseItem
 */
MultiverseItem::~MultiverseItem()
{
  qDeleteAll(childItems_);
}


/**
 * @brief MultiverseItem::appendChild
 * @param item
 */
void MultiverseItem::appendChild(MultiverseItem* item)
{
  childItems_.append(item);
}

/**
 * @brief MultiverseItem::removeChild
 * @param child
 */
void MultiverseItem::removeChild(MultiverseItem* child)
{
  for (int i = 0; i < childItems_.size(); ++i)
    if (childItems_.at(i) == child)
      childItems_.remove(i);
}


/**
 * @brief MultiverseItem::removeChildren
 */
void MultiverseItem::removeChildren()
{
  qDeleteAll(childItems_);
  childItems_.clear();
}


/**
 * @brief MultiverseItem::setOverrideData
 * @param data
 */
void MultiverseItem::setOverrideData(QVariant data)
{
  override_data_ = data;
}


/**
 * @brief MultiverseItem::createChildren
 */
void MultiverseItem::createChildren()
{
  if (!universe_)
    return;

  auto sources = universe_->sources();
  for (const auto & metadata : sources)
    {
      auto universe = universe_->sourceUniverse(metadata);
      if (universe)
        new MultiverseItem(this, universe);
    }
}


/**
 * @brief MultiverseItem::child
 * @param row
 * @return
 */
MultiverseItem* MultiverseItem::child(int row)
{
  if (row < 0 || row >= childItems_.size())
    return nullptr;
  return childItems_.at(row);
}


/**
 * @brief MultiverseItem::childCount
 * @return
 */
int MultiverseItem::childCount() const
{
  return childItems_.count();
}


/**
 * @brief MultiverseItem::childRow
 * @param universe
 * @return
 */
int MultiverseItem::childRow(int column, const QVariant &data) const
{
  for (int row = 0; row < childItems_.size(); row++)
    {
      auto childData = childItems_.at(row)->data(column, Qt::EditRole);
      if (data == childData)
        return row;
    }
  return -1;
}


/**
 * @brief MultiverseItem::row
 * @return
 */
int MultiverseItem::row() const
{
  if (parentItem_)
    return parentItem_->childItems_.indexOf(const_cast<MultiverseItem*>(this));
  return 0;
}


/**
 * @brief MultiverseItem::data
 * @param column
 * @return
 */
QVariant MultiverseItem::data(int column, int role) const
{
  switch (role) {
    case Qt::DisplayRole:
      {
        if (!universe_ && !discovery_)
          {
            if (column)
              return QVariant();
            return QString("%1 (%2)").arg(
                  override_data_.toString(),
                  QString::number(childCount()));
          }
        if (universe_)
          {
            switch (static_cast<MultiverseModel::Column>(column))
              {
              case MultiverseModel::Universe:
                return universe_->number();
              case MultiverseModel::Priority:
                {
                  auto v = universe_->priority();
                  if (v > 200)
                    return QVariant();
                  return v;
                }
              case MultiverseModel::Channels:
                {
                  auto active = universe_->activeSlots();
                  return active ? active - 1 : active;
                }
              case MultiverseModel::Description:
                return universe_->description();
              default:
                return QVariant();
              }
          }
        if (discovery_)
          {
            switch (static_cast<MultiverseModel::Column>(column))
              {
              case MultiverseModel::Universe:
                return discovery_->universe;
              case MultiverseModel::Description:
                return QString::fromUtf8(discovery_->description.c_str());
              default:
                return QVariant();
              }
          }
      }
    case Qt::FontRole:
      if (!universe_ && !discovery_)
        {
          QFont bold;
          bold.setBold(true);
          return QVariant(bold);
        }
      return QVariant();
    case Qt::EditRole:
      if (universe_)
        return QVariant(QVariant::fromValue(universe_));
      if (discovery_)
        return QVariant(QVariant::fromValue(discovery_));
      return data(column, Qt::DisplayRole);
    default:
      return QVariant();
    }
}


/**
 * @brief MultiverseItem::flags
 * @param column
 * @return
 */
Qt::ItemFlags MultiverseItem::flags(int column, Qt::ItemFlags base) const
{
  if (!universe_ && !discovery_)
    {
      if (column)
        return Qt::NoItemFlags;
      return base & ~Qt::ItemIsSelectable;
    }

  switch (static_cast<MultiverseModel::Column>(column))
    {
    case MultiverseModel::Universe:
    case MultiverseModel::Priority:
    case MultiverseModel::Channels:
    case MultiverseModel::Description:
      return base;
    default:
      return Qt::NoItemFlags;
    }
}


/**
 * @brief MultiverseItem::parentItem
 * @return
 */
MultiverseItem * MultiverseItem::parentItem()
{
  return parentItem_;
}

