// Complete implementation of client side for bibleverses web app.

// On page load, need to set up 'Register' and 'Login' buttons etc

var rootUrl = "/bibleverses/";
var cgiRoot = rootUrl + "cgi-bin/main.cgi/";

var verselist = [];

function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
	var c = ca[i];
	while (c.charAt(0)==' ') { c = c.substring(1,c.length); }
	if (c.indexOf(nameEQ) === 0) { return c.substring(nameEQ.length,c.length); }
    }
    return null;
}

function setCookie(name, value, days) {
    var expires;
    if (days) {
	var date = new Date();
	date.setTime(date.getTime()+(days*24*60*60*1000));
	expires = "; expires="+date.toGMTString();
    } else {
	expires = "";
    }
    document.cookie = name+"="+value+expires + "; path=" + rootUrl ;
}

function eraseCookie(name) {
    setCookie(name, "", -1);
}

function encodeObj(obj) {
    var ks = keys(obj);
    var val = "";
    for (var i = 0; i < ks.length; i++) {
	val = val + ks[i] + "=" + encodeURIComponent(obj[ks[i]]) + "&";
    }
    return val;
}

function doPostRequest(method, data) {
    var encoded = encodeObj(data);
    logDebug("Data to send: " + encoded);
    var d = doXHR(cgiRoot + method + "/",
	  {
	      method: 'POST',
	      sendContent: encoded,
	      headers: {
                  "Content-Type": "application/x-www-form-urlencoded"
              }
	  });
    return d;
}

function doGetRequest(method) {
    var d = doXHR(cgiRoot + method + "/",
	{
	    method: 'GET'
	});
    return d;
}

function standardErrorHandler(err) {
    logError(err);
}

function setLoginCookie(email, password) {
    // Security is very low (just put password in cookie).
    // But the data being protected has minimal security requirements.
    setCookie("email", email, 100000);
    setCookie("password", password, 100000);
}

function pageNeedsVerseList() {
    return (getElementsByTagAndClassName("span", "verseadmin").length > 0);
}

function makeVerseRef(verse) {
    return verse.replace(/ |,|:|-/g, "_");
}

function get_email() {
    var email = readCookie('email');
    if (email === null) {
	return null;
    } else {
	return decodeURIComponent(email);
    }
}

function makePasswordHash(email, password) {
    return SHA1(email + password);
}

function resetRegisterBlock() {
    $('id_reg_email').value = '';
    $('id_reg_password').value = '';
    hideElement($('regresultfail'));
    hideElement($('regresultok'));
    showElement($('regbuttonsdiv'));
    hideElement($('regclosediv'));
}

function resetLoginBlock() {
    $('id_login_email').value = '';
    $('id_login_password').value = '';
    hideElement($('loginresultfail'));
    hideElement($('loginresultok'));
    showElement($('loginbuttonsdiv'));
    hideElement($('loginclosediv'));
}

function center_block(block) {
    setElementDimensions(block, {'w': 30}, "em");
    showElement(block); // before getElementDimensions(b) or it won't work
    var vp_dim = getViewportDimensions();
    var vp_pos = getViewportPosition();
    var b_dim = getElementDimensions(block);
    var newpos = {x: (vp_dim.w - b_dim.w)/2, y:vp_pos.y + 20};
    setElementPosition(block, newpos);
}

function onRegister1(ev) {
    hideElement($('loginblock'));
    resetRegisterBlock();

    center_block($('registerblock'));
}

function onLogin1(ev) {
    hideElement($('registerblock'));
    resetLoginBlock();

    center_block($('loginblock'));
}

function onCancelReg(ev) {
    hideElement($('registerblock'));
}

function onCancelLogin(ev) {
    hideElement($('loginblock'));
}

function onCloseReg(ev) {
    hideElement($('registerblock'));
}

function onCloseLogin(ev) {
    hideElement($('loginblock'));
}

