const PREF_NONE 	= 0x00;
const PREF_STRING 	= 0x20;
const PREF_INT 		= 0x40;
const PREF_BOOL 	= 0x80;

const nsISupportsString = Components.interfaces.nsISupportsString;
const nsIPrefLocalizedString = Components.interfaces.nsIPrefLocalizedString;

var pref = Components.classes["@mozilla.org/preferences-service;1"]
	.getService(Components.interfaces.nsIPrefBranch);
var sstr = Components.classes["@mozilla.org/supports-string;1"]
	.createInstance(nsISupportsString);

function getPrefValue(prefID) {
	try {
		switch (pref.getPrefType(prefID)) {
		case PREF_NONE:
			return null;
		case PREF_BOOL:
			return (pref.getBoolPref(prefID)) ? "true" : "false";
		case PREF_INT:
			return pref.getIntPref(prefID).toString(10);
			//			case PREF_STRING: return pref.getComplexValue(prefID,nsISupportsString).data;
		case PREF_STRING:
			var v = pref.getComplexValue(prefID, nsISupportsString).data;
			if (v.indexOf("chrome:") == 0)
				try {
					v = pref.getComplexValue(prefID, nsIPrefLocalizedString).data;
				} catch (e) {}
			return v;
			//			case PREF_STRING: return pref.getCharPref(prefID);
		default:
			return "[unknown PrefType: " + pref.getPrefType(prefID) + "]";
		}
	} catch (e) {
		return null;
	}
}
function restoreDefault(prefID) {
	try {
		pref.clearUserPref(prefID);
	} catch (e) {}
}
function setIntPref(prefID, prefVal) {
	if (prefVal) {
		var re = new RegExp("^[0-9]+$");
		if (re.test(prefVal))
			pref.setIntPref(prefID, parseInt(prefVal));
		else {
			alert(document.getElementById("pref_bundle").getString("positive_integer_expected"));
			document.getElementById(prefID).value = getPrefValue(prefID);
			document.getElementById(prefID).focus();
		}
	} else
		restoreDefault(prefID);
}
function setCharPref(prefID, prefVal) {
	sstr.data = prefVal;
	pref.setComplexValue(prefID, nsISupportsString, sstr);
	//	pref.setCharPref(prefID,prefVal);
}
function initCheckbox(prefID) {
	var box = document.getElementById(prefID);
	if (!box) {
    return;
   }
	try {
		box.checked = (box.getAttribute("inverse") == "true") ? !pref.getBoolPref(prefID) : pref.getBoolPref(prefID);
	} catch (e) {
		box.disabled = true;
	}
}
function toggleCheckbox(prefID) {
	var val;
	
	try {
		val = !pref.getBoolPref(prefID);
	} catch (e) {
		var box = document.getElementById(prefID);
		val = (box.getAttribute("inverse") == "true") ? !box.checked : box.checked;
	}
	pref.setBoolPref(prefID, val);
}
function initRadiogroup(prefID) {
	var grp = document.getElementById(prefID),
	val = getPrefValue(prefID);
	
	if (val == null)
		try {
			for (grp.selectedIndex = 0; grp.selectedItem.value; grp.selectedIndex++)
				grp.selectedItem.disabled = true;
		} catch (e) {}
		
	else
		try {
			for (grp.selectedIndex = 0; grp.selectedItem.value != val; grp.selectedIndex++);
		} catch (e) {}
}
function toggleRadiogroup(prefID) {
	var grp = document.getElementById(prefID),
	val = grp.value;
	
	try {
		switch (pref.getPrefType(prefID)) {
		case PREF_BOOL:
			pref.setBoolPref(prefID, (val == "true") ? true : false);
			break;
		case PREF_INT:
			val = parseInt(val);
			if (!isNaN(val))
				pref.setIntPref(prefID, val);
			break;
		case PREF_STRING:
			pref.setCharPref(prefID, val);
			break;
		}
	} catch (e) {}
}
function initTextbox(prefID, emptyStr) {
	var box = document.getElementById(prefID),
	val = getPrefValue(prefID);
	
	box.removeAttribute("onfocus");
	box.removeAttribute("onblur");
	if (val == null) {
		val = document.getElementById("pref_bundle").getString("pref_not_set");
		if (!box.readonly) {
			box.setAttribute("onfocus", "this.value=''");
			box.setAttribute("onblur", "initTextbox('" + prefID + "'," + ((emptyStr) ? ("'" + emptyStr + "'") : "false") + ")");
		}
		box.value = (emptyStr) ? emptyStr : val;
		return;
	}
	if (!val && emptyStr) {
		if (!box.readonly) {
			box.setAttribute("onfocus", "this.value=''");
			box.setAttribute("onblur", "initTextbox('" + prefID + "','" + emptyStr + "')");
		}
		box.value = emptyStr;
	} else
		box.value = val;
}
function initMenulist(prefName, prefRoot, invalidNote) {
	var lst = document.getElementById(prefName),
	val = getPrefValue(prefRoot + prefName),
	sel = null;
	
	lst.selectedIndex = 0;
	lst.value = val;
	try {
		sel = lst.selectedItem.value;
	} catch (e) {}
	if (lst.value != sel) {
		lst.firstChild.appendChild(document.createElement("menuseparator"));
		lst.firstChild.appendChild(document.createElement("menuitem"));
		lst.firstChild.lastChild.setAttribute("value", val);
		lst.firstChild.lastChild.setAttribute("label", (val) ? ((invalidNote) ? val + " " + invalidNote : val) : document.getElementById("pref_bundle").getString("pref_not_set"));
		lst.firstChild.lastChild.setAttribute("disabled", !val);
		lst.selectedItem = lst.firstChild.lastChild;
	}
}
/* --- String Functions ----------------------------------------------------------------------------------------- */
function alphabetical(x, y) {
	return x.toLowerCase().localeCompare(y.toLowerCase());
}
function expandEnvironmentStrings(string) {
	var str = /%(\w+)%/.exec(string);
	
	if (str) {
		var env = Components.classes["@mozilla.org/process/environment;1"]
			.getService(Components.interfaces.nsIEnvironment);
		
		for (var i = 1, reg; i < str.length; i++)
			if (env.exists(str[i])) {
				reg = new RegExp("%" + str[i] + "%");
				string = string.replace(reg, env.get(str[i]));
			}
	}
	return string;
}
function makeUTF8(string) {
	setCharPref(kmPrefs.temp, string);
	var ret = pref.getCharPref(kmPrefs.temp);
	restoreDefault(kmPrefs.temp);
	return ret;
}
/* --- Windows Registry Functions (Mozilla 1.8) ----------------------------------------------------------------- */
const HKCR = 0x80000000;
const HKCU = 0x80000001;
const HKLM = 0x80000002;
const HKU  = 0x80000003;
const HKCC = 0x80000005;

