/*
    PIP - Platform Independent Primitives
    Introspection module - Base server structs
    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 "piintrospection_server_p.h"

#include "pichunkstream.h"
#include "piinit.h"
#include "piobject.h"
#include "pisysteminfo.h"


const uint PIIntrospection::sign = 0x0F1C2B3A;


PIIntrospection::RequiredInfo::RequiredInfo() {
	types = itInfo;
}


PIIntrospection::ProcessInfo::ProcessInfo() {
	processorsCount = 0;
}


PIIntrospection::ObjectInfo::ObjectInfo() {
	queued_events = 0;
}


PIIntrospection::ProcessInfo PIIntrospection::getInfo() {
	PIIntrospection::ProcessInfo ret;
	PISystemInfo * si   = PISystemInfo::instance();
	ret.architecture    = si->architecture;
	ret.execCommand     = si->execCommand;
	ret.execDateTime    = si->execDateTime;
	ret.hostname        = si->hostname;
	ret.OS_name         = si->OS_name;
	ret.OS_version      = si->OS_version;
	ret.processorsCount = si->processorsCount;
	ret.user            = si->user;
	ret.build_options   = PIInit::buildOptions();
	return ret;
}


PIVector<PIIntrospection::ObjectInfo> PIIntrospection::getObjects() {
	PIVector<PIIntrospection::ObjectInfo> ret;
	PIObject::mutexObjects().lock();
	const PIVector<PIObject *> & ao(PIObject::objects());
	ret.resize(ao.size());
	for (int i = 0; i < ao.size_s(); ++i) {
		ret[i].classname = PIStringAscii(ao[i]->className());
		ret[i].name      = ao[i]->name();
		// ret[i].properties = ao[i]->properties();
		ret[i].parents   = ao[i]->scopeList();
		ao[i]->mutex_queue.lock();
		ret[i].queued_events = ao[i]->events_queue.size_s();
		ao[i]->mutex_queue.unlock();
	}
	PIObject::mutexObjects().unlock();
	return ret;
}


PIByteArray PIIntrospection::packInfo() {
	PIByteArray ret;
	ret << getInfo();
	return ret;
}


void PIIntrospection::unpackInfo(PIByteArray & ba, PIIntrospection::ProcessInfo & info) {
	ba >> info;
}


PIByteArray PIIntrospection::packProcStat(PISystemMonitor * sm) {
	ProcessStat ps;
	if (sm) {
		ps.proc    = sm->statistic();
		ps.threads = sm->threadsStatistic();
	}
	PIByteArray ret;
	ret << ps.proc << ps.threads;
	return ret;
}


void PIIntrospection::unpackProcStat(PIByteArray & ba, PIIntrospection::ProcessStat & info) {
	ba >> info.proc >> info.threads;
}


PIByteArray PIIntrospection::packContainers() {
	PIByteArray ret;
	PIVector<PIIntrospectionContainers::TypeInfo> data;
	PIIntrospectionContainers * p = 0;
#ifdef PIP_INTROSPECTION
	p = PIINTROSPECTION_CONTAINERS->p;
#endif
	if (p) {
		data = p->getInfo();
	}
	ret << data;
	return ret;
}


void PIIntrospection::unpackContainers(PIByteArray & ba, PIVector<PIIntrospectionContainers::TypeInfo> & data) {
	data.clear();
	ba >> data;
}


PIByteArray PIIntrospection::packThreads() {
	PIByteArray ret;
	PIIntrospectionThreads * p = 0;
#ifdef PIP_INTROSPECTION
	p = PIINTROSPECTION_THREADS->p;
#endif
	if (p) {
		p->mutex.lock();
		PIMap<PIThread *, PIIntrospectionThreads::ThreadInfo> & tm(p->threads);
		auto it = tm.makeIterator();
		while (it.next()) {
			if (it.key()->isPIObject()) {
				it.value().classname = PIStringAscii(it.key()->className());
				it.value().name      = it.key()->name();
			}
		}
		ret << tm.values();
		p->mutex.unlock();
	} else {
		ret << PIVector<PIIntrospectionThreads::ThreadInfo>();
	}
	return ret;
}


void PIIntrospection::unpackThreads(PIByteArray & ba, PIVector<PIIntrospectionThreads::ThreadInfo> & threads) {
	threads.clear();
	ba >> threads;
}


PIByteArray PIIntrospection::packObjects() {
	PIByteArray ret;
	ret << getObjects();
	return ret;
}


void PIIntrospection::unpackObjects(PIByteArray & ba, PIVector<PIIntrospection::ObjectInfo> & objects) {
	objects.clear();
	ba >> objects;
}
