Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/FileUtils.jsm");

const PREF_TFB_UPDATE_URL_DOWNLOAD = "tenfourbird.update.url.download";

const PREF_APP_UPDATE_CHANNEL             = "app.update.channel";
const PREF_PARTNER_BRANCH                 = "app.partner.";

const PREF_APP_DISTRIBUTION               = "distribution.id";
const PREF_APP_DISTRIBUTION_VERSION       = "distribution.version";
const PREF_APP_DISTRIBUTION_ABOUT         = "distribution.about";

const FILE_UPDATE_LOCALE  = "update.locale";

const KEY_APPDIR          = "XCurProcD";
const KEY_GRED            = "GreD";

// not used yet
const PATH_CMD_MACHINE = "/usr/bin/machine";
const PATH_STDIN = "/dev/stdout";

function UpdateURLFormatter(update)
	{
	this.update = update;

	XPCOMUtils.defineLazyGetter(this, "gABI", function()
		{
		let abi = null;
		try
			{
			abi = Services.appinfo.XPCOMABI;
			}
		catch (e)
			{
			LOG("gABI - XPCOM ABI unknown: updates are not possible.");
			}
		// Mac universal build should report a different ABI than either macppc
		// or mactel.
		let macutils = CoC["@mozilla.org/xpcom/mac-utils;1"].getService(CoI.nsIMacUtils);

		if (macutils.isUniversalBinary)
			{
			abi += "-u-" + macutils.architecturesInBinary;
			}
//@line 49 "/Users/t_mrc-ct/Projects/Tenfourbird/repos/comm-esr31/mail/base/content/updatesOverlay.js"
		return abi;
		});
	XPCOMUtils.defineLazyGetter(this, "gOSVersion", function()
		{
		let osVersion;
		let sysInfo = CoC["@mozilla.org/system-info;1"].getService(CoI.nsIPropertyBag2);
		try
			{
			osVersion = sysInfo.getProperty("name") + " " + sysInfo.getProperty("version");
			}
		catch (e)
			{
			LOG("gOSVersion - OS Version unknown: updates are not possible.");
			}
		if (osVersion)
			{
			try
				{
				osVersion += " (" + sysInfo.getProperty("secondaryLibrary") + ")";
				}
			catch (e)
				{
				// Not all platforms have a secondary widget library, so an error is nothing to worry about.
				}
			osVersion = encodeURIComponent(osVersion);
			}
		return osVersion;
		});
	}

/**
 * Gets the locale from the update.locale file for replacing %LOCALE% in the
 * update url. The update.locale file can be located in the application
 * directory or the GRE directory with preference given to it being located in
 * the application directory.
 */
UpdateURLFormatter.prototype.getLocale = function()
	{
	if (gLocale)
		{
		return gLocale;
		}
	var localeFile = FileUtils.getFile(KEY_APPDIR, [FILE_UPDATE_LOCALE]);
	if (!localeFile.exists())
		{
		localeFile = FileUtils.getFile(KEY_GRED, [FILE_UPDATE_LOCALE]);
		}

	if (!localeFile.exists())
		{
		throw Components.Exception(FILE_UPDATE_LOCALE + " file doesn't exist in " +
			"either the " + KEY_APPDIR + " or " + KEY_GRED +
			" directories", CoR.NS_ERROR_FILE_NOT_FOUND);
		}
	gLocale = this.readStringFromFile(localeFile);
	LOG("getLocale - getting locale from file: " + localeFile.path +
		", locale: " + gLocale);
	return gLocale;
	}
/**
 * Read the update channel from defaults only.  We do this to ensure that
 * the channel is tightly coupled with the application and does not apply
 * to other instances of the application that may use the same profile.
 */
UpdateURLFormatter.prototype.getUpdateChannel = function()
	{
	var channel = "default";
	var prefName;
	var prefValue;
	try
		{
		channel = Services.prefs.getDefaultBranch(null).getCharPref(PREF_APP_UPDATE_CHANNEL);
		}
	catch (e)
		{
		 // use default when pref not found
		}

	try
		{
		var partners = Services.prefs.getChildList(PREF_PARTNER_BRANCH);
		if (partners.length)
			{
			channel += "-cck";
			partners.sort();

			for each (prefName in partners)
				{
				prefValue = Services.prefs.getCharPref(prefName);
				channel += "-" + prefValue;
				}
			}
		}
	catch (e)
		{
		Components.utils.reportError(e);
		}
	return channel;
	}
