var fs = require('fs');

var reservationJSON = {
	"items": []
};

var REGEX_CREATE	= /^new$/;
var REGEX_UPDATE	= /^[0-9]+$/;
var REGEX_DELETE	= /^[0-9]+-del$/;
var REGEX_SHOW		= /^[0-9]+-edit$/;
var REGEX_READ		= /^[0-9]+-read$/;

var REGEX_INT		= /^(\-|\+)?([0-9]+)$/;
var REGEX_EMAIL		= /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
var REGEX_TIME		= /^(([01][0-9]|2[0-4]):[0-5][0-9])$/;
var REGEX_DATE		= /^([0-9]{4})-(0[0-9]|1[012])-([0-2][0-9]|3[01])$/;

var LANG = {};
LANG["ACTIONS"] = {
	1: "Das Reservieren",
	2: "Das Aktualisieren der Informationen",
	3: "Das Löschen der Reservierung",
	4: "Das Anzeigen der Inforationen",
	5: "Das Setzen des Gelesen-Status"
};
LANG["ERROR_MESSAGES"] = {
	1: 	"Das Feld \"Name\" darf nicht leer sein.",
	2: 	"Das Feld \"Kommentar\" darf nicht leer sein.",
	4: 	"Das Feld \"Anzahl der Personen\" darf nicht leer und muss eine ganze, positive Zahl sein.",
	8: 	"Das Feld \"Datum\" darf nicht leer sein und muss einem gültigen Datum im Format JJJJ-MM-TT entsprechen.",
	16: "Das Feld \"Uhrzeit\" darf nicht leer sein und muss einer gültigen Uhrzeit im Format HH:MM entsprechen.",
	32: "Das Feld \"E-Mail\" darf nicht leer und muss eine gültige E-Mail-Adresse sein.",
	64: "Beim Verarbeiten der Anfrage ist ein interner Fehler aufgetreten."
};
LANG["MESSAGES"] = {
	"success": "%action% war erfolgreich.",
	"failure": "%action% konnte nicht durchgeführt werden."
};
LANG["INTERNAL"] = {
	"noinput": "No input file for reservation JSON specified!"
};

var FILENAME		= false;

module.exports.init = function(reservationfile) {
	FILENAME = reservationfile;
	module.exports.loadFile();
}

module.exports.loadFile = function() {
	if (!FILENAME) throw LANG["MESSAGES"]["noinput"];
    fs.readFile(FILENAME, 'utf8', function(err, data) {
		if (err) throw err;
		reservationJSON = JSON.parse(data);
	});
}

module.exports.saveJSON = function() {
	if (!FILENAME) throw LANG["MESSAGES"]["noinput"];
	fs.writeFile(FILENAME, JSON.stringify(reservationJSON, null, 4), function(err) {
		if(err) {
			console.log(err);
			return false;
		}
	});
	return true;
}

module.exports.MenuAction = {
    ERROR:  0,
    CREATE: 1,
    UPDATE: 2,
    DELETE: 3,
    SHOW:   4,
    READ:   5
}

module.exports.ErrorCode = {
    SUCCESS: 		0,
    NOSTRING_NAME: 	1,
    NOSTRING_DESC: 	2,
    NONUMBER_PERS: 	4,
	NODATE_DATE: 	8,
	NOTIME_TIME: 	16,
	NOEMAIL_MAIL: 	32,
	WRONG_ACTION: 	64
}
module.exports.ErrorCode["MAX"] = sum(module.exports.ErrorCode);

module.exports.getStatusMessage = function(errorCode, action) {
	if (action) {
		if (!errorCode) {
			return {
				type: "success",
				message: LANG["MESSAGES"]["success"].replace("%action%", LANG["ACTIONS"][action]),
				reasons: null
			}
		} else {
			var reasons = [];
			for (var i = 1; i < module.exports.ErrorCode["MAX"]; i=i*2) {
				if (errorCode & i) { // bit-wise comparing
					reasons.push(LANG["ERROR_MESSAGES"][i]);
				}
			}
			return {
				type: "danger",
				message: LANG["MESSAGES"]["failure"].replace("%action%", LANG["ACTIONS"][action]),
				reasons: reasons
			}
		}
	} else {
		return null;
	}
}

module.exports.determineAction = function(nametag) {
	if (nametag && REGEX_CREATE.test(nametag)) { 		// new
		return module.exports.MenuAction.CREATE;
	} else if (nametag && REGEX_UPDATE.test(nametag)) { // update
		return module.exports.MenuAction.UPDATE;
	} else if (nametag && REGEX_DELETE.test(nametag)) { // delete
		return module.exports.MenuAction.DELETE;
	} else if (nametag && REGEX_SHOW.test(nametag)) { 	// show
		return module.exports.MenuAction.SHOW;
	} else if (nametag && REGEX_READ.test(nametag)) { 	// read
		return module.exports.MenuAction.READ;
	}
	return module.exports.MenuAction.ERROR;
}