function getKey(keyRoot, keyPath, keyName) {
	var keyValue = null;
	
	try {
		var reg = Components.classes["@mozilla.org/windows-registry-key;1"].createInstance(Components.interfaces.nsIWindowsRegKey);
		reg.open(keyRoot, keyPath, reg.ACCESS_READ);
		/*		switch(reg.getValueType(keyName)) {
		// getValueType() is not available
		case reg.TYPE_STRING: keyValue = reg.readStringValue(keyName); break;
		case reg.TYPE_BINARY: keyValue = reg.readBinaryValue(keyName); break;
		case reg.TYPE_INT   : keyValue = reg.readIntValue(keyName); break;
		case reg.TYPE_INT64 : keyValue = reg.readInt64Value(keyName); break;
		}
		 */
		keyValue = reg.readStringValue(keyName);
		reg.close();
	} catch (e) {}
	return keyValue;
}
/* --- File & Folder Functions ---------------------------------------------------------------------------------- */
const nsIFilePicker = Components.interfaces.nsIFilePicker;
const nsILocalFile = Components.interfaces.nsILocalFile;
const nsIFile = Components.interfaces.nsIFile;
const nsIProperties = Components.interfaces.nsIProperties;

const MODE_RDONLY	= 0x01;
const MODE_WRONLY	= 0x02;
const MODE_RDWR		= 0x04;
const MODE_CREATE	= 0x08;
const MODE_APPEND	= 0x10;
const MODE_TRUNCATE	= 0x20;
const MODE_SYNC		= 0x40;
const MODE_EXCL		= 0x80;