/* Get the distribution pref values, from defaults only */
UpdateURLFormatter.prototype.getDistributionPrefValue = function(aPrefName)
	{
	var prefValue = "default";
	try
		{
		prefValue = Services.prefs.getDefaultBranch(null).getCharPref(aPrefName);
		}
	catch (e)
		{
		// use default when pref not found
		}
	return prefValue;
	}
/**
 * Reads a string of text from a file.  A trailing newline will be removed
 * before the result is returned.  This function only works with ASCII text.
 */
UpdateURLFormatter.prototype.readStringFromFile = function(file)
	{
	if (!file.exists())
		{
		LOG("readStringFromFile - file doesn't exist: " + file.path);
		return null;
		}
	var fis = CoC["@mozilla.org/network/file-input-stream;1"].createInstance(CoI.nsIFileInputStream);
	fis.init(file, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, 0);
	var sis = CoC["@mozilla.org/scriptableinputstream;1"].createInstance(CoI.nsIScriptableInputStream);
	sis.init(fis);
	var text = sis.read(sis.available());
	sis.close();
	if (text[text.length - 1] == "\n")
		{
		text = text.slice(0, -1);
		}
	return text;
	}

UpdateURLFormatter.prototype.format = function(url)
	{
	/* from Checker:getUpdateURL (nsUpdateService.js) */
	url = url.replace(/%PRODUCT%/g, Services.appinfo.name);
	url = url.replace(/%VERSION%/g, Services.appinfo.version);
	url = url.replace(/%BUILD_ID%/g, Services.appinfo.appBuildID);
	url = url.replace(/%BUILD_TARGET%/g, Services.appinfo.OS + "_" + this.gABI);
	url = url.replace(/%OS_VERSION%/g, this.gOSVersion);
	if (/%LOCALE%/.test(url))
		{
		url = url.replace(/%LOCALE%/g, this.getLocale());
		}
	url = url.replace(/%CHANNEL%/g, this.getUpdateChannel());
	url = url.replace(/%PLATFORM_VERSION%/g, Services.appinfo.platformVersion);
	url = url.replace(/%DISTRIBUTION%/g,　this.getDistributionPrefValue(PREF_APP_DISTRIBUTION));
	url = url.replace(/%DISTRIBUTION_VERSION%/g,　this.getDistributionPrefValue(PREF_APP_DISTRIBUTION_VERSION));

	url = url.replace(/%UPDATE_TYPE%/g, this.update.type);
	url = url.replace(/%UPDATE_VERSION%/g, this.update.appVersion);
	url = url.replace(/%UPDATE_BUILD_ID%/g, this.update.buildID);

	url = url.replace(/\+/g, "%2B");
	return url;
	}

function ManualUpdatePage_TFBird(target_id)
	{
	this.targetId = target_id;
	}
ManualUpdatePage_TFBird.prototype.onPageShow = function()
	{
	var url = getPref("getCharPref", PREF_TFB_UPDATE_URL_DOWNLOAD, null);
	var fmt;

	if(url != null && url.length > 0)
		{
		fmt = new UpdateURLFormatter(gUpdates.update);
		url = fmt.format(url);
		}
	else
		{
		url = getPref("getCharPref", PREF_APP_UPDATE_MANUAL_URL, null);

		if(url = null || url == "")
			{
			LOG("ManualUpdatePage_TFBird(\"" + this.targetId + "\"):onPageShow - update URL not defined");
			}
		}

	var manualUpdateLinkLabel = document.getElementById(this.targetId);
	manualUpdateLinkLabel.value = url;
	manualUpdateLinkLabel.setAttribute("url", url);

	gUpdates.setButtons(null, "noThanksButton", "okButton", true);
	gUpdates.wiz.getButton("finish").focus();
	}
ManualUpdatePage_TFBird.prototype.onExtra2 = function()
	{
	gUpdates.never();
	gUpdates.wiz.cancel();
	}

var gManualUpdate2Page_TFBird = new ManualUpdatePage_TFBird("manualUpdate2LinkLabel");
var gManualUpdate3Page_TFBird = new ManualUpdatePage_TFBird("manualUpdate3LinkLabel");