/*
    PIP - Platform Independent Primitives
	Translation private
    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 "pitranslator_p.h"

#include "pichunkstream.h"
#include "piiodevice.h"

constexpr int currentVersion = 1;
const PIByteArray fileHeader("PIPBTF", 6);


void PITranslatorPrivate::Context::add(const PIMap<uint, PIString> & sm) {
	auto it = sm.makeIterator();
	while (it.next())
		strings[it.key()] = it.value();
}


void PITranslatorPrivate::Translation::clear() {
	piDeleteAll(contexts.values());
	contexts.clear();
	lang.clear();
}


PITranslatorPrivate::Context * PITranslatorPrivate::Translation::createContext(const PIString & context) {
	return createContext(context.hash());
}


PITranslatorPrivate::Context * PITranslatorPrivate::Translation::createContext(uint hash) {
	auto & ret(contexts[hash]);
	if (!ret) ret = new Context();
	return ret;
}


PIString PITranslatorPrivate::Translation::translate(const PIString & in, const PIString & context) {
	auto c = contexts.value(context.hash());
	if (!c) return in;
	return c->strings.value(in.hash(), in);
}


bool PITranslatorPrivate::Translation::load(const PIByteArray & data) {
	if (data.size_s() <= 4) return false;
	PIChunkStream cs(data);
	Context * ctx = nullptr;
	PIMap<uint, PIString> strings;
	while (!cs.atEnd()) {
		switch (cs.read()) {
		case 1: {
			int version = cs.getData<int>();
			if (version != currentVersion) {
				piCout << "Invalid translation version!";
				return false;
			}
		} break;
		case 3: {
			uint ctx_hash = cs.getData<uint>();
			ctx           = createContext(ctx_hash);
		} break;
		case 4: {
			cs.get(strings);
			if (ctx) ctx->add(strings);
		} break;
		}
	}
	return true;
}


int PITranslatorPrivate::Translation::count() const {
	int ret  = 0;
	auto cit = contexts.makeIterator();
	while (cit.next())
		ret += cit.value()->strings.size_s();
	return ret;
}


PIByteArray PITranslatorPrivate::Translation::save() {
	PIChunkStream cs;
	cs.add(1, currentVersion).add(2, lang);
	auto cit = contexts.makeIterator();
	while (cit.next()) {
		cs.add(3, cit.key()).add(4, cit.value()->strings);
	}
	return cs.data();
}


int PITranslatorPrivate::headerSize() {
	return fileHeader.size_s();
}


bool PITranslatorPrivate::checkHeader(PIIODevice * d) {
	if (!d) return false;
	return d->read(fileHeader.size_s()) == fileHeader;
}


void PITranslatorPrivate::writeHeader(PIIODevice * d) {
	if (!d) return;
	d->write(fileHeader);
}
