/*
Pure Javascript implementation of Uniforum message translation.
Copyright (C) 2008 Joshua I. Miller <unrtst@cpan.org>, all rights reserved

This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published
by the Free Software Foundation; either version 2, 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
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.
*/

/*****************************************************************************/
/* E010001 02/11/10 PMS - Corrected late loading of locale_data problem      */
/* E010000 02/09/10 PMS - Added code                                         */
/*****************************************************************************/

Gettext = function (args) {
	this.domain = 'messages';
	this.locale_data = undefined;

	// set options
	var options = [ "domain", "locale_data" ];
	if (this.isValidObject(args)) {
		for (var i in args) {
			for (var j=0; j<options.length; j++) {
				if (i == options[j]) {
					// don't set it if it's null or undefined
					if (this.isValidObject(args[i]))
						this[i] = args[i];
				}
			}
		}
	}

	// try to load the lang file from somewhere
	this.try_load_lang();

	return this;
}

Gettext.context_glue = "\004";
Gettext._locale_data = {};

Gettext.prototype.try_load_lang = function() {
	if (typeof(this.locale_data) != 'undefined') {
		var locale_copy = this.locale_data;
		this.locale_data = undefined;
		this.parse_locale_data(locale_copy);

		if (typeof(Gettext._locale_data[this.domain]) == 'undefined') {
			throw new Error("Error: Gettext 'locale_data' does not contain the domain '"+this.domain+"'");
		}
	}
};

Gettext.prototype.textdomain = function (domain) {
    if (domain && domain.length) this.domain = domain;
    return this.domain;
}

Gettext.prototype.parse_locale_data = function(locale_data) {
	if (typeof(Gettext._locale_data) == 'undefined') {
		Gettext._locale_data = { };
	}
	for (var domain in locale_data) {
		if ((! locale_data.hasOwnProperty(domain)) || (! this.isValidObject(locale_data[domain])))
			continue;
		var has_msgids = false;
		for (var msgid in locale_data[domain]) {
			has_msgids = true;
			break;
		}
		if (! has_msgids) continue;

		var data = locale_data[domain];

		if (domain == "") domain = "messages";
		if (! this.isValidObject(Gettext._locale_data[domain]) )
			Gettext._locale_data[domain] = { };
		if (! this.isValidObject(Gettext._locale_data[domain].head) )
			Gettext._locale_data[domain].head = { };
		if (! this.isValidObject(Gettext._locale_data[domain].msgs) )
			Gettext._locale_data[domain].msgs = { };

		for (var key in data) {
			if (key == "") {
				var header = data[key];
				for (var head in header) {
					var h = head.toLowerCase();
					Gettext._locale_data[domain].head[h] = header[head];
				}
			} else {
				Gettext._locale_data[domain].msgs[key] = data[key];
			}
		}
	}

	for (var domain in Gettext._locale_data) {
		if (this.isValidObject(Gettext._locale_data[domain].head['plural-forms']) &&
			typeof(Gettext._locale_data[domain].head.plural_func) == 'undefined') {

			var plural_forms = Gettext._locale_data[domain].head['plural-forms'];
			var pf_re = new RegExp('^(\\s*nplurals\\s*=\\s*[0-9]+\\s*;\\s*plural\\s*=\\s*(?:\\s|[-\\?\\|&=!<>+*/%:;a-zA-Z0-9_\(\)])+)', 'm');
			if (pf_re.test(plural_forms)) {
				var pf = Gettext._locale_data[domain].head['plural-forms'];
				if (! /;\s*$/.test(pf)) pf = pf.concat(';');
				var code = 'var plural; var nplurals; '+pf+' return { "nplural" : nplurals, "plural" : (plural === true ? 1 : plural ? plural : 0) };';
				Gettext._locale_data[domain].head.plural_func = new Function("n", code);
			} else {
				throw new Error("Syntax error in language file. Plural-Forms header is invalid ["+plural_forms+"]");
			}   

		} else if (typeof(Gettext._locale_data[domain].head.plural_func) == 'undefined') {
			Gettext._locale_data[domain].head.plural_func = function (n) {
				var p = (n != 1) ? 1 : 0;
				return { 'nplural' : 2, 'plural' : p };
				};
		} 
	}

	return;
};

Gettext.prototype.gettext = function (msgid) {
	var msgctxt;
	var msgid_plural;
	var n;
	var category;
	return this.dcnpgettext(null, msgctxt, msgid, msgid_plural, n, category);
};

Gettext.prototype.dgettext = function (domain, msgid) {
	var msgctxt;
	var msgid_plural;
	var n;
	var category;
	return this.dcnpgettext(domain, msgctxt, msgid, msgid_plural, n, category);
};

Gettext.prototype.dcgettext = function (domain, msgid, category) {
	var msgctxt;
	var msgid_plural;
	var n;
	return this.dcnpgettext(domain, msgctxt, msgid, msgid_plural, n, category);
};

// ngettext
Gettext.prototype.ngettext = function (msgid, msgid_plural, n) {
	var msgctxt;
	var category;
	return this.dcnpgettext(null, msgctxt, msgid, msgid_plural, n, category);
};

Gettext.prototype.dngettext = function (domain, msgid, msgid_plural, n) {
	var msgctxt;
	var category;
	return this.dcnpgettext(domain, msgctxt, msgid, msgid_plural, n, category);
};

