window.onload = function () {
	$('#subcategory').prop('disabled', true);
	$('#category').change(function() {
		fillSubcategory(this.value)
	});
	
	customizeUploadButton()
}

function sortCategories(categories) {
	var sortedCategories = []
	for(var key in categories) {
		sortedCategories.push(categories[key])
	}
	sortedCategories.sort()
	return sortedCategories
}

function fillDetectedFilelist(file) {
	var reader = new FileReader();
	fileList = document.querySelectorAll(".detectedFiles")[0]
	fileList.querySelector(".label").innerHTML = ""
	fileList.querySelector(".content").innerHTML = ""
	reader.onload = function() {
		autodetectSuccess = false
		b = new bencode()
		try {
			torrentObject = b.decode(reader.result)
		} catch(err) {
		
		}

		if(torrentObject.info.name) {
			document.querySelectorAll("input.name")[0].value = torrentObject.info.name
		}

		sizeGroup = document.querySelectorAll(".sizeGroup")[0]
		if(torrentObject.info.pieces.length && torrentObject.info["piece length"]) {
			sizeGroup.style.display = ""
			size = (torrentObject.info.pieces.length / 20) * torrentObject.info["piece length"]
			size = getNextUnit(size)
			document.querySelectorAll(".detectedSize")[0].innerHTML = ((Math.round(size[0] * 100)) / 100) + " " + size[1]
			autodetectSuccess = true
		} else {
			sizeGroup.style.display = "none"
		}

		trackerGroup = document.querySelectorAll(".trackerGroup")[0]
		if(torrentObject.announce) {
			trackerGroup.style.display = ""
			document.querySelectorAll(".detectedTracker")[0].innerHTML = torrentObject.announce
			autodetectSuccess = true
		} else {
			trackerGroup.style.display = "none"
		}

		filesGroup = document.querySelectorAll(".filesGroup")[0]
		if(torrentObject["info"]["files"] != undefined && torrentObject["info"]["files"].length > 0) {
			// render the file-tree if multiple files are present
			autodetectSuccess = true
			for(var fileIndex = 0; fileIndex < torrentObject.info.files.length; fileIndex++){
				path = torrentObject["info"]["files"][fileIndex]["path"]
				renderFile(getRoot(), path.reverse())
			}
		} else {
			// assume the torrent is only one file named "name"
			autodetectSuccess = true
			renderFile(getRoot(), [torrentObject["info"]["name"]])
		}

		var detectInfosGroup = document.querySelectorAll(".detectedInfosGroup")[0]
		if(autodetectSuccess) {
			detectInfosGroup.style.display = "block"
		} else {
			detectInfosGroup.style.display = "none"
		}
	}
	reader.readAsArrayBuffer(file)
}

function renderFile(root, path) {
	if(path.length == 0){
		return 0
	} else {
		nextElement = path.pop()
		folderName = ""
		for(var i = 0; i < nextElement.length; i++) {
			code = nextElement.charCodeAt(i)
			if((code >= 97 && code <= 122) || (code >= 65 && code <= 90)) {
				folderName = folderName + nextElement[i]
			}
		}
		type = path.length > 0 ? "dir" : "file"
		newRoot = getOrCreate(root, folderName, nextElement, type)
		renderFile(newRoot, path)
	}
}

function getOrCreate(root, foldername, displayname, type) {
	var obj = root.querySelector("div." + type + "." + foldername)

	if(obj == undefined || obj.length == 0){
		element = document.createElement("div")
		element.classList.add(type)
		element.classList.add(foldername)
		label = document.createElement("div")
		label.classList.add("label")
		label.innerHTML = displayname
		element.appendChild(label)

		if(type == "dir") {
			label.classList.add("closed")
			label.onclick = function() {
				if(this.classList.contains("closed")) {
					this.classList.remove("closed")
					this.classList.add("opened")
				} else if(this.classList.contains("opened")) {
					this.classList.remove("opened")
					this.classList.add("closed")
				}
				content = this.parentElement.querySelector(".content")
				content.hidden = !content.hidden
			}
			content = document.createElement("div")
			content.classList.add("content")
			content.hidden = true
			element.appendChild(content)
		}
		root = root.querySelector(".content")
		root.appendChild(element)
		return element
	} else {
		return obj
	}
}

