var dllCLSID = "{F9D60BB6-FCD7-3FDC-9499-812EAC7305B7}";

var maxImages = 5000;			// Maximum number of images in database
var includeDirs = true;			// Include subfolders
var switchInterval = 30*60;		// Change the desktop every ...
var cycleInterval = 15;			// Change the displayed image every ...
								// Supported file types
var shuffleImages = false;		// Randomize pictures
var supportedFileTypes = " .jpg .jpeg .jpe .gif .png .bmp ";
var imgStyle = 0;				// Image positioning style 0=system, 1=stretch, 2=tile, 3=centre, 4=maintainAspect, 5=crop
var osXP = false;				// convert to BMP for XP

var imageIndex = -1;
var cycleIndex = -1;
var tRefresh, tRefresh2, startUp;
var aImages;

var gadgetPath = System.Gadget.path;
var charbackslash = new RegExp("\\\\", "g");

var myWallpaper = System.Environment.getEnvironmentVariable("USERPROFILE") + "\\Local Settings\\Application Data\\Microsoft\\Wallpaper1.";
var publicPictures = System.Environment.getEnvironmentVariable("PUBLIC") + "\\Pictures";
var myPictures = System.Environment.getEnvironmentVariable("USERPROFILE") + "\\Pictures";
var defaultWallpapers = System.Environment.getEnvironmentVariable("WINDIR") + "\\Web\\Wallpaper";
var currentPath = myPictures;

System.Gadget.settingsUI = "Settings.html";
System.Gadget.onDock = dockedState;
System.Gadget.onUndock = dockedState;
System.Gadget.Flyout.file = "flyout.html";

var oShell = new ActiveXObject("WScript.Shell");
var oFSO = new ActiveXObject("Scripting.FileSystemObject");

var bDebug = oFSO.FileExists(gadgetPath+"\\debug.txt");
try{
	if (bDebug)
		var debugLogFile = oFSO.OpenTextFile(gadgetPath+"\\debug.txt", 2);
} catch(err) {bDebug = false; debugLog("Open debug.txt error"+err.name+" - "+err.message)}

//detect OS
try{
	var oWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!//./root/cimv2");
	var tmp = oWMI.ExecQuery("Select * From Win32_OperatingSystem Where Primary='true'");
	var eTmp = new Enumerator(tmp);
	if (eTmp.item().Name.toLowerCase().indexOf("windows xp") > -1) {
		osXP = true;
		imgStyle = 4;
	}
	
	var tmp=null;
	var eTmp=null;
	var oWMI=null;
	if (bDebug) debugLog("XP: "+osXP);
} catch(err) {debugLog("detect OS:"+err.name+" - "+err.message)}


var Wallpaper, regRoot;

//register ActiveX component
if(bDebug) debugLog("Register ActiveX");
if(bDebug) debugLog("trying HKCU");
if (!activeDLL("HKCU")) {
	if(bDebug) debugLog("trying HKLM");
	if (!activeDLL("HKLM"))
		debugLog("Error creating Wallpaper ActiveX object");
}