function getFolder(prefID) {
	var path;
	try {
		path = pref.getComplexValue(prefID, nsILocalFile);
	} catch (e) {
		try {
			path = Components.classes["@mozilla.org/file/directory_service;1"]
				.getService(nsIProperties)
				.get(prefID, nsIFile);
		} catch (e) {
			path = false;
		}
	}
	//	return ((path) ? path.path : false);
	var Kpath = path.path;
	if (prefID == "CurProcD") {
		Kpath = Kpath.replace(/\\browser/, '');
	}
	return ((path) ? Kpath : false);
}
function getFile(filePath, fileName) {
	var file = Components.classes["@mozilla.org/file/local;1"]
		.createInstance(nsILocalFile);
	
	file.initWithPath(filePath);
	if (fileName)
		file.append(fileName);
	return file;
}
function getFileURL(file) {
	var ios = Components.classes["@mozilla.org/network/io-service;1"]
		.getService(Components.interfaces.nsIIOService);
	var fph = ios.getProtocolHandler("file")
		.QueryInterface(Components.interfaces.nsIFileProtocolHandler);
	return fph.getURLSpecFromFile(file);
	
}
function getFileContents(file) {
	var fileContents = "";
	
	if (file.exists()) {
		var fis = Components.classes["@mozilla.org/network/file-input-stream;1"]
			.createInstance(Components.interfaces.nsIFileInputStream);
		var sis = Components.classes["@mozilla.org/scriptableinputstream;1"]
			.createInstance(Components.interfaces.nsIScriptableInputStream);
		
		fis.init(file, MODE_RDONLY, 0, fis.CLOSE_ON_EOF);
		sis.init(fis);
		while (sis.available() > 0)
			fileContents += sis.read(sis.available());
		sis.close();
		fis.close();
	}
	return fileContents;
}
function getFileContentsUTF8(file) {
	var fileContents = "";
	
	if (file.exists()) {
		var fis = Components.classes["@mozilla.org/network/file-input-stream;1"]
			.createInstance(Components.interfaces.nsIFileInputStream);
		var sis = Components.classes["@mozilla.org/scriptableinputstream;1"]
			.createInstance(Components.interfaces.nsIScriptableInputStream);
		
		fis.init(file, MODE_RDONLY, 0, fis.CLOSE_ON_EOF);
		sis.init(fis);
		while (sis.available() > 0)
			fileContents += makeUTF8(sis.read(sis.available()));
		sis.close();
		fis.close();
	}
	return fileContents;
}
function setFileContents(file, fileContents) {
	var fos = Components.classes["@mozilla.org/network/file-output-stream;1"]
		.createInstance(Components.interfaces.nsIFileOutputStream);
	
	fos.init(file, MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE, 0644, 0);
	var ret = fos.write(fileContents, fileContents.length);
	fos.close();
	return ret;
}
/* --- User StyleSheet Functions -------------------------------------------------------------------------------- */
var UserPrefs = getFile(getFolder("ProfD"), "user.js");
var UserStyle = getFile(getFolder("UChrm"), "userContent.css");
var testInverse = false;
var testResult = true;

