/*
    PIP - Platform Independent Primitives
    Resources subsystem
    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 "piresourcesstorage.h"

#include "piset.h"


PIResourcesStorage::Section::Section() {}


PIResourcesStorage::Section::~Section() {}


void PIResourcesStorage::Section::add(const PIResourcesStorage::Section & s) {
	auto i = s.entries.makeIterator();
	while (i.next()) {
		if (!i.value()) continue;
		if (entries.value(i.key(), 0)) continue;
		entries[i.key()] = i.value();
	}
}


void PIResourcesStorage::Section::purge() {
	PIVector<PIByteArray *> bav = entries.values();
	PISet<PIByteArray *> bas;
	for (auto i: bav) {
		if (i) bas << i;
	}
	bav = bas.toVector();
	for (auto i: bav)
		delete i;
	entries.clear();
}


PIResourcesStorage::PIResourcesStorage() {}


PIResourcesStorage::~PIResourcesStorage() {
	clear();
}


void PIResourcesStorage::registerSection(const PIString & section_name, const PIResourcesStorage::Section & data) {
	Section * s = sections.value(section_name, 0);
	if (!s) {
		s                      = new Section();
		sections[section_name] = s;
	}
	s->add(data);
}


void PIResourcesStorage::registerSection(const uchar * rc_data, const uchar * rc_desc, int rc_desc_size) {
	// piCout << "registerSection" << this;
	PIByteArray dba(rc_desc, rc_desc_size);
	PIVector<PIResourcesStorage::__RCEntry> el;
	dba >> el;
	PIMap<PIString, PIVector<PIResourcesStorage::__RCEntry>> ebs;
	for (const auto & e: el) {
		ebs[e.section] << e;
	}
	auto it = ebs.makeIterator();
	while (it.next()) {
		PIResourcesStorage::Section s;
		const PIVector<PIResourcesStorage::__RCEntry> & itv(it.value());
		for (const auto & e: itv) {
			// piCout << "add" << e.name << e.alias << PIString::readableSize(e.size);
			PIByteArray * eba = new PIByteArray(&(rc_data[e.offset]), e.size);
			s.entries[e.name] = eba;
			if (!e.alias.isEmpty() && e.alias != e.name) s.entries[e.alias] = eba;
		}
		registerSection(it.key(), s);
	}
}


PIResourcesStorage::Section * PIResourcesStorage::section(const PIString & section_name) const {
	return sections.value(section_name, 0);
}


PIByteArray PIResourcesStorage::get(const PIString & section_name, const PIString & entry_name) const {
	Section * s = sections.value(section_name, 0);
	if (!s) return PIByteArray();
	PIByteArray * ba = s->entries.value(entry_name, 0);
	if (!ba) return PIByteArray();
	return *ba;
}


PIByteArray PIResourcesStorage::get(const PIString & entry_name) const {
	auto i = sections.makeIterator();
	while (i.next()) {
		if (!i.value()) continue;
		PIByteArray * ba = i.value()->entries.value(entry_name, 0);
		if (!ba) continue;
		return *ba;
	}
	return PIByteArray();
}


void PIResourcesStorage::clear() {
	// piCout << "PIResourcesStorage clear";
	PIVector<Section *> sv = sections.values();
	for (auto i: sv) {
		if (i) i->purge();
	}
	sections.clear();
}


PIResourcesStorage * PIResourcesStorage::instance() {
	static PIResourcesStorage * ret = new PIResourcesStorage();
	return ret;
}