// Register Wallpaper ActiveX component
function RegisterWallpaper() {
	var classRoot = regRoot + "\\Software\\Classes\\WallpaperGadget.Wallpaper\\";
	var clsidRoot = regRoot + "\\Software\\Classes\\CLSID\\" + dllCLSID + "\\";

	try{
		oShell.RegWrite(classRoot,"WallpaperGadget.Wallpaper", "REG_SZ");
		oShell.RegWrite(classRoot + "CLSID\\", dllCLSID, "REG_SZ");
		oShell.RegWrite(clsidRoot, "WallpaperGadget.Wallpaper", "REG_SZ");
		oShell.RegWrite(clsidRoot + "InprocServer32\\", "mscoree.dll", "REG_SZ");
		oShell.RegWrite(clsidRoot + "InprocServer32\\ThreadingModel", "Both", "REG_SZ");
		oShell.RegWrite(clsidRoot + "InprocServer32\\Class", "WallpaperGadget.Wallpaper", "REG_SZ");
		oShell.RegWrite(clsidRoot + "InprocServer32\\Assembly", "Wallpaper, Version=1.0.2601.7681, Culture=neutral, PublicKeyToken=null", "REG_SZ");
		oShell.RegWrite(clsidRoot + "InprocServer32\\RuntimeVersion", "v2.0.50727", "REG_SZ");
		oShell.RegWrite(clsidRoot + "InprocServer32\\CodeBase", "file:///" + gadgetPath.replace(charbackslash, "/") + "/Wallpaper.dll", "REG_SZ");
		oShell.RegWrite(clsidRoot + "InprocServer32\\1.0.2601.7681\\Class", "WallpaperGadget.Wallpaper", "REG_SZ");
		oShell.RegWrite(clsidRoot + "InprocServer32\\1.0.2601.7681\\Assembly", "Wallpaper, Version=1.0.2601.7681, Culture=neutral, PublicKeyToken=null", "REG_SZ");
		oShell.RegWrite(clsidRoot + "InprocServer32\\1.0.2601.7681\\RuntimeVersion", "v2.0.50727", "REG_SZ");
		oShell.RegWrite(clsidRoot + "InprocServer32\\1.0.2601.7681\\CodeBase", "file:///" + gadgetPath.replace(charbackslash, "/") + "/Wallpaper.dll", "REG_SZ");
		oShell.RegWrite(clsidRoot + "ProgId\\", "WallpaperGadget.Wallpaper", "REG_SZ");
		oShell.RegWrite(clsidRoot + "ProgId\\Implemented Categories\\{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}\\", "", "REG_SZ");
	} catch(err) {debugLog("RegisterWallpaper: "+err.name+" - "+err.message)}
}



// terminate the DLL
function terminate() {
	try{Wallpaper.Terminate()} catch(err) {debugLog("Can't dispose of Wallpaper DLL")}

	Wallpaper = null;

	UnregisterWallpaper();
}



// Unregister DirectSound ActiveX component
function UnregisterWallpaper() {
	var classRoot = regRoot + "\\Software\\Classes\\WallpaperGadget.Wallpaper\\";
	var clsidRoot = regRoot + "\\Software\\Classes\\CLSID\\" + dllCLSID + "\\";

	try{		
		oShell.RegDelete(clsidRoot + "ProgId\\Implemented Categories\\{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}\\");
		oShell.RegDelete(clsidRoot + "ProgId\\Implemented Categories\\");
		oShell.RegDelete(clsidRoot + "ProgId\\");
		oShell.RegDelete(clsidRoot + "InprocServer32\\1.0.2601.7681\\");
		oShell.RegDelete(clsidRoot + "InprocServer32\\");
		oShell.RegDelete(clsidRoot);
		oShell.RegDelete(classRoot + "CLSID\\");
		oShell.RegDelete(classRoot);
	} catch(err) {debugLog("UnregisterWallpaper: "+err.name+" - "+err.message)}
}



// Try to register the DLL
function activeDLL(root) {
	regRoot = root;

	try{
		RegisterWallpaper();
		Wallpaper = new ActiveXObject("WallpaperGadget.Wallpaper");
	} catch(err) {
		Wallpaper = null;
		UnregisterWallpaper();
		return false;
	}
	return true;
}



//log a debug entry
function debugLog(str) {
	try{
		System.Debug.outputString(str);
		if (bDebug)
			debugLogFile.WriteLine(str);
	} catch(err) {}
}



// Initialize the Gadget
function startUpGadget() {
	try{
		dockedState();

		//restore settings
		if (System.Gadget.Settings.readString("switchInterval") != "")
			switchInterval = System.Gadget.Settings.read("switchInterval");
		if (System.Gadget.Settings.readString("cycleInterval") != "")
			cycleInterval = System.Gadget.Settings.read("cycleInterval");
		if (System.Gadget.Settings.readString("includeDirs") != "")
			includeDirs = System.Gadget.Settings.read("includeDirs");
		if (System.Gadget.Settings.readString("currentPath") != "")
			currentPath = System.Gadget.Settings.readString("currentPath");
		if (System.Gadget.Settings.readString("shuffleImages") != "")
			shuffleImages = System.Gadget.Settings.read("shuffleImages");
		if (System.Gadget.Settings.readString("imgStyle") != "")
			imgStyle = System.Gadget.Settings.read("imgStyle");
		if (System.Gadget.Settings.readString("cycleIndex") != "")
			cycleIndex = System.Gadget.Settings.read("cycleIndex")-1;
		if (System.Gadget.Settings.readString("imageIndex") != "")
			imageIndex = System.Gadget.Settings.read("imageIndex")-1;
	
		startUp = true;
		initArray(false);
		startUp = false;
	} catch(err) {debugLog("startUpGadget: "+err.name+" - "+err.message)}
}