function showUserBar(bar) {
    // easiest way to get layout correct is to relatively
    // position these elements
    var navbar_dim = getElementDimensions($('navbarcont'));
    showElement(bar);
    bar.style.top = (-navbar_dim.h + 5).toString() + "px";
    bar.style.right = "4px";
}

function addUserBar1() {
    hideElement($('userbar2'));
    showUserBar($('userbar1'));
}

function addUserBar2(email) {
    replaceChildNodes($('username'), email);
    hideElement($('userbar1'));
    showUserBar($('userbar2'));
}

function setCheckBoxDisplay(state) {
    // Would be much nicer to do this using a stylesheet rule
    var vadmins = getElementsByTagAndClassName("span", "verseadmin");
    for (var i = 0; i < vadmins.length; i++) {
	vadmins[i].style.display = state;
    }
}

function showCheckBoxes() {
    setCheckBoxDisplay('inline');
}

function hideCheckBoxes() {
    setCheckBoxDisplay('none');
    var elems = getElementsByTagAndClassName("li", "memorised");
    for (var i = 0; i < elems.length; i++) {
	removeElementClass(elems[i], "memorised");
    }
}

function updateControls() {
    var email = get_email();
    if (email !== null && email !== '') {
	addUserBar2(email);
	showCheckBoxes();
    } else {
	addUserBar1();
	hideCheckBoxes();
    }
}

function doLogout() {
    eraseCookie('email');
    eraseCookie('password');
    updateControls();
}

function onLogout(ev) {
    doLogout();
}

function indicateFinishedVerse(verse) {
    var refid = makeVerseRef(verse);
    var elem = $('id_verseli_' + refid);
    if (elem) {
	addElementClass(elem, "memorised");
	$('id_versecb_' + refid).checked = true;
	removeElementClass($('id_verseli_' + refid), "manuallyshown");
    }
}

function indicateFinishedVerses() {
    for (var i = 0; i < verselist.length; i++) {
	indicateFinishedVerse(verselist[i]);
    }
}

function indicateUnfinishedVerse(verse) {
    var refid = makeVerseRef(verse);
    var elem = $('id_verseli_' + refid);
    if (elem) {
	var hidden_div = getFirstElementByTagAndClassName("div", "versebottom", elem);
	removeElementClass(elem, "memorised");
	$('id_versecb_' + refid).checked = false;
	removeElementClass($('id_verseli_' + refid), "manuallyhidden");
    }
}

function verseListArrived(req) {
    var json = evalJSONRequest(req);
    logDebug(req.responseText);
    if (json.success) {
	verselist = json.verselist;
	indicateFinishedVerses();
    } else {
	// login details wrong.
	doLogout();
	// (or, TODO, network error)
    }
}

function loadVerses() {
    var email = get_email();
    if (email !== null && email !== "") {
	if (pageNeedsVerseList()) {
	    var d = doGetRequest("verses");
	    d.addCallbacks(verseListArrived, standardErrorHandler);
	}
    }
}

function doLoggedInSetup(email, password) {
    setLoginCookie(email, password);
    updateControls();
    loadVerses();
}

function registerResult(req) {
    var json = evalJSONRequest(req);
    logDebug(req.responseText);
    if (json.success) {
	showElement($('regresultok'));
	hideElement($('regresultfail'));
	hideElement($('regbuttonsdiv'));
	showElement($('regclosediv'));
	doLoggedInSetup($('id_reg_email').value,
			makePasswordHash($('id_reg_email').value,
					 $('id_reg_password').value));
    } else {
	var fail = $('regresultfail');
	if (json.validation) {
	    logDebug("Validation: " + repr(json.validation));
	    replaceChildNodes(fail, json.validation[1]);
	} else {
	    replaceChildNodes(fail, "An error occurred: " + json.error);
	}
	showElement(fail);
    }
}

