/*******************************************************************************/
//  Simple message queue manager for user requests - pda4Pi Project
//  Copyright (C) 2013  Cleverson dos Santos Assis

//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU 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 General Public License for more details.

//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
/*******************************************************************************/

//Classe que faz um gerenciamento primitivo e simples de uma fila
//de requisições usando as pastas in e out
function MessageQueue() {
    
	//Handle do gerenciador de arquivos do node.js
	this.fs = require('fs');
    
	//Caminho de entrada dos arquivos
	this.infolder = "./in";
	
	//Caminho de entrada dos arquivos
	this.outfolder = "./out";
	
}

MessageQueue.prototype.setInFolder = function(infolder){
	this.infolder = infolder;
}

MessageQueue.prototype.setOutFolder = function(outfolder){
	this.outfolder = outfolder;
}

//Valida o conteúdo de uma arquivo de mensagem que esteja na fila.
//A mensagem pode contem N ou mais atributos, mas o formato básico
//de entrada deve ser respeitado:
// {
//		text: "nonono"		//Texto com o comando a ser interpretado posteriormente
// }
// Ou um json de erro, com errorCode, description e filename
// retorna o proprio Json convertido
MessageQueue.prototype.validateJSONFile = function(jsonFile){
    
	//Primeiro, resgata o conteúdo do arquivo de maneira sincrona
	//e logo em seguida um eval é acionado
	var content="("+this.fs.readFileSync(this.infolder+"/"+jsonFile)+")";
	var json;
	var castError = false;
	try{
		json = eval(content);
		
		if (json==undefined || json == null){
			castError = true;
		}
		
	}catch(e){
		castError = true;
	}
	
	if (castError) {
		return ({
			errorCode: "--NaVJson--",
			description: "Invalid json format! The message must be in JSON format!",
			filename: jsonFile
		});	
	}
	
	//Teste dos atributos obrigatórios
	if (json.text == undefined || json.text == null){
		return ({
			errorCode: "--NaVJson--",
			description: "No 'text' property. This property contains the request user message! Please verify again!",
			filename: jsonFile
		});
	}
	if (typeof json.text != "string"){
		return ({
			errorCode: "--NaVJson--",
			description: "The 'text' must be a string sentence",
			filename: jsonFile
		});
	}
	
	return json;
	
}


//Pega o 1o arquivo que vier na fila de entrada da pasta IN,
//retornando o json no seguinte formato básico(quando sucesso):
//	{
//		filename: "",					//Nome do arquivo da mensagem
//		starttime: "18/08/2013 17:53",	//Hora em que a mensagem foi capturada
//		details: [object]				//Objeto da mensagem a ser processado
//	}
// retorna -1 caso nenhum arquivo seja encontrado
MessageQueue.prototype.pickAMessage = function(path){
    
	//Lista os arquivos .json da pasta in
	var files = this.fs.readdirSync(this.infolder);
	for (i=0; i<files.length; i++){
		if (files[i].indexOf(".json") > -1){
			
			//Ao pegar o arquivo, para evitar leitura repetida
			//em caso de erro, e venha a bloquear a fila,
			//então o arquivo é renomeado para extensão .lock
			
			lockFile = files[i].replace(".json",".lock");
			this.fs.renameSync(this.infolder+"/"+files[i], this.infolder+"/"+lockFile);
			
			//Mesmo sendo um .json
			resul = this.validateJSONFile(lockFile);
			if (resul.errorCode != undefined){
				return resul;
			}
			
			
			return ({
				filename: lockFile,
				starttime: new Date(),
				details: resul
			});
		}
	}
	
	//Caso não haja arquivos
	return -1;
} 


//Devolve o arquivo travado para a fila de entrada, para uma próxima leitura
MessageQueue.prototype.unlockMessage = function(message){
    
	//Somente renomeia o arquivo .lock para .json
	//permitindo uma próxima leitura
	var unlockFile = message.filename.replace(".lock",".json");
	this.fs.renameSync(this.infolder+"/"+message.filename, this.infolder+"/"+unlockFile);
	
}


//Joga a mensagem processada com parâmetros adicionais para fila de saida ("Out")
MessageQueue.prototype.throwAwayAMessage = function(message){
    
	//Apaga o arquivo na fila IN para começo de conversa
	this.fs.unlinkSync(this.infolder+"/"+message.filename);
	
	//Segundo cria um arquivo de saída com a mensagem
	//com o conteúdo do objeto json
	//Como uso o stringfy, algo me diz que lá na frente pode ter um
	//bug ou outro...sei não. Mas é o que tem para agora.
	var unlockFile = message.filename.replace(".lock",".json");
	message.filename = unlockFile;
	this.fs.writeFileSync(this.outfolder+'/'+unlockFile, JSON.stringify(message));
	
}

//Exportação do módulo para nodeJS
module.exports = MessageQueue;
