//Version 0.0, April 10, 2006, (c) jason howald (jason.howald@gmail.com)
//License: GNU General Public License (http://www.gnu.org/copyleft/gpl.html)


//****************************************//
//             taskInterface              //
//****************************************//

function taskInterface(T) {
    this.task = T;
}

taskInterface.smallInputLength = 20;
taskInterface.largeInputLength = 40;

taskInterface.prototype.node = function(str){
    return document.createElement("div");
}

taskInterface.prototype.create = function() {
    //It's safe to call "create" twice, and not even very inefficient.
    if (this.span == undefined) {
        var gui = this;
        this.gui = gui;
        
        this.span = document.createElement("span");
        this.span.className = "gui_task";

        this.key = document.createElement("span");
        this.key.className = "gui_key";
        this.keyName = document.createElement("span");
        this.keyName.className = "gui_keyname";
        this.keyName.appendChild(document.createTextNode(this.task.label));
        this.key.appendChild(this.keyName);
        this.key.open = false;
        addEvent(this.key,"click",function() {
            if (this.open) {
                gui.subwindow.style.display = "none";
                this.open = false;
            } else {
                gui.subwindow.style.display = "block";
                this.open = true;
            }
        });
        this.span.appendChild(this.key);
        
        this.keyPretty = document.createElement("span");
        this.keyPretty.className = "gui_prettybox";
        this.key.appendChild(this.keyPretty);

        this.subwindow = document.createElement("div");
        this.subwindow.className = "gui_subwindow";
        this.span.appendChild(this.subwindow);

        this.task.plan();//sadly, we have to plan it just to gets its title!
        this.createTitleBox();
        this.subwindow.appendChild(this.titleBox);
        
        this.closeWindow = document.createElement("img");
        this.closeWindow.className = "gui_closewindow";
        this.closeWindow.src = "xmark.gif";
        this.closeWindow.width = 16;
        this.closeWindow.height = 16;
        addEvent(this.closeWindow,"click",function() {
            gui.subwindow.style.display = "none";
            gui.key.open = false;
        });
        this.subwindow.appendChild(this.closeWindow);

        this.controls = document.createElement("div");
        this.controls.className = "gui_controls";
        this.subwindow.appendChild(this.controls);        

        this.solveButton = document.createElement("div");
        this.solveButton.gui = this;
        this.solveButton.state = "solve";
        this.solveText = document.createElement("img");
        this.solveText.src = "compute.gif";
        this.solveText.width = 16;
        this.solveText.height = 16;
        this.solveButton.className = "gui_solveButton";
        this.solveButton.appendChild(this.solveText);
        addEvent(this.solveButton,"click",this.clickSolve);
        this.controls.appendChild(this.solveButton);


        this.helpButton = document.createElement("div");
        this.helpButton.gui = this;
        this.helpButton.state = "help";
        this.helpText = document.createElement("img");
        this.helpText.src = "help.gif";
        this.helpButton.className = "gui_helpButton";
        this.helpButton.appendChild(this.helpText);
        addEvent(this.helpButton,"click",this.clickHelp);
        this.controls.appendChild(this.helpButton);
        
        this.equations = document.createElement("div");
        this.equations.className = "gui_equations";
        this.subwindow.appendChild(this.equations);


        this.input = document.createElement("input");
        this.input.gui = this;
        this.input.className = "gui_input";
        this.input.setAttribute("type","text");
        this.input.setAttribute("size",taskInterface.smallInputLength);
        //addEvent(this.input,"keypress",this.catchReturn);//fails in ie
        addEvent(this.input,"focus",this.beginEdit);
        addEvent(this.input,"blur",this.endEdit);
        this.equations.appendChild(this.input);
        
        this.prettyBox = document.createElement("span");
        this.prettyBox.className = "gui_prettybox";
        this.equations.appendChild(this.prettyBox);

        this.status = document.createElement("img");
        this.status.Correct = "checkmark.gif";
        this.status.Unknown = "questionmark.gif";
        this.status.Incorrect = "xmark.gif";
        this.status.src = this.status.Incorrect;
        this.status.className = "gui_status";
        this.status.style.display = "none";
        this.equations.appendChild(this.status);

        this.helpBlock = document.createElement("div");
        this.helpBlock.className = "gui_help";
        this.subwindow.appendChild(this.helpBlock);

        if (this.nothingButHelp) {
            this.solveButton.style.display = "none";
            this.equations.style.display = "none";
            this.clickHelp();
        }

    }
    this.update();
    return this.span;
}

