/*
    PIP - Platform Independent Primitives
    Peer - named I/O ethernet node, forming self-organized peering network
    Ivan Pelipenko peri4ko@yandex.ru

    This program 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 3 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 Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "picollection.h"


//! \~\class PICollection picollection.h
//! \~\details
//! \~english \section PICollection_sec0 Synopsis
//! \~russian \section PICollection_sec0 Краткий обзор
//! \~english
//! This class has only static functions so no need to create instance of the
//! %PICollection. This class provide macros to add some classes or existing
//! objects to global collection and access to them from any place of the code.
//!
//! \~russian
//! Этот класс предоставляет статические методы, поэтому не нужно создавать
//! его экземпляр. Имеется несколько макросов для добавления классов или существующих
//! объектов в глобальные группы. Затем можно получить их список в любом месте программы.
//! \~\snippet picollection.cpp main
//!


PIStringList PICollection::groups() {
	PIStringList sl;
	PIVector<PICollection::Group> & cg(_groups());
	for (const auto & g: cg)
		sl << g.name;
	return sl;
}


PIVector<const PIObject *> PICollection::groupElements(const PIString & group) {
	PIVector<PICollection::Group> & cg(_groups());
	for (const auto & g: cg)
		if (g.name == group) return g.elements;
	return PIVector<const PIObject *>();
}


bool PICollection::addToGroup(const PIString & group, const PIObject * element) {
	// piCout << "add to" << group << element;
	PIString n = PIStringAscii(element->className());
	PIVector<PICollection::Group> & cg(_groups());
	for (auto & g: cg)
		if (g.name == group) {
			for (int i = 0; i < g.elements.size_s(); ++i)
				if (PIString(g.elements[i]->className()) == n) return false;
			g.elements << element;
			// piCout << "new group" << group << ", ok";
			return true;
		}
	_groups() << Group(group);
	_groups().back().elements << element;
	// piCout << "new group" << group << ", ok";
	return true;
}


PIVector<PICollection::Group> & PICollection::_groups() {
	static PIVector<PICollection::Group> ret;
	return ret;
}


PICollection::CollectionAdder::CollectionAdder(const PIString & group, const PIObject * element, const PIString & name, bool own) {
	if (!element) return;
	if (name.isNotEmpty()) const_cast<PIObject *>(element)->setName(name);
	bool added = PICollection::addToGroup(group, element);
	if (!added && own) delete element;
}