// Initialize the image array
function initArray(dirChanged) {
	try{window.clearTimeout(tRefresh)} catch(err) {debugLog("Cancel timer: "+err.name+ " - "+err.message)}
	try{window.clearTimeout(tRefresh2)} catch(err) {debugLog("Cancel timer2: "+err.name+ " - "+err.message)}

	aImages = new Array();
	catalogueImages(currentPath);

	//if there's no images, use the windows wallpaper folder
	if (aImages.length == 0) {
		currentPath = defaultWallpapers;
		catalogueImages(currentPath);
	}

	//if we have images, setup the timers and display the 1st picture
	if (aImages.length>0)
	{
		if (shuffleImages) aImages.sort(randomOrder);

		if (imageIndex>aImages.length || dirChanged) imageIndex = -1;
		if (cycleIndex>aImages.length || dirChanged) cycleIndex = -1;

		displayNext(true);
		setupTimers();
	}
}



// Used to randomly sort the image array
function randomOrder() {
	return (Math.round(Math.random())-0.5); 
}



// Setup the update Timer
function setupTimers() {
	//clear timers
	try{window.clearTimeout(tRefresh)} catch(err) {debugLog("Cancel timer: "+err.name+ " - "+err.message)}
	try{window.clearTimeout(tRefresh2)} catch(err) {debugLog("Cancel timer2: "+err.name+ " - "+err.message)}

	//create desktop change timers
	tRefresh = window.setInterval(displayNext, switchInterval * 1000);

	//create slideshow timer only if we're not in preview next mode
	if (cycleInterval == 0)
		imageIndex = cycleIndex-1;
	else
		tRefresh2 = window.setInterval("displayNext(true)", cycleInterval * 1000);
}



// Display the previous image
function displayPrevious() {
	if (cycleIndex-- == 0) cycleIndex = aImages.length - 1;

	imgSrc.src = aImages[cycleIndex];
	System.Gadget.Settings.write("cycleIndex", cycleIndex);
	if (cycleInterval == 0) {
		imageIndex = cycleIndex-1;
		System.Gadget.Settings.write("imageIndex", imageIndex);
	}
}



// Display the next image
function displayNext(setImage) {
	if (!System.Gadget.visible && !startUp && cycleInterval != 0) return;

	try{
		//go to the next image
		if (!setImage) {	// set the Desktop
			if (imageIndex++ == aImages.length-1) imageIndex = 0;
			System.Gadget.Settings.write("imageIndex", imageIndex);
	
			setWallpaper(true);
			if (cycleInterval == 0) cycleIndex=imageIndex;
		}
	
		if (setImage || cycleInterval == 0) {
			if (cycleIndex++ == aImages.length-1) cycleIndex = 0;
			System.Gadget.Settings.write("cycleIndex", cycleIndex);
	
			imgSrc.src = aImages[cycleIndex];
			if (cycleInterval == 0) imageIndex=cycleIndex-1;
		}
	} catch(err) {debugLog("displayNext: "+err.name+" - "+err.message)}
}



// Set the desktop wallpaper
function setWallpaper(setImage) {
	try{
		if (setImage)
			scaleImage(aImages[imageIndex]);
		else {
			if (bDebug) debugLog(aImages[cycleIndex]);
			scaleImage(aImages[cycleIndex]);
			imageIndex = cycleIndex;
			if (cycleInterval == 0) displayNext(true);
		}
	} catch(err) {debugLog("setWallpaper: "+err.name+" - "+err.message)}
}



