(function() {
	
	var exports = {};
	
	exports.update = function(data)
	{
		data = data || {};
		
		var visibleBlock = document.querySelector('#'+data.uistate);
		var allBlocks = document.querySelectorAll(".mode");
		for (var i = 0; i < allBlocks.length; i++) {
			var block = allBlocks[i];
			if (block === visibleBlock) {
				if (!block.classList.contains("on")) {
					block.classList.add("on");
				}
			}
			else {
				block.classList.remove("on");
			}
		}
		
		if (data.outputFolder) {
			var elements = document.querySelectorAll(".output-folder");
			for (var i = 0; i < elements.length; i++) {
				elements[i].innerText = data.outputFolder;
			}
		}
		
		if (data.showProjectSettings) {
			projectSettings.update({
				indexingMode: (data.indexingMode || "tagged" || "all"),
				outputPath: (data.outputPath || "Build/")
			});
			
			projectSettings.show();
		}
		
		if (data.showMixinSettings) {
			mixinSettings.update({
				generators: (data.generators || []), // [ {"name": ..., "configPath": ... } ],
				selectedGenerator: (data.selectedGenerator || null), // { "name": ..., "config": {...} },
				ownerDirectoryPath: (data.ownerDirectoryPath || null)
			});
			
			mixinSettings.show();
		}
	};
	
	exports.prepareForReuse = function()
	{
		projectSettings.prepareForReuse();
		mixinSettings.prepareForReuse();
	};
	
	window.ui = exports;
	
	// Internals
	
	var projectSettings = {
		// UI
		container: null,
		indexingModeTagged: null,
		indexingModeAll: null,
		
		init: function()
		{
			// UI elements
			this.container = document.querySelector('#projectSettings');
			this.indexingModeTagged = document.querySelector('input[name="indexingMode"][id="tagged"]');
			this.indexingModeAll = document.querySelector('input[name="indexingMode"][id="all"]');
			
			// Events
			this.indexingModeAll.addEventListener('click', function() { projectSettings.save(); });
			this.indexingModeTagged.addEventListener('click', function() { projectSettings.save(); });
		},
		
		prepareForReuse: function()
		{
			this.hide();
		},
		
		show: function()
		{
			utils.show(this.container);
		},
		
		hide: function()
		{
			utils.hide(this.container);
		},
		
		update: function(data)
		{
			if (data.indexingMode === "tagged") {
				this.indexingModeTagged.checked = true;
			}
			else if (data.indexingMode === "all") {
				this.indexingModeAll.checked = true;
			}
		},
		
		save: function()
		{
			var data = {
				indexingMode: "tagged",
				outputPath: "Build/"
			};
			
			if (this.indexingModeAll.checked) {
				data.indexingMode = "all";
			}
			
			bridge.send('saveProjectSettings', data);
		}
	};
	
	var mixinSettings = {
		// UI
		container: null,
		noGenerator: null,
		parentGenerator: null,
		generatorSelect: null,
		generatorConfig: null,
		saveButton: null,
		parentGeneratorFormat: null,
		
		// State
		isVisible: false,
		generators: null,
		selectedGenerator: null,
		
		init: function()
		{
			// Find UI elements
			this.container = document.querySelector('#mixinSettings');
			this.noGenerator = document.querySelector('#noGenerators');
			this.parentGenerator = document.querySelector('#parentGenerator');
			this.generatorSelect = document.querySelector('select#generators');
			this.generatorConfig = document.querySelector('#generatorConfig');
			this.saveButton = document.querySelector('#mixinSettings #save');
			this.parentGeneratorFormat = (document.querySelector('#parentGenerator') || {}).innerHTML;
			
			// Bind events
			this.generatorSelect.addEventListener('click', function() {
				return mixinSettings.didChangeGeneratorSelection();
			});
			
			this.generatorConfig.onsubmit = function() {
				return mixinSettings.save() && false;
			};
			
			this.saveButton.onclick = this.generatorConfig.onsubmit;	
			
			utils.disable(this.saveButton);
			utils.hide(this.parentGenerator);
			utils.hide(this.noGenerator);
		},
		
		prepareForReuse: function()
		{
			if (this.selectedGenerator) {
				this.generatorSelect.selectedIndex = 0;
				this.didChangeGeneratorSelection();
			}
			
			this.hide();
		},
		
		show: function()
		{
			utils.show(this.container);
		},
		
		hide: function()
		{
			utils.hide(this.container);
		},
		
		update: function(data)
		{
			if (data.generators) {
			
				// Repopulate list
				var generators = [];
				var shouldReselectGenerator = false;
				var generatorOptionHTML = '<option>Dynamo</option>';
				var selectedGenerator = data.selectedGenerator;
				var userSelectedGenerator = this.selectedGenerator;
				
				if (data.generators.length > 0) {
					generatorOptionHTML += '<optgroup label="Generators">';
					
					data.generators.forEach(function(currentGenerator) {
						shouldReselectGenerator = shouldReselectGenerator || (userSelectedGenerator && currentGenerator.name == userSelectedGenerator.name);
						
						// Convenience: store the config path for the selected generator
						if ((selectedGenerator || {}).name === currentGenerator.name) {
							selectedGenerator.configPath = currentGenerator.configPath;
							currentGenerator.config = (selectedGenerator || {}).config;
						}
						
						generators.push(currentGenerator);
						generatorOptionHTML += '<option>' + currentGenerator.name + '</option>';
					});
					
					generatorOptionHTML += '</optgroup>';
				}
								
				this.generators = generators;
				this.generatorSelect.innerHTML = generatorOptionHTML;
				
				// Reselect generator that's not saved to disk yet
				if (shouldReselectGenerator) {
					this.generatorSelect.value = userSelectedGenerator.name;
				}
				else if (data.selectedGenerator) {
					// Select generator that's currently active
					this.generatorSelect.value = data.selectedGenerator.name;
					this.didChangeGeneratorSelection();
				}
				else {
					this.generatorSelect.selectedIndex = 0;
					this.didChangeGeneratorSelection();
				}
			}
			
			// Show information about generators if our project doesn't have any			
			if (this.generators.length === 0) {
				utils.disable(this.generatorSelect);
				utils.disable(this.saveButton);
				
				utils.hide(this.parentGenerator);
				utils.hide(this.generatorConfig);
				utils.show(this.noGenerator);
			}
			// Show information about the owner generator directory if the directory is managed by an ancestor
			else if (data.ownerDirectoryPath) {
				
				utils.disable(this.generatorSelect);
				utils.disable(this.saveButton);
				
				utils.hide(this.noGenerator);
				utils.hide(this.generatorConfig);
				
				var message = this.parentGeneratorFormat;
				message = message.replace('$generatorName', (this.selectedGenerator || {}).name);
				message = message.replace('$parentDirectory', data.ownerDirectoryPath);
				this.parentGenerator.innerHTML = message;
				
				utils.show(this.parentGenerator);				
			}
			// Show generator configuration and enable selection
			else {
				utils.enable(this.generatorSelect);
				utils.enable(this.saveButton);
				
				utils.hide(this.noGenerator);
				utils.hide(this.parentGenerator);
				utils.show(this.generatorConfig);
			}
		},
		
		didChangeGeneratorSelection: function()
		{
			var generatorIndex = this.generatorSelect.selectedIndex - 1;
			var selectedGenerator = generatorIndex !== -1 ? this.generators[generatorIndex] : null;
			
			if (selectedGenerator !== this.selectedGenerator) {
				this.selectedGenerator = selectedGenerator;
				
				var configPath = (selectedGenerator || {}).configPath;
				var configValues = (selectedGenerator || {}).config;
				
				this.generatorConfig.innerHTML = '';
				
				if (selectedGenerator) {
					bridge.send('fetchConfigMarkup', { name: selectedGenerator.name }, function(response) {
						
						if (response && response.data) {
							var form = mixinSettings.generatorConfig;
							mixinSettings.generatorConfig.innerHTML = response.data || '';
							
							utils.applyValuesToForm(mixinSettings.generatorConfig, configValues);
							
							// Evaluate scripts
							var scripts = mixinSettings.generatorConfig.querySelectorAll('script');
							
							for (var i = 0; i < scripts.length; i++) {
								var script = scripts[i];
								script.parentNode.removeChild(script);									
								
								try { eval(script.innerText); } catch(e) {};
							}
						}
					});
				}
			}
			
			return true;
		},
		
		save: function()
		{
			var data = null;
			
			if (this.selectedGenerator) {
				data = {};
				data.generator = this.selectedGenerator.name;
				data.config = utils.formToDictValue(this.generatorConfig) || {};
				
				this.selectedGenerator.config = data.config;
			}
			
			bridge.send('assignGenerator', data);
		}
	};
	
	// Initialize
	projectSettings.init();
	mixinSettings.init();
})();