function getRoot() {
	rootElement = document.querySelectorAll(".detectedFiles.fileRoot")[0]
	return rootElement
}

function fillSubcategory(value) {
	var subSelect = $('#subcategory')
	var selText = $(':first-child', subSelect).text()
	subSelect.empty();
	subSelect.append($('<option value="-1" selected>'+selText+'</selected>'))
	if (value >= 0) {
		var subcategories = null
		for(var i = 0; i < global_categories.length; i++) {
			if (global_categories[i]["id"] == value) {
				subcategories = global_categories[i]["subcategories"]
				break
			}
		}
		if(subcategories) {
			for(subcategoryIndex in subcategories) {
				var subcategoryId = subcategories[subcategoryIndex]["id"]
				var subcategoryLocalString = subcategories[subcategoryIndex]["label"]
				var node = $('<option value="'+subcategoryId+'">'+subcategoryLocalString+'</string>')
				subSelect.append(node)
			}
		}
	}
	subSelect.prop('disabled', value < 0)
}

// Hides the default browser-upload-form and replaces it by an button
function customizeUploadButton() {
	$("input.file").before('<button id="button-file" type="button" class="btn btn-default"><span class="text">Upload...</span><span class="glyphicon glyphicon-open-file" aria-hidden="true"></span></button>');
	$("input.file").hide();
	$('body').on('click', '#button-file', function() {
			$("input.file").trigger('click');
	});
}

// This sets the Uploadbutton to the filename of the uploaded file
function setButtonToFilename(event) {
	$("input[name='torrentFile']").each(function() {
		var fileName = $(this).val().split('/').pop().split('\\').pop();
		targetInput = event["target"]
		button = targetInput.previousSibling.getElementsByClassName("text")[0]
		button.innerHTML = chunk(fileName, 40)
		fillDetectedFilelist(this.files[0])
	});
}

function setError(element) {
	element.classList.add("has-error")
	element.classList.remove("has-success")
}

function setSuccess(element) {
	element.classList.add("has-success")
	element.classList.remove("has-error")
}

function validateForm() {
	valid = true

	/* TODO: Iterate over these to do dynamic requirement checking
	form_groups = document.querySelectorAll(".torrent-form .form-group.required")
	required_inputs = document.querySelectorAll(".torrent-form input.required")
	required_dropdown = document.querySelectorAll(".torrent-form select.dropdown.required")
	required_textarea = document.querySelectorAll(".torrent-form textarea.required")
	*/

	file = document.querySelector(".torrent-form .file input")
	category = document.querySelector("#category")
	subcategory = document.querySelector("#subcategory")
	torrentname = document.querySelector(".torrent-form .name input")
	description = document.querySelector(".torrent-form .description textarea")
	tracker = document.querySelector(".trackerGroup .detectedTracker").parentElement

	file_label = document.querySelector(".torrent-form .file")
	category_label = document.querySelector(".torrent-form .category")
	name_label =  document.querySelector(".torrent-form .name")
	description_label = document.querySelector(".torrent-form .description")

	if(validtracker.indexOf(torrentObject.announce) < 0) {
		valid = false
		setError(tracker)
	} else {
		setSuccess(tracker)
	}

	if(file.value.length <= 0) {
		valid = false
		setError(file_label)
	} else {
		setSuccess(file_label)
	}

	if(category.value < 0) {
		valid = false
		setError(category_label)
	} else {
		setSuccess(category_label)
	}

	if(subcategory.value < 0) {
		valid = false
		setError(category_label)
	} else {
		setSuccess(category_label)
	}

	if(torrentname.value.length <= 0) {
		valid = false
		setError(name_label)
	} else {
		setSuccess(name_label)
	}

	if(description.value.length <= 0) {
		valid = false
		setError(description_label)
	} else {
		setSuccess(description_label)
	}

	return valid;
}

