$(function() {

function partial_oplop(label) {
    /* Return a partial function application of oplop(). */
    return function(password) {
        return oplop(label, password);
    };
}


function nextSection($node) {
    /* Return the section next to the one enclosing the passed-in node. */
    return $node.parents("section").next();
}


function activateNext($node) {
    /* Activate the next section. */
    var h2 = nextSection($node).children("h2");
    $("#accordion").accordion('activate', h2);
}


function onEnter(fxn) {
    /* Event handler that executes the function when Enter is pressed and
       activates the next section. */
    return function(evt) {
        if (evt.which == 13) {  // \r
            var focus = fxn(evt);
            activateNext($(evt.target));
            if (focus) {
                $(focus).focus();  // Passing back a callback didn't work
            }
            return false;
        }
        else {
            return true;
        }
    };
}


function bindLabel() {
    /* Set up the event bindings for the label field. */
    function handle(evt) {
        var $label = $(evt.target);
        var label_value = $label.val();
        var partial = partial_oplop(label_value);

        $label.val("");
        return bindMasterPassword(partial);
    }

    $("#label").keydown(onEnter(handle));
}


function bindMasterPassword(partial) {
    /* Set up the event bindings for the master_password field. */
    function handle(evt) {
        var $master = $(evt.target);
        var master_value = $master.val();
        var password = evt.data(master_value);

        $master.val("");
        $("#password").html(password);
    }

    // Only need a single event handler
    $("#master_password").unbind("keydown");
    $("#master_password").bind("keydown", partial, onEnter(handle));
    return "#master_password";
}


function reset() {
    /* Reset the state of the app. */
    $("#password").html("");  // Label & password cleared by reset button
    $("#accordion").accordion('activate', 0);
    // Set focus to first visible text field
    $(":text:visible:first").focus();
}


// Initialize GUI
$("#accordion").accordion({header: "h2", animated:false, event: false});
// Clear out any pre-existing state and starting over
$(":reset").click(reset);
// Set initial bindings
bindLabel();
reset();

$("form").css("visibility", "visible");
/* Can't rely on reset() to make the first text box selected as it is called
   before the form is made visible which blocks the focus setting. */
$(":text:visible:first").focus();

});
