// ==UserScript==
// @name          4chan 404 Defeater
// @namespace     http://spacetaken.net/44d/
// @description   Provides a refresh feature that warns you of awaiting 404, inc. auto-refresh, compatible with 4chan extension
// @include       http://*.4chan.org/*/res/*
// ==/UserScript==

//use the unsafe window for lots of stuff because it is far simpler that way

getFragment = function(fullURL){
	return fullURL.substring(fullURL.lastIndexOf('#')+1);
}

getDocumentPath = function(){
	var loc = window.location.href;
	var ind = loc.indexOf(window.location.host);
	return removeFragment(loc.substring(ind+window.location.host.length));	
}

removeFragment = function(fullURL){
	var ind = fullURL.lastIndexOf("#");
	return (ind == -1) ? fullURL : fullURL.substring(0, ind);		
}

window.writeCookie = function(name, value){
	document.cookie = name+"="+value+";; path="+getDocumentPath();
}

window.readCookie = function(name, defaultValue){
	var sc = document.cookie.split(";");
	for(var i=0; i<sc.length; i++){
		var cur = sc[i];
		if(cur.indexOf(name) != -1){
			return cur.substring(cur.indexOf(name)+name.length+1);
		}
	}
	return defaultValue;
}

unsafeWindow.doF5 = function(){						
	//only allow one regular-check at once
	if(checkingF5 && !doingSafeSubmit)
		return false;
	var xhr = new XMLHttpRequest();
	xhr.onreadystatechange = function(){
		if(xhr.readyState == 4){
			var is404d = false;			
			try{
				document.getElementById("f5_progress").style.display = "none";
				if(doingSafeSubmit){
					if(xhr.status == "404")
						is404d = true;
					else
						document.forms[0].submit();
				}
				else if(xhr.status == "200"){
					window.location.reload();
				}
				else if(xhr.status == "404"){
					is404d = true;
					clearInterval(autoF5TimerId);
				}
				//else probably 304 Not Modified
			}catch(e){}
			if(is404d)
				document.getElementById("control_f5_section").innerHTML = "<span style=\"font-size: 20pt; color: red; margin: 8px;\">404</span>";
			checkingF5 = false;	
			doingSafeSubmit = false;
		}
	}
	try{
		xhr.open("HEAD", removeFragment(window.location.href), true);
		xhr.setRequestHeader("If-Modified-Since", new Date(document.lastModified).toUTCString());
		xhr.send(null);
		checkingF5 = true;
		document.getElementById("f5_progress").style.display = "block";
	}catch(e){}
	return false;
}


unsafeWindow.updateAutoF5 = function(){
	var checked = document.getElementById("auto_f5_checker").checked;
	//stop or start auto f5ing
	if(checked)
		autoF5TimerId = setInterval('doF5()', 1000*60*autoF5Rate);
	else
		clearInterval(autoF5TimerId);
}

unsafeWindow.doSafeSubmit = function(){
	if(!doingSafeSubmit){
		doingSafeSubmit = true;
		unsafeWindow.doF5();
	}
}

unsafeWindow.validateRate = function(){
	var field = document.getElementById("ref_rate_mins");
	autoF5Rate = parseFloat(field.value);
	if(isNaN(autoF5Rate)) autoF5Rate = 1;
	else if(autoF5Rate < 0.1) autoF5Rate = 0.1;
	field.value = autoF5Rate;		//update to possibly different-to-inputted value 
	if(document.getElementById("auto_f5_checker").checked){
		clearInterval(autoF5TimerId);
		autoF5TimerId = setInterval("doF5()", Math.round(1000*60*autoF5Rate));
	}
}

window.saveCookies = function(){
	writeCookie("44d_scroll_pos", document.body.scrollTop);
	if(document.getElementById("auto_f5_checker")){
		writeCookie("44d_f5_rate", autoF5Rate);	
		writeCookie("44d_auto_f5", document.getElementById("auto_f5_checker").checked);
	}
}


//dont show on 404 etc pages
if(document.getElementById("navtop")){
	
	var doingSafeSubmit = false;
	var checkingF5 = false;
	var dateGot = new Date().toUTCString();
	var autoF5TimerId;
	
	var autoF5 = readCookie("44d_auto_f5", false);
	var autoF5Rate = readCookie("44d_f5_rate", 2);
	var scrollPos = readCookie("44d_scroll_pos", 0);
	
	//setup control
	window.controlNode = document.createElement('div');
	document.body.appendChild(controlNode);
	controlNode.setAttribute("class", "doubledash");
	controlNode.style.position = "fixed";
	controlNode.style.right = "10px";
	controlNode.style.top = "45%";
	controlNode.style.border = "1px solid";
	controlNode.style.textAlign = "center";
	var ih = "<a href=\"#\" onclick=\"document.body.scrollTop=0; return false;\" style=\"text-decoration: none; color: black;\" title=\"top\">==</a>";
	ih += "<div id=\"control_f5_section\">"
	ih += "<div><a href=\"#\" onclick=\"doF5(); return false;\" style=\"font-size: 20pt; color: black; margin: 8px; outline: none; text-decoration: none;\">F5</a></div>"
	ih += "<div id=\"f5_progress\" style=\"display: none; font-size: 20pt; color: black; margin-top: -20px;\">...</div>";
	ih += "<input type=\"checkbox\" id=\"auto_f5_checker\" onclick=\"updateAutoF5()\" style=\"vertical-align: middle\" "+ (autoF5=="true" ? "checked=\"yes\"" : "") + "><label for=\"auto_f5_checker\">Auto</label>";
	ih += "<br><label>\/Mins.</label><br><input type=\"text\" id=\"ref_rate_mins\" onchange=\"validateRate();\" value=\""+autoF5Rate+"\" size=\"2\" style=\"vertical-align: middle\">";
	ih += "</div>"
	ih += "<a href=\"#\" onclick=\"document.body.scrollTop=999999; return false;\" style=\"text-decoration: none; color: black;\" title=\"bottom\">==</a>";
	window.controlNode.innerHTML = ih;
	
	document.body.scrollTop = scrollPos;
	unsafeWindow.updateAutoF5();
	
	//replace submit button with one that checks for 404
	var nodes = document.evaluate("//input[@type='submit' and @accesskey='s']", document, null,	XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
	var submitButton = nodes.snapshotItem(0);
	var safeSubmitButton = document.createElement("input");
	safeSubmitButton.setAttribute("type", "button");
	safeSubmitButton.setAttribute("value", "Submit");
	safeSubmitButton.setAttribute("onclick", "doSafeSubmit()");
	submitButton.parentNode.replaceChild(safeSubmitButton, submitButton);		
	
	//save scroll position when doing regular f5 too
	window.addEventListener("unload", saveCookies, true);
}