#include "shared.h"

#include "picrypt.h"

extern PIScreen * screen;


class DlgWatcher: public PIThread {
	PIOBJECT(DlgWatcher)

public:
	DlgWatcher() { close = ok = false; }
	EVENT_HANDLER2(void, tileEvent, PIScreenTile *, tile, PIScreenTypes::TileEvent, e) {
		if (e.type == TileButtons::ButtonSelected) {
			ok    = e.data.toInt() == 0;
			close = true;
		}
	}
	EVENT_HANDLER1(void, keyPressed, PIKbdListener::KeyEvent, key) {
		if (key.key == PIKbdListener::Return) {
			ok    = true;
			close = true;
		}
		if (key.key == PIKbdListener::Esc) {
			ok    = false;
			close = true;
		}
	}
	bool ok;
	bool close;
};


PIString readableTime(const PITime & t) {
	PIString ret;
	bool pt = false;
	if (t.hours > 0) {
		ret += PIString::fromNumber(t.hours).expandLeftTo(2, '0') + " h ";
		pt = true;
	}
	if ((t.minutes > 0) || pt) {
		ret += PIString::fromNumber(t.minutes).expandLeftTo(2, '0') + " m ";
		pt = true;
	}
	if ((t.seconds > 0) || pt) ret += PIString::fromNumber(t.seconds).expandLeftTo(2, '0') + " s";
	return ret;
}


PIString askUserInput(const PIString & desc) {
	PIScreenTile dlg;
	dlg.setMargins(1, 1, 1, 1);
	dlg.spacing                  = 1;
	dlg.back_format.color_back   = Yellow;
	TileSimple * lbl             = new TileSimple();
	TileInput * input            = new TileInput();
	TileButtons * btns           = new TileButtons();
	lbl->back_format.color_back  = Yellow;
	btns->back_format.color_back = Yellow;
	lbl->content << TileSimple::Row(desc, CellFormat(Black, Transparent));
	btns->content << TileButtons::Button("  Ok  ", CellFormat());
	btns->content << TileButtons::Button("Cancel", CellFormat());
	dlg.addTile(lbl);
	dlg.addTile(input);
	dlg.addTile(btns);
	DlgWatcher w;
	CONNECTU(screen, keyPressed, &w, keyPressed)
	CONNECTU(screen, tileEvent, &w, tileEvent)
	screen->setDialogTile(&dlg);
	while (!w.close) {
		PIKbdListener::instance()->readKeyboard();
		piMSleep(10);
	}
	if (!w.ok) return PIString();
	return input->text;
}


bool askQuestion(const PIString & t) {
	PIScreenTile dlg;
	dlg.setMargins(1, 1, 1, 1);
	dlg.spacing                  = 1;
	dlg.back_format.color_back   = Yellow;
	TileSimple * lbl             = new TileSimple();
	TileButtons * btns           = new TileButtons();
	lbl->back_format.color_back  = Yellow;
	btns->back_format.color_back = Yellow;
	lbl->content << TileSimple::Row(t, CellFormat(Black, Transparent));
	btns->content << TileButtons::Button("  Ok  ", CellFormat());
	btns->content << TileButtons::Button("Cancel", CellFormat());
	dlg.addTile(lbl);
	dlg.addTile(btns);
	DlgWatcher w;
	CONNECTU(screen, keyPressed, &w, keyPressed)
	CONNECTU(screen, tileEvent, &w, tileEvent)
	screen->setDialogTile(&dlg);
	while (!w.close) {
		PIKbdListener::instance()->readKeyboard();
		piMSleep(10);
	}
	return w.ok;
}


void showInfo(const PIString & t) {
	PIScreenTile dlg;
	dlg.setMargins(1, 1, 1, 1);
	dlg.spacing                  = 1;
	dlg.back_format.color_back   = Yellow;
	TileSimple * lbl             = new TileSimple();
	TileButtons * btns           = new TileButtons();
	lbl->back_format.color_back  = Yellow;
	btns->back_format.color_back = Yellow;
	lbl->content << TileSimple::Row(t, CellFormat(Black, Transparent));
	btns->content << TileButtons::Button("  Ok  ", CellFormat());
	dlg.addTile(lbl);
	dlg.addTile(btns);
	DlgWatcher w;
	CONNECTU(screen, keyPressed, &w, keyPressed)
	CONNECTU(screen, tileEvent, &w, tileEvent)
	screen->setDialogTile(&dlg);
	while (!w.close) {
		PIKbdListener::instance()->readKeyboard();
		piMSleep(10);
	}
}


void removeFiles(const PIDir & dir, PIStringList l) {
	l.removeAll("..");
	PIString ap = dir.absolutePath();
	// piCout << "remove from" << ap;
	for (const auto & s: l) {
		PIFile::FileInfo fi = PIFile::fileInfo(ap + PIDir::separator + s);
		if (fi.isDir()) {
			PIVector<PIFile::FileInfo> el = PIDir::allEntries(fi.path);
			piForeachCR(PIFile::FileInfo & e, el) {
				// piCout << "remove" << e.path;
				PIFile::remove(e.path);
			}
		}
		// piCout << "remove" << fi.path;
		PIFile::remove(fi.path);
	}
}


bool cryptFiles(const PIDir & dir, PIStringList l, const PIByteArray & secret) {
	if (secret.size() != PICrypt::sizeKey() || secret.isEmpty()) return false;
	l.removeAll("..");
	PIString ap = dir.absolutePath();
	for (const auto & s: l) {
		PIFile::FileInfo fi = PIFile::fileInfo(ap + PIDir::separator + s);
		if (fi.isDir()) {
			PIVector<PIFile::FileInfo> el = PIDir::allEntries(fi.path);
			piForeachCR(PIFile::FileInfo & e, el) {
				if (e.size != 0) cryptFile(e.path, secret);
			}
		}
		if (fi.size != 0) cryptFile(fi.path, secret);
	}
	return false;
}


bool cryptFile(const PIString & path, const PIByteArray & secret) {
	PIFile inf;
	PIByteArray ba;
	PICrypt crypt;
	if (!crypt.setKey(secret)) return false;
	if (!inf.open(path, PIIODevice::ReadOnly)) return false;
	ba = inf.readAll();
	ba = crypt.crypt(ba);
	if (ba.isEmpty()) return false;
	PIFile outf;
	if (!outf.open(path + ".crypt", PIIODevice::ReadWrite)) return false;
	outf.resize(0);
	outf.write(ba);
	outf.close();
	return true;
}