Gettext.prototype.dcngettext = function (domain, msgid, msgid_plural, n, category) {
	var msgctxt;
	return this.dcnpgettext(domain, msgctxt, msgid, msgid_plural, n, category, category);
};

// pgettext
Gettext.prototype.pgettext = function (msgctxt, msgid) {
	var msgid_plural;
	var n;
	var category;
	return this.dcnpgettext(null, msgctxt, msgid, msgid_plural, n, category);
};

Gettext.prototype.dpgettext = function (domain, msgctxt, msgid) {
	var msgid_plural;
	var n;
	var category;
	return this.dcnpgettext(domain, msgctxt, msgid, msgid_plural, n, category);
};

Gettext.prototype.dcpgettext = function (domain, msgctxt, msgid, category) {
	var msgid_plural;
	var n;
	return this.dcnpgettext(domain, msgctxt, msgid, msgid_plural, n, category);
};

// npgettext
Gettext.prototype.npgettext = function (msgctxt, msgid, msgid_plural, n) {
	var category;
	return this.dcnpgettext(null, msgctxt, msgid, msgid_plural, n, category);
};

Gettext.prototype.dnpgettext = function (domain, msgctxt, msgid, msgid_plural, n) {
	var category;
	return this.dcnpgettext(domain, msgctxt, msgid, msgid_plural, n, category);
};

Gettext.prototype.dcnpgettext = function (domain, msgctxt, msgid, msgid_plural, n, category) {
	if (! this.isValidObject(msgid)) return '';

	var plural = this.isValidObject(msgid_plural);
	var msg_ctxt_id = this.isValidObject(msgctxt) ? msgctxt+Gettext.context_glue+msgid : msgid;

	var domainname = this.isValidObject(domain)	  ? domain :
					 this.isValidObject(this.domain) ? this.domain :
													   'messages';

	var category_name = 'LC_MESSAGES';
	var category = 5;

	var locale_data = new Array();
	if (typeof(Gettext._locale_data) != 'undefined' &&
		this.isValidObject(Gettext._locale_data[domainname])) {
		locale_data.push( Gettext._locale_data[domainname] );

	} else if (typeof(Gettext._locale_data) != 'undefined') {
		// didn't find domain we're looking for. Search all of them.
		for (var dom in Gettext._locale_data) {
			locale_data.push( Gettext._locale_data[dom] );
		}
	}

	var trans = [];
	var found = false;
	var domain_used; // so we can find plural-forms if needed
	if (locale_data.length) {
		for (var i=0; i<locale_data.length; i++) {
			var locale = locale_data[i];
			if (this.isValidObject(locale.msgs[msg_ctxt_id])) {
				// make copy of that array (cause we'll be destructive)
				for (var j=0; j<locale.msgs[msg_ctxt_id].length; j++) {
					trans[j] = locale.msgs[msg_ctxt_id][j];
				}
				trans.shift(); // throw away the msgid_plural
				domain_used = locale;
				found = true;
				// only break if found translation actually has a translation.
				if ( trans.length > 0 && trans[0].length != 0 )
					break;
			}
		}
	}

	if ( trans.length == 0 || trans[0].length == 0 ) {
		trans = [ msgid, msgid_plural ];
	}

	var translation = trans[0];
	if (plural) {
		var p;
		if (found && this.isValidObject(domain_used.head.plural_func) ) {
			var rv = domain_used.head.plural_func(n);
			if (! rv.plural) rv.plural = 0;
			if (! rv.nplural) rv.nplural = 0;
			// if plurals returned is out of bound for total plural forms
			if (rv.nplural <= rv.plural) rv.plural = 0;
			p = rv.plural;
		} else {
			p = (n != 1) ? 1 : 0;
		}
		if (this.isValidObject(trans[p]))
			translation = trans[p];
	}

	return translation;
};

Gettext.strargs = function (str, args) {
	if ( null == args ||
		 'undefined' == typeof(args) ) {
		args = [];
	} else if (args.constructor != Array) {
		args = [args];
	}

	var newstr = "";
	while (true) {
		var i = str.indexOf('%');
		var match_n;

		if (i == -1) {
			newstr += str;
			break;
		}

		newstr += str.substr(0, i);

		if (str.substr(i, 2) == '%%') {
			newstr += '%';
			str = str.substr((i+2));

		} else if ( match_n = str.substr(i).match(/^%(\d+)/) ) {
			var arg_n = parseInt(match_n[1]);
			var length_n = match_n[1].length;
			if ( arg_n > 0 && args[arg_n -1] != null && typeof(args[arg_n -1]) != 'undefined' )
				newstr += args[arg_n -1];
			str = str.substr( (i + 1 + length_n) );

		} else {
			newstr += '%';
			str = str.substr((i+1));
		}
	}

	return newstr;
}

Gettext.prototype.strargs = function (str, args) {
	return Gettext.strargs(str, args);
}

Gettext.prototype.isArray = function (thisObject) {
	return this.isValidObject(thisObject) && thisObject.constructor == Array;
};

Gettext.prototype.isValidObject = function (thisObject) {
	if (null == thisObject) {
		return false;
	} else if ('undefined' == typeof(thisObject) ) {
		return false;
	} else {
		return true;
	}
};

function _j (msgid) {
	if (typeof(gt) != "undefined" ) {
		return gt.gettext(msgid);
	} else {
		return msgid;
	}
}