module.exports.checkValidity = function(name, desc, person, email, date, time) {
	var errorCode = 0;
	
	if (!name || !(typeof name === 'string' || name instanceof String))
		errorCode += module.exports.ErrorCode.NOSTRING_NAME;
	if (!desc || !(typeof desc === 'string' || desc instanceof String))
		errorCode += module.exports.ErrorCode.NOSTRING_DESC;
	if (isNaN(filterInt(person)))
		errorCode += module.exports.ErrorCode.NONUMBER_PERS;
	if (!REGEX_EMAIL.test(email))
		errorCode += module.exports.ErrorCode.NOEMAIL_MAIL;
	if (!REGEX_DATE.test(date))
		errorCode += module.exports.ErrorCode.NODATE_DATE;
	if (!REGEX_TIME.test(time))
		errorCode += module.exports.ErrorCode.NOTIME_TIME;
	
	return errorCode;
}

module.exports.addValue = function(name, desc, person, email, date, time, nametag) {
	var errorCode = module.exports.checkValidity(name, desc, person, email, date, time);
	var action = module.exports.determineAction(nametag);
	if (action !== module.exports.MenuAction.CREATE) {
		errorCode += module.exports.ErrorCode.WRONG_ACTION;
	}
	if (!errorCode) {
		person = filterInt(person);
		reservationJSON["items"].unshift({
			name: name,
			desc: desc,
			email: email,
			person: person,
			time: time,
			date: date,
			read: false
		});
		module.exports.saveJSON();
	}
	return errorCode;
}

module.exports.updateValue = function(name, desc, person, email, date, time, nametag) {
	var errorCode = module.exports.checkValidity(name, desc, person, email, date, time);
	var action = module.exports.determineAction(nametag);
	if (action !== module.exports.MenuAction.UPDATE) {
		errorCode += module.exports.ErrorCode.WRONG_ACTION;
	}
	if (!errorCode) {
		person = filterInt(person);
		var position = splitNameTag(nametag, action);
		reservationJSON["items"][position.id] = {
			name: name,
			desc: desc,
			email: email,
			person: person,
			time: time,
			date: date,
			read: true
		};
		module.exports.saveJSON();
	}
	return errorCode;
}

module.exports.deleteValue = function(nametag) {
	var errorCode = module.exports.ErrorCode.SUCCESS;
	var action = module.exports.determineAction(nametag);
	if (action !== module.exports.MenuAction.DELETE) {
		errorCode += module.exports.ErrorCode.WRONG_ACTION;
	}
	if (!errorCode) {
		var position = splitNameTag(nametag, action);
		reservationJSON["items"].splice(position.id, 1);
		module.exports.saveJSON();
	}
	return errorCode;
}

module.exports.showValue = function(nametag) {
	var errorCode = module.exports.ErrorCode.SUCCESS;
	var action = module.exports.determineAction(nametag);
	if (action !== module.exports.MenuAction.SHOW) {
		errorCode += module.exports.ErrorCode.WRONG_ACTION;
	}
	if (!errorCode) {
		var position = splitNameTag(nametag, action);
		result = reservationJSON["items"][position.id];
		result.id = position.id;
		return result;
	}
	return errorCode;
}

module.exports.readValue = function(nametag) {
	var errorCode = module.exports.ErrorCode.SUCCESS;
	var action = module.exports.determineAction(nametag);
	if (action !== module.exports.MenuAction.READ) {
		errorCode += module.exports.ErrorCode.WRONG_ACTION;
	}
	if (!errorCode) {
		var position = splitNameTag(nametag, action);
		reservationJSON["items"][position.id]["read"] = !reservationJSON["items"][position.id]["read"];
		module.exports.saveJSON();
	}
	return errorCode;
}

module.exports.getJSON = function() {
	return reservationJSON;
}

var filterInt = function(value) {
	if(REGEX_INT.test(value))
		return Number(value);
	return NaN;
}

function sum(obj) {
  var sum = 0;
  for(var el in obj) {
    if(obj.hasOwnProperty(el)) {
      sum += parseFloat(obj[el]);
    }
  }
  return sum;
}

var splitNameTag = function(nametag, action) {
	if (action) {											// create, update, show, read & delete
		var splitArr = nametag.split("-");
		var result = {};
		result.type = action;
		if (action == module.exports.MenuAction.CREATE) {	// create
			result.id = null;
		} else {											// update, show, read & delete
			result.id = parseInt(splitArr[0]);
		}
		return result;
	} else {
		return false;
	}
}