#include "execbot.h"
#include <QDebug>
#include <QFile>
#include <QDir>
#include <QFileInfo>
#include <QTextCodec>

ExecBot::ExecBot(QObject *parent) : TelegramBotBase(parent) {
	connect(getAPI(), SIGNAL(newFile(TelegramBotAPI::File)), this, SLOT(saveFile(TelegramBotAPI::File)));
}


QString ExecBot::loginMessage(uint id) {
	if (sessions.contains(id)) {
		if (sessions[id] == Password) return tr("Enter password");
		if (sessions[id] == NotLogged) return tr("Please send me /start");
	}
	return tr("Error");
}


QString ExecBot::help() {
	return tr("Input command for exec on server, after exec finished result will be sended to you");
}


bool ExecBot::loginUser(uint id, const QString &msg) {
	if (sessions.contains(id)) {
		switch (sessions[id]) {
			case NotLogged:
				if (msg == "/start") sessions[id] = Password;
			break;
			case Password:
				if (msg == "rootpasswd") {
					sessions[id] = Ready;
					return true;
				}
			break;
			case Ready:
			case CommandExec:
				return true;
			default:
			break;
			return false;
		}
	} else {
		if (msg == "/start") sessions[id] = Password;
		else sessions[id] = NotLogged;
	}
	return false;
}


void ExecBot::messageFromUser(uint id, const QString &msg) {
	if (sessions.contains(id)) {
		if (msg == "/exit") {
			sessions[id] = NotLogged;
			disconnectUser(id);
			getAPI()->sendMessage(id, tr("Logout"));
			return;
		}
		if (sessions[id] == CommandExec) {
			if (msg == "/kill") {
				int rm = -1;
				for (int i=0; i<run_commands.size(); i++) {
					if (run_commands[i].user == id) {
						run_commands[i].cmd->terminate();
						getAPI()->sendMessage(id, tr("Process killed"));
						sessions[id] = Ready;
						rm = i;
					}
				}
				if (rm >= 0) {
					run_commands[rm].cmd->deleteLater();
					run_commands.remove(rm);
				}
			} else
				getAPI()->sendMessage(id, tr("Command is running, please wait for finish"));
			return;
		}
		if (sessions[id] == Ready) {
			if (msg.startsWith("/download")) {
				QFile f;
				f.setFileName(msg.mid(9).trimmed());
				if (f.open(QIODevice::ReadOnly)) {
					QByteArray ba = f.readAll();
					getAPI()->sendMessage(id, TelegramBotAPI::Document, ba, QFileInfo(f).fileName());
				} else
					getAPI()->sendMessage(id, tr("File not found"));
				return;
			}
			getAPI()->sendMessage(id, "exec: " + msg);
			UserCommand uc;
			uc.user = id;
			uc.cmd = new QProcess();
//			uc.cmd->setProcessChannelMode(QProcess::MergedChannels);
			connect(uc.cmd, SIGNAL(readyRead()), this, SLOT(cmdRead()));
//			connect(uc.cmd, SIGNAL(started()), this, SLOT(cmdStart()));
			connect(uc.cmd, SIGNAL(finished(int)), this, SLOT(cmdFinish(int)));
			uc.cmd->start(msg);
			if (uc.cmd->waitForStarted(3000)) {
				sessions[id] = CommandExec;
				run_commands.append(uc);
			} else getAPI()->sendMessage(id, tr("Can't run command %1").arg(msg));
		}
	}
}


void ExecBot::cmdRead() {
//	qDebug() << "cmdRead()";
	QProcess * p = (QProcess *)sender();
	for (int i=0; i<run_commands.size(); i++) {
		if (run_commands[i].cmd == p) {
			int id = run_commands[i].user;
#ifdef WIN32
			QTextCodec *codec = QTextCodec::codecForName("IBM 866");
#else
			QTextCodec *codec = QTextCodec::codecForName("UTF-8");
#endif
			QString s = codec->toUnicode(p->readAll());
			getAPI()->sendMessage(id, s);
		}
	}
}

void ExecBot::cmdFinish(int code) {
//	qDebug() << "cmdFinish()" << code;
	QProcess * p = (QProcess *)sender();
	int rm = -1;
	for (int i=0; i<run_commands.size(); i++) {
		if (run_commands[i].cmd == p) {
			int id = run_commands[i].user;
#ifdef WIN32
			QTextCodec *codec = QTextCodec::codecForName("IBM 866");
#else
			QTextCodec *codec = QTextCodec::codecForName("UTF-8");
#endif
			QString s = codec->toUnicode(p->readAll());
			getAPI()->sendMessage(id, s);
			rm = i;
			sessions[id] = Ready;
		}
	}
	if (rm >= 0) {
		run_commands[rm].cmd->deleteLater();
		getAPI()->sendMessage(run_commands[rm].user, tr("Command finished with code %1").arg(code));
		run_commands.remove(rm);
	}
}


void ExecBot::saveFile(TelegramBotAPI::File fl) {
	if (sessions.contains(fl.chat_id)) {
		if (sessions[fl.chat_id] == Ready) {
			QFile f;
			QDir::current().mkdir("uploads");
			f.setFileName("uploads/" + fl.filename);
			if (f.open(QIODevice::ReadWrite)) {
				f.resize(0);
				f.write(fl.data);
				getAPI()->sendMessage(fl.chat_id, tr("File received"));
			} else {
				getAPI()->sendMessage(fl.chat_id, tr("Can't write file"));
			}
		} else {
			 getAPI()->sendMessage(fl.chat_id, loginMessage(fl.chat_id));
		}
	} else {
		getAPI()->sendMessage(fl.chat_id, tr("Please send me /start"));
	}
}