taskInterface.prototype.catchReturn = function(event) {
    if(typeof event!='undefined'){
        var pressedkey=event.keyCode;
    }else{
        var pressedkey=e.keyCode;
    }
    if(pressedkey==13){
        this.gui.endEdit();
    }
//    alert("caught");
    return false;
}

taskInterface.prototype.onlyHelp = function() {
    this.nothingButHelp = true;
}

taskInterface.prototype.beginEdit = function() {
    var gui = this.gui;
    gui.input.setAttribute("size",taskInterface.largeInputLength);
    //gui.helpButton.style.display = 'none';
    //gui.solveButton.style.display = 'none';
}

taskInterface.prototype.endEdit = function() {
    var gui = this.gui;
    if (gui.input.value == "") {return false;}
    var entry = expression.newFromAscii(gui.input.value);
    if (!(entry.meta.badSyntax)) {
        gui.addPretty(entry,gui.status.Incorrect);
    }
    var correct = gui.task.solve();
    if (entry.semanticEquiv(correct)) {
        gui.acceptSolution(entry);
    } else {
        gui.solveButton.state = "solve";
        gui.status.src = gui.status.Incorrect;
        gui.status.style.display = "";
    }
    gui.input.setAttribute("size",taskInterface.smallInputLength);
    //gui.helpButton.style.display = '';
    //gui.solveButton.style.display = '';
    return false; //prevent form submission
}

taskInterface.prototype.acceptSolution = function(exp) {
    var gui = this;
    gui.solveButton.state = "clear";
    gui.addPretty(exp,gui.status.Correct);
    gui.status.src = gui.status.Correct;
    gui.status.style.display = "";
    gui.task.revealed = true;
}

taskInterface.prototype.clickSolve = function() {
    var gui = this.gui;
    if (gui.solveButton.state.match(/solve/i)) {
        gui.solveButton.state = "clear";//do first.  I worry about update() callbacks.
        var solution = gui.task.solve();//in ie, this can be a task.  :(

        //alert(ALLPROPERTIES(solution));
        //alert("<<"+typeof(solution)+">>");
        gui.input.value = solution.toStringAscii();
        gui.acceptSolution(solution);
    } else {
        gui.solveButton.state = "solve";
        gui.input.value = "";
        gui.noPretty();
        gui.task.unSolve();
        gui.status.src = gui.status.Incorrect;
        gui.status.style.display = "none";
    }
}

taskInterface.prototype.clickHelp = function() {
    var gui = this.gui;
    if (gui.helpButton.state.match(/^help$/i)) {
        gui.task.plan();
        gui.removeHelpBox();//just in case.  
        gui.createHelpBox();
        gui.helpBlock.appendChild(gui.helpBox);
        gui.helpButton.state = "unhelp";
    } else {
        gui.helpBlock.removeChild(gui.helpBox);
        gui.helpButton.state = "help";
    }

}

taskInterface.prototype.update = function() {
    //It's safe to call "update" if it's not yet "created," but
    //it WON'T create itself as a side effect of updating.
    var task = this.task;
    if (this.span != undefined) {
        if ((task.solved)&&(task.revealed)&&(this.solveButton.state.match(/solve/))) {
            //Someone else revealed us.  pretend user clicked solve.
            this.clickSolve();
        } else if (((!task.solved)||(!task.revealed))&&(this.solveButton.state.match(/clear/))) {
            //Someone else unsolved us.
            this.clickSolve();
        } 
        if ((!task.planned)&&(this.helpButton.state.match(/unhelp/i))) {
            alert("state issues");
            //someone unplanned us.
            this.clickHelp();
        }             
    }
}