function getIntUserPref(prefID, emptyStr) {
	var re = new RegExp("user_pref[\\s]*\\([\\s]*." + prefID + ".[\\s]*,[\\s]*([\\d]+)[\\s]*\\)[\\s]*;", "m");
	try {
		var ret = getFileContents(UserPrefs).match(re)[1];
	} catch (e) {
		var ret = emptyStr;
	}
	return ret;
}
function testMultiline(aString, aRegExpString) {
	var re = new RegExp(aRegExpString, "m");
	
	return re.test(aString);
}
function addToUserStyle(aString) {
	var fileContents = getFileContents(UserStyle);
	
	if (aString.indexOf("@import") > -1)
		// insert @import rules on top of others
		fileContents = aString + "\r\n" + fileContents;
	else
		fileContents += "\r\n" + aString;
	
	return (setFileContents(UserStyle, fileContents) == fileContents.length);
}
function addToUserPrefs(aString) {
	var fileContents = getFileContents(UserPrefs);
	
	fileContents = aString + "\r\n" + fileContents;
	
	return (setFileContents(UserPrefs, fileContents) == fileContents.length);
}
function removeFromFile(file, aRegExpString) {
	var fileContents = getFileContents(file);
	if (testInverse)
		var re = new RegExp("\r\n" + aRegExpString);
	else {
		var re = new RegExp(aRegExpString + "\r\n");
		testResult = true;
	}
	
	if (re.test(fileContents)) {
		fileContents = fileContents.replace(re, "");
		testResult &= (setFileContents(file, fileContents) == fileContents.length);
	} else
		testResult &= true;
	if (testInverse) {
		testInverse = false;
		return testResult;
	} else {
		testInverse = true;
		return removeFromFile(file, aRegExpString);
	}
}
/* --- K-Meleon-specific Functions ------------------------------------------------------------------------------ */
var kPlugin = {
	
	absent : function (pluginName) {
		return !(getFile(getFolder("KAPlugins"), pluginName + ".dll").exists() || getFile(getFolder("KUPlugins"), pluginName + ".dll").exists());
	},
	load : function (pluginName) {
		if (this.absent(pluginName))
			return false;
		try {
			var val = pref.getBoolPref("kmeleon.plugins." + pluginName + ".load");
		} catch (e) {
			return false;
		}
		return val;
	},
	fullName : function (pluginName) {
		try {
			var val = document.getElementById("kplugin_bundle").getString(pluginName);
		} catch (e) {
			return document.getElementById("kplugin_bundle").getString("unknown_kplugin");
		}
		return val;
	}
	
};

function kTabs() {
	try {
		var val = pref.getBoolPref("kmeleon.notab");
	} catch (e) {
		return true;
	}
	return !val;
}

var kMacrosModule = {
	
	load : function (moduleName) {
		if (getFile(getFolder("KUserSettings"), "macros.cfg").exists())
			return false;
		if (!getFile(getFolder("CurProcD") + "\\macros\\", "main.kmm").exists())
			return false;
		if (moduleName == "main")
			return true;
		return ((getFile(getFolder("CurProcD") + "\\macros\\", moduleName + ".kmm").exists() || getFile(getFolder("KUserSettings") + "\\macros\\", moduleName + ".kmm").exists()) && (getPrefValue("kmeleon.plugins.macros.modules." + moduleName + ".load") != "false"));
	}
	
};
/* --- Helper Functions ----------------------------------------------------------------------------------------- */
var interactiveElements = new Array("button", "checkbox", "menulist", "radio", "textbox");

function disableAll(disable) {
	for (var j = 0; j < interactiveElements.length; j++)
		for (var k = 0, e = document.getElementsByTagName(interactiveElements[j]); k < e.length; k++)
			e[k].disabled = disable;
	for (var j = 0, t = document.getElementsByTagName("tab"); j < t.length; j++)
		t[j].setAttribute("disabled", disable);
}

var kmPrefs = {
	
	last : "kmprefs.last",
	temp : "kmprefs.temp",
	save : function () {
		try {
			Components.classes["@mozilla.org/preferences-service;1"]
			.getService(Components.interfaces.nsIPrefService)
			.savePrefFile(null);
		} catch (e) {}
	}
	
};

/* --- Functions from Seamonkey 2 \chrome\comm\content\communicator\pref\preferences.js --- */

function EnableElementById(aElementId, aEnable, aFocus) {
	EnableElement(document.getElementById(aElementId), aEnable, aFocus);
}

function EnableElement(aElement, aEnable, aFocus) {
	/*  try {
	let pref = document.getElementById(aElement.getAttribute("preference"));
	} catch(e) { let pref = false; }
	if (!pref) {
	let enabled = aEnable;
	} else {
	let enabled = aEnable && !pref.locked;
	}
	 */
	let enabled = aEnable;
	aElement.disabled = !enabled;
	
	if (enabled && aFocus)
		aElement.focus();
}