function scaleImage(sFilename) {
	if (!oFSO.FileExists(sFilename)) return;

	try{
		var lFilename = myWallpaper;
	
		//use BMP if we're running in XP
		if (osXP) {
			lFilename += "bmp";
			if (imgStyle!=4 && imgStyle!=5) imgStyle = 4;
		} else
			lFilename += "jpg";
	
		//set the current user positioning values for the standard styles
		switch(imgStyle)
		{
			case 1: //stretch
				oShell.RegWrite("HKCU\\Control Panel\\Desktop\\WallpaperStyle","2", "REG_SZ");
				oShell.RegWrite("HKCU\\Control Panel\\Desktop\\TileWallpaper","0", "REG_SZ");
				break;
			case 2: //tile
				oShell.RegWrite("HKCU\\Control Panel\\Desktop\\WallpaperStyle","1", "REG_SZ");
				oShell.RegWrite("HKCU\\Control Panel\\Desktop\\TileWallpaper","1", "REG_SZ");
				break;
			case 3: //centre
				oShell.RegWrite("HKCU\\Control Panel\\Desktop\\WallpaperStyle","1", "REG_SZ");
				oShell.RegWrite("HKCU\\Control Panel\\Desktop\\TileWallpaper","0", "REG_SZ");
				break;
		}
	
		if (osXP || imgStyle == 4) {					// maintain aspect ratio
			Wallpaper.ScaleImage(sFilename, lFilename);
			Wallpaper.SetWallpaper(lFilename);
		} else if (imgStyle == 5) {						// crop to fit screen
			Wallpaper.CropImage(sFilename, lFilename);
			Wallpaper.SetWallpaper(lFilename);
		} else											// all other styles
			Wallpaper.SetWallpaper(sFilename);
	} catch(err) {debugLog("scaleImage: "+err.name+" - "+err.message)}
}



// Catalogue the images in the selected folder
function catalogueImages(filePath) {
	//stop getting images if we have too many
	if (aImages.length >= maxImages) return;

	//get the folder
	try{
		var oFolder = System.Shell.itemFromPath(filePath); 
	} catch(err) {debugLog("catalogueImages: "+err.name+" - "+err.message); return;}

	try{
		//dont look in compressed folders
		if(oFolder.type == "Compressed (zipped) Folder") return;
	
		//get the files in the folder
		var oItems = oFolder.SHFolder.Items;
		var sFiletype;
	
		var imageCount = oItems.count;
	
		for(var i = 0; i<imageCount && aImages.length<maxImages; i++)
		{
			var sFile = oItems.item(i).path;
			if (bDebug) debugLog("file: "+sFile);
	
			if(!oItems.item(i).isFolder)
	        {
				sFiletype = sFile.substr(sFile.lastIndexOf(".")).toLowerCase();
	            if(supportedFileTypes.indexOf(" " + sFiletype + " ") > -1)
					aImages.push(sFile);
	        }
	    }
	
		if (includeDirs)
			for(var i = 0; i<oItems.count && aImages.length<maxImages; i++)
				if(oItems.item(i).isFolder) {
					if (bDebug) debugLog("scanning "+ oItems.item(i).path);
					catalogueImages(oItems.item(i).path);
				}
	} catch(err) {debugLog("catalogueImages: "+err.name+" - "+err.message)}
}



// scale the gadget according to it's docked state
function dockedState() {
	System.Gadget.beginTransition();
	
	if (System.Gadget.docked) {
		document.body.style.width = 130;
		document.body.style.height = 100;
	} else {
		document.body.style.width = 360;
		document.body.style.height = 280;
	}

	if (startUp) {
		System.Gadget.endTransition(System.Gadget.TransitionType.none, 0);
		fixZoom();
	} else {
		System.Gadget.endTransition(System.Gadget.TransitionType.morph, 0.2);
		window.setTimeout(fixZoom, 300);
	}
}



// begin/endTransition corrupt the image, so we change the scale after the transition
function fixZoom() {
	if (System.Gadget.docked) {
		System.Gadget.background = "images/background.png";
		imgFrame.style.top = 5;
		imgFrame.style.left = 4;
		imgFrame.style.height = 90;
		imgFrame.style.width = 121;
		imgSrc.style.width = 121;
		imgSrc.style.maxHeight = 90;
		divMenu.style.top = 70;
	} else {
		System.Gadget.background = "images/backgroundLarge.png";
		imgFrame.style.top = 9;
		imgFrame.style.left = 9;
		imgFrame.style.height = 261;
		imgFrame.style.width = 341;
		imgSrc.style.width = 341;
		imgSrc.style.maxHeight = 261;
		divMenu.style.top = 244;
	}
}