taskInterface.prototype.createHelpBox = function() {
    var hsteps = this.task.showList;
    this.helpBox = document.createElement("div");
    if (this.nothingButHelp) {
        this.helpBox.className = "gui_helpbox_unbordered";
    } else {
        this.helpBox.className = "gui_helpbox";
    }
    for (var i in hsteps) {
        if (typeof(hsteps[i]) == "string") {
            //passed a string, DOMify and add to helpbox
            var help = document.createElement("span");
            help.className = "gui_instruction";
            help.appendChild(document.createTextNode(hsteps[i]+ " "));
            this.helpBox.appendChild(help);
        } else if (hsteps[i].tagName !== undefined) {
            //passed a DOM element.  Drop it in.
            //clone it just in case it's inserted twice.
            this.helpBox.appendChild(hsteps[i].clone());
        } else if (hsteps[i].pretty !== undefined) {
            this.helpBox.appendChild(hsteps[i].pretty());
        } else {
            //passed a task.  Append its gui.
            //alert(hsteps[i]);
            this.helpBox.appendChild(hsteps[i].gui.create());
        }
    }
}

taskInterface.prototype.createTitleBox = function() {
    var tsteps = this.task.titleList;
    this.titleBox = document.createElement("div");
    if (this.nothingButHelp) {
        //this.titleBox.className = "gui_titleBox_unbordered";
    } else {
        //this.titleBox.className = "gui_titleBox";
    }
    for (var i in tsteps) {
        if (typeof(tsteps[i]) == "string") {
            //passed a string, DOMify and add to titleBox
            var title = document.createElement("span");
            title.className = "gui_tasktitle";
            title.appendChild(document.createTextNode(tsteps[i]+ " "));
            this.titleBox.appendChild(title);
        } else if (tsteps[i].tagName !== undefined) {
            //passed a DOM element.  Drop it in.
            //clone it just in case it's inserted twice.
            this.titleBox.appendChild(tsteps[i].clone());
        } else if (tsteps[i].pretty !== undefined) {
            this.titleBox.appendChild(tsteps[i].pretty());
        } else if (tsteps[i].method !== undefined) {
            //passed a task.  Append its *solution*.
            //alert("other " + tsteps[i].label + " " + typeof(tsteps[i]) + " " + tsteps[i].__proto__);
            this.titleBox.appendChild(tsteps[i].solve().pretty());
        } //OTHER THINGS ARE PASSED, and I can't figure out why.  :(
    }
}


taskInterface.prototype.removeHelpBox = function() {
    for (var i=0; i<this.helpBlock.childNodes.length; i++){
        this.helpBlock.removeChild(this.helpBlock.firstChild);
    }
}


taskInterface.prototype.addPretty = function(exp,sourceimage) {
    this.noPretty();
    this.pretty = exp.pretty();
    this.pretty2 = exp.pretty();
    this.prettyBox.appendChild(this.pretty);
    this.keyPretty.appendChild(document.createTextNode("(="));
    this.keyPretty.appendChild(this.pretty2);
    var pic = document.createElement("img");
    pic.src = sourceimage;
    pic.width = 16;
    pic.height = 16;
	this.keyPretty.appendChild(pic);
    this.keyPretty.appendChild(document.createTextNode(")"));
}

taskInterface.prototype.noPretty = function() {
    this.disownAll(this.keyPretty);
    this.disownAll(this.prettyBox);
    
    //while(this.keyPretty.firstChild !== undefined) {
    //    this.keyPretty.removeChild(this.keyPretty.firstChild);
    //}        
    //for (var i=0; i<this.keyPretty.childNodes.length; i++){
    //    this.keyPretty.removeChild(this.keyPretty.firstChild);
    //}
    //for (var i=0; i<this.prettyBox.childNodes.length; i++){
    //    this.prettyBox.removeChild(this.prettyBox.firstChild);
   // }
}

taskInterface.prototype.disownAll = function(parent){
    while(parent.hasChildNodes()){
        parent.removeChild(parent.childNodes[0])
    }
}
