#include "rxgrouplist.hh"
#include "contact.hh"
#include "config.hh"


/* ********************************************************************************************* *
 * Implementation of RXGroupList
 * ********************************************************************************************* */
RXGroupList::RXGroupList(QObject *parent)
  : ConfigObject(parent), _contacts()
{
  connect(&_contacts, SIGNAL(elementModified(int)), this, SLOT(onModified()));
  connect(&_contacts, SIGNAL(elementRemoved(int)), this, SLOT(onModified()));
  connect(&_contacts, SIGNAL(elementAdded(int)), this, SLOT(onModified()));
}

RXGroupList::RXGroupList(const QString &name, QObject *parent)
  : ConfigObject(name, parent), _contacts()
{
  connect(&_contacts, SIGNAL(elementModified(int)), this, SLOT(onModified()));
  connect(&_contacts, SIGNAL(elementRemoved(int)), this, SLOT(onModified()));
  connect(&_contacts, SIGNAL(elementAdded(int)), this, SLOT(onModified()));
}

RXGroupList &
RXGroupList::operator =(const RXGroupList &other) {
  copy(other);
  return *this;
}

ConfigItem *
RXGroupList::clone() const {
  RXGroupList *lst = new RXGroupList();
  if (! lst->copy(*this)) {
    lst->deleteLater();
    return nullptr;
  }
  return lst;
}

int
RXGroupList::count() const {
  return _contacts.count();
}

void
RXGroupList::clear() {
  _contacts.clear();
  emit modified(this);
}

DMRContact *
RXGroupList::contact(int idx) const {
  if (idx >= _contacts.count())
    return nullptr;
  return _contacts.get(idx)->as<DMRContact>();
}

int
RXGroupList::addContact(DMRContact *contact, int idx) {
  return _contacts.add(contact, idx);
}

bool
RXGroupList::remContact(int idx) {
  return _contacts.del(_contacts.get(idx));
}

const DMRContactRefList *
RXGroupList::contacts() const {
  return &_contacts;
}

DMRContactRefList *
RXGroupList::contacts() {
  return &_contacts;
}

YAML::Node
RXGroupList::serialize(const Context &context, const ErrorStack &err) {
  YAML::Node node = ConfigObject::serialize(context, err);
  node.SetStyle(YAML::EmitterStyle::Flow);
  return node;
}

void
RXGroupList::onModified() {
  emit modified(this);
}


/* ********************************************************************************************* *
 * Implementation of RXGroupLists
 * ********************************************************************************************* */
RXGroupLists::RXGroupLists(QObject *parent)
  : ConfigObjectList(RXGroupList::staticMetaObject, parent)
{
  // pass...
}


RXGroupList *
RXGroupLists::list(int idx) const {
  if (ConfigItem *obj = get(idx))
    return obj->as<RXGroupList>();
  return nullptr;
}

int
RXGroupLists::add(ConfigObject *obj, int row, bool unique) {
  if (obj && obj->is<RXGroupList>())
    return ConfigObjectList::add(obj, row, unique);
  return -1;
}

ConfigItem *
RXGroupLists::allocateChild(const YAML::Node &node, ConfigItem::Context &ctx, const ErrorStack &err) {
  Q_UNUSED(ctx)

  if (! node)
    return nullptr;

  if (! node.IsMap()) {
    errMsg(err) << node.Mark().line << ":" << node.Mark().column
                << ": Cannot create group list: Expected object.";
    return nullptr;
  }

  return new RXGroupList();
}