function chunk(string, n) {
	var ret = "";
	for(var i=0, len=string.length; i < len; i += n) {
		if(i==0) {
			ret = string.substr(i, n)
		} else {
			ret += "<br/>" + string.substr(i, n)
		}
	}
	return ret
};


// Bencode Library 
// Copyright 2014 Steven Goodwin
// Released under the GPL, version 2

// For format details, please see:
// http://en.wikipedia.org/wiki/Bencode

bencode = function() {
	this.STATE_NULL = 0;
	this.STATE_INTEGER = 1;				// i-?[0-9]e
	this.STATE_STRING_LENGTH = 2;		// [0-9]+:\a+
	this.STATE_STRING_CONTENT = 3;		// [0-9]+:\a+
	this.STATE_LIST = 4;				// l<contents>e
	this.STATE_DICTIONARY = 5;			// d<contents>e
}

// Parse accepts an array of characters to process, and the index of the
// first character to parse.
// It returns an object containing the parsed result (in result.o), and the index
// of the next character to parse in result.idx
bencode.prototype.parse = function(dataArray, fromIndex) {
	var length = dataArray.byteLength;
	var idx = fromIndex;
	var state = this.STATE_NULL;

	// State data
	var current = "";
	var currentObject = null;;
	// String-specific state data
	var stringLength;
	
	while(idx < length) {
		var c = String.fromCharCode(dataArray[idx]) ;
		
		switch(state) {
			case this.STATE_NULL:
					switch(c) {
						case 'i':
								state = this.STATE_INTEGER;
								current = "";
								break;
						case '0':
						case '1':
						case '2':
						case '3':
						case '4':
						case '5':
						case '6':
						case '7':
						case '8':
						case '9':
								state = this.STATE_STRING_LENGTH;
								current = c;
								break;
						case 'l':
								currentObject = new Array();
								state = this.STATE_LIST;
								break;
								
						case 'd':
								currentObject = new Object();
								state = this.STATE_DICTIONARY;
								break;

						default:
								return null;
						}
					//
					++idx;
					break;
					
			case this.STATE_INTEGER:	
					switch(c) {
						case '-':	// we assume that negative numbers start with -
								current = "-";
								break;
						case 'e':
								return { o : current, idx : idx+1 };
						case '0':
						case '1':
						case '2':
						case '3':
						case '4':
						case '5':
						case '6':
						case '7':
						case '8':
						case '9':
								current += c;
								break;
					}
					++idx;
					break;
					
			case this.STATE_STRING_LENGTH:	
					switch(c) {
						case ':':	// the separator between length and content
								stringLength = parseInt(current, 10);
								state = this.STATE_STRING_CONTENT;
								current = "";		// We now parse the string content
								break;
						case '0':
						case '1':
						case '2':
						case '3':
						case '4':
						case '5':
						case '6':
						case '7':
						case '8':
						case '9':
								current += c;
								break;
						default:
								return null;
						
					}
					++idx;
					break;
					
				case this.STATE_STRING_CONTENT:
					current += c;
					if (--stringLength == 0) {
						return { o : current, idx : idx+1 };
					}

					++idx;
					break;
											
				case this.STATE_DICTIONARY:
					
					if (c == 'e') {
						return { o : currentObject, idx : idx+1 };
					} else {
						var objKey = this.parse(dataArray, idx);
						var objValue = this.parse(dataArray, objKey.idx);
						
						currentObject[objKey.o] = objValue.o;
						idx = objValue.idx;
					}
					break;
					
				case this.STATE_LIST:
					
					if (c == 'e') {
						return { o : currentObject, idx : idx+1 };
					} else {
						var obj = this.parse(dataArray, idx);
						
						currentObject.push(obj.o);
						idx = obj.idx;
					}
					break;
				
		}
	}
	
	return null;
}

bencode.prototype.decode = function(byteArray) {
	var dataArray = new Uint8Array(byteArray);
	var result = this.parse(dataArray, 0);
	
	return result.o;
}