function loginResult(req) {
    var json = evalJSONRequest(req);
    logDebug(req.responseText);
    if (json.success) {
	showElement($('loginresultok'));
	hideElement($('loginresultfail'));
	hideElement($('loginbuttonsdiv'));
	showElement($('loginclosediv'));
	doLoggedInSetup($('id_login_email').value,
			makePasswordHash($('id_login_email').value,
					 $('id_login_password').value));
    } else {
	var fail = $('loginresultfail');
	if (json.validation) {
	    logDebug("Validation: " + repr(json.validation));
	    replaceChildNodes(fail, json.validation[1]);
	} else {
	    replaceChildNodes(fail, "An error occurred: " + json.error);
	}
	showElement(fail);
    }
}

function onRegister2(ev) {
    var d = doPostRequest( "register",
	{'email': $('id_reg_email').value,
	'password': makePasswordHash($('id_reg_email').value,
				     $('id_reg_password').value)
	});
    d.addCallbacks(registerResult, standardErrorHandler);
}

function onLogin2(ev) {
    var d = doPostRequest( "login",
	{'email': $('id_login_email').value,
	'password': makePasswordHash($('id_login_email').value,
				     $('id_login_password').value)
	});
    d.addCallbacks(loginResult, standardErrorHandler);
}

function verseAdded(req) {
    var json = evalJSONRequest(req);
    if (json.success) {
	indicateFinishedVerse(json.verse);
    }
    // TODO - error handling in case json.success != true

}

function addVerse(ref) {
    var d = doPostRequest("addverse", {"verse": ref});
    d.addCallbacks(verseAdded, standardErrorHandler);
}

function verseRemoved(req) {
    var json = evalJSONRequest(req);
    if (json.success) {
	indicateUnfinishedVerse(json.verse);
    }
    // TODO - error handling in case json.success != true
}

function removeVerse(ref) {
    var d = doPostRequest("removeverse", {"verse": ref});
    d.addCallbacks(verseRemoved, standardErrorHandler);
}

function toggleVerseCheckBox(ev) {
    var cb = ev.src();
    // Find the full reference
    var parent = $(cb.id.replace("id_versecb_", "id_verseli_"));
    var ref = getFirstElementByTagAndClassName("a", "biblelink", parent).innerHTML;
    if (cb.checked) {
	addVerse(ref);
	verselist.push(ref);
    } else {
	removeVerse(ref);
    }
}

function manuallyShow(item) {
    removeElementClass(item, "manuallyhidden");
    addElementClass(item, "manuallyshown");
}

function manuallyHide(item) {
    addElementClass(item, "manuallyhidden");
    removeElementClass(item, "manuallyshown");
}

function showBtnClicked(ev) {
    var refid = ev.src().id.replace("id_show_","");
    manuallyShow($("id_verseli_" + refid));
}

function hideBtnClicked(ev) {
    var refid = ev.src().id.replace("id_hide_","");
    manuallyHide($("id_verseli_" + refid));
}

function connectCheckBoxes() {
    var vbtns = getElementsByTagAndClassName("span", "versebtns");
    var cb, show, hide;
    for (var i = 0; i < vbtns.length; i++) {
	cb = getFirstElementByTagAndClassName("input", "versecb", vbtns[i]);
	connect(cb, 'onclick', toggleVerseCheckBox);
	show = getFirstElementByTagAndClassName("span", "showbtn", vbtns[i]);
	connect(show, 'onclick', showBtnClicked);
	hide = getFirstElementByTagAndClassName("span", "hidebtn", vbtns[i]);
	connect(hide, 'onclick', hideBtnClicked);
    }
}

connect(window, 'onload',
        function(ev) {
	    connectCheckBoxes();
	    updateControls();
	    connect($('register1'), 'onclick', onRegister1);
	    connect($('register2'), 'onclick', onRegister2);
	    connect($('cancelreg'), 'onclick', onCancelReg);
	    connect($('closereg'), 'onclick', onCloseReg);
	    connect($('login1'), 'onclick', onLogin1);
	    connect($('login2'), 'onclick', onLogin2);
	    connect($('cancellogin'), 'onclick', onCancelLogin);
	    connect($('closelogin'), 'onclick', onCloseLogin);
	    connect($('logout'), 'onclick', onLogout);
	    loadVerses();
        }
       );


