/*
 * Copyright (c) 2007 Collactive. All rights reserved.
 */

if (typeof(Collactive) == 'undefined') {
	Collactive = {};
}

// The form helping wizard
Collactive.Wizard = function(ui) {
    Collactive.addBindMethod(this);

	this._ui = ui;
    this.steps = [];
    this.currentIndex = 0;
    this.finishCallback = null;


    // Adds a wizard step
    //  - text: wizard text to show
    //  - show: the element(s) to show
    //  - focus: the element(s) to focus (default: same as 'show')
    //  - trapKeys: the element(s) to trap enter/tab on (default: same as 'focus')
    this.addStep = function(text, show, focus, trapKeys) {
        if (focus == null) {
            focus = show;
        }
        if (trapKeys == null) {
            trapKeys = focus;
        }
        this.steps[this.steps.length] = {
            show: show,
            focus: focus,
            trapKeys: trapKeys,
            text: text
        };
    };


    // Sets the callback called when the user completes
    this.setFinishCallback = function(cb) {
        this.finishCallback = cb;
    },


    // Starts the wizard
    this.start = function() {
        this.createStyleSheet();
        this.createElements();
        this.showWizard();
    }


    // Stops the wizard, hides the instruction window
    this.stop = function() {
        this.wizardDiv.style.display = "none";
        Collactive.Effects.visiblizeElements();
    },


    // Shows the wizard on the current step
    this.showWizard = function() {
        if (this.currentIndex >= this.steps.length) {
            return;
        }

        var step = this.steps[this.currentIndex];

        this.showInstructions(step.show, step.text);

        Collactive.Effects.hideAllExcept(step.show);

        // TODO: make this happen only if the yellow box is over this
        Collactive.Effects.invisiblizeElements("embed", this.messageBox);
        Collactive.Effects.invisiblizeElements("object", this.messageBox);
        if (navigator.appName.indexOf("Microsoft") != -1) {
            Collactive.Effects.invisiblizeElements("select", this.messageBox);
        }

        var event = (navigator.appName.indexOf("Microsoft") != -1) ? "keydown" : "keypress";
        if (step.trapKeys) {
            if (step.trapKeys.length > 0) {
                for (var i in step.trapKeys) {
                    var one = step.trapKeys[i];
                    Collactive.DomUtils.registerListener(one, event,
                                                         this.bind(this.keyHandler), null);
                }
            }
            Collactive.DomUtils.registerListener(step.trapKeys, event,
                                                 this.bind(this.keyHandler), null);
        }

        if (step.focus) {
            step.focus.focus();
        }

    };


    // Add the wizard's stylesheet
    this.createStyleSheet = function() {
        var styleSheet = [];
        styleSheet[styleSheet.length] = ".collactive_wizard {";
        styleSheet[styleSheet.length] = "  position: absolute;";
        styleSheet[styleSheet.length] = "  background-image: url(" + this._ui.getImageUrl("small_dialog.gif") + ");";
        styleSheet[styleSheet.length] = "  font-size: 12px;";
        styleSheet[styleSheet.length] = "  font-weight: bold;";
        styleSheet[styleSheet.length] = "  z-index: 99999;";
        styleSheet[styleSheet.length] = "  visibility: hidden;";
        styleSheet[styleSheet.length] = "  width: 264px;";
        styleSheet[styleSheet.length] = "  height: 142px;";
        styleSheet[styleSheet.length] = "}";
        styleSheet[styleSheet.length] = "";
        styleSheet[styleSheet.length] = ".collactive_wizard_instructions {";
        styleSheet[styleSheet.length] = "  position: absolute;";
        styleSheet[styleSheet.length] = "  top: 45px;";
        styleSheet[styleSheet.length] = "  left: 62px;";
        styleSheet[styleSheet.length] = "  font-weight: normal;";
        styleSheet[styleSheet.length] = "  font-family: Arial;";
        styleSheet[styleSheet.length] = "  font-size: 12px;";
        styleSheet[styleSheet.length] = "  color: #042a56;";
        styleSheet[styleSheet.length] = "  width: 190px;";
        styleSheet[styleSheet.length] = "  height: 60px;";
        styleSheet[styleSheet.length] = "}";
        styleSheet[styleSheet.length] = ".collactive_wizard_instructions td {";
        styleSheet[styleSheet.length] = "  font-weight: normal;";
        styleSheet[styleSheet.length] = "  font-family: Arial;";
        styleSheet[styleSheet.length] = "  font-size: 12px;";
        styleSheet[styleSheet.length] = "  color: #042a56;";
        styleSheet[styleSheet.length] = "}";
        styleSheet[styleSheet.length] = "";
        styleSheet[styleSheet.length] = ".collactive_wizard_buttondiv {";
        styleSheet[styleSheet.length] = "  position: absolute;";
        styleSheet[styleSheet.length] = "  bottom: 10px;";
        styleSheet[styleSheet.length] = "  left: 62px;";
        styleSheet[styleSheet.length] = "  text-align: center;";
        styleSheet[styleSheet.length] = "  width: 190px;";
        styleSheet[styleSheet.length] = "}";
        styleSheet[styleSheet.length] = ".collactive_wizard_title {";
        styleSheet[styleSheet.length] = "  position: absolute;";
        styleSheet[styleSheet.length] = "  top: 4px;";
        styleSheet[styleSheet.length] = "  left: 130px;";
        styleSheet[styleSheet.length] = "  font-weight: bold;";
        styleSheet[styleSheet.length] = "  font-family: Arial;";
        styleSheet[styleSheet.length] = "  font-size: 11px;";
        styleSheet[styleSheet.length] = "  color: #135095;";
        styleSheet[styleSheet.length] = "}";
        styleSheet[styleSheet.length] = "";
        styleSheet[styleSheet.length] = ".collactive_wizard_button {";
        styleSheet[styleSheet.length] = "  padding-left: 4px;";
        styleSheet[styleSheet.length] = "  padding-right: 4px;";
        styleSheet[styleSheet.length] = "  font-family: MS Sans Serif;";
        styleSheet[styleSheet.length] = "  font-weight: normal;";
        styleSheet[styleSheet.length] = "  font-size: 10pt;";
        styleSheet[styleSheet.length] = "}";
        Collactive.DomUtils.addStyleSheet(styleSheet.join(""));
    };

    // Add the wizard's DOM elements
    //<div class="collactive_wizard">
    //    <div class="collactive_wizard_instructions"></div>
    //    <div class="collactive_wizard_buttons">
    //      <input id="wizard_prev" type="button" value="<< Back" onclick="prevWizardStep()">
    //      <input id="wizard_next" type="button" value="Next &gt;&gt;" onclick="nextWizardStep()">
    //    </div>
    //</div>
    this.createElements = function() {
        this.wizardDiv = document.createElement("div");
        this.wizardDiv.className = "collactive_wizard";
        
        this.instructionsDiv = document.createElement("div");
        this.instructionsDiv.className = "collactive_wizard_instructions";
        this.wizardDiv.appendChild(this.instructionsDiv);

        this.titleDiv = document.createElement("div");
        this.titleDiv.className = "collactive_wizard_title";
        this.titleDiv.innerHTML = "Be Active";
        this.wizardDiv.appendChild(this.titleDiv);

        var buttonsDiv = document.createElement("div");
        buttonsDiv.className = "collactive_wizard_buttondiv"
        this.prevButton = document.createElement("input");
        this.prevButton.type = "button";
        this.prevButton.className = "collactive_wizard_button";
        Collactive.DomUtils.registerListener(this.prevButton, "click",
                                             this.bind(this.prevStep));
        // TODO: onclick
        buttonsDiv.appendChild(this.prevButton);
        this.nextButton = document.createElement("input");
        this.nextButton.type = "button";
        this.nextButton.className = "collactive_wizard_button";
        Collactive.DomUtils.registerListener(this.nextButton, "click",
                                             this.bind(this.nextStep));
        // TODO: onclick
        buttonsDiv.appendChild(this.nextButton);

        this.wizardDiv.appendChild(buttonsDiv);
        Collactive.DomUtils.addToBody(this.wizardDiv);
    };


    // Displays the wizard next to an element
    this.showInstructions = function(target, html) {
        this.instructionsDiv.innerHTML = '<table height="100%"><tr><td height="100%" valign="center">' + html + '</td></tr></table>';
        this.wizardDiv.style.visibility = "visible";
        var wizardInfo = Collactive.DomUtils.getElementInfo(this.wizardDiv);
        var targetInfo = Collactive.DomUtils.getElementInfo(target);

        this.wizardDiv.style.position = "absolute";
        var top = (targetInfo.top - wizardInfo.height - Collactive.WIZARD_SPACING);
        this.wizardDiv.style.top = (top > 0 ? top : 0) + "px";

        var center = targetInfo.left + targetInfo.width/2;
        var left = Math.ceil(center - wizardInfo.width/2);
        this.wizardDiv.style.left = (left > 0 ? left : 0) + "px";

        this.prevButton.disabled = (this.currentIndex == 0);

        var isLastStep = (this.currentIndex == (this.steps.length - 1));
        var isOneStep = (this.steps.length == 1);

        if (isOneStep) {
            this.nextButton.value = "OK";
            this.prevButton.style.display = "none";
        } else {
            this.prevButton.value = "<< Back"
            this.nextButton.value = "Next >>";
            if (this.currentIndex == (this.steps.length - 1)) {
                if (this.finishCallback != null) {
                    this.nextButton.value = "Finish!";
                } else {
                    this.nextButton.disabled = (this.currentIndex == (this.steps.length - 1));
                }
            }
        }
    };

    // Called for the "next" / "finish" button in the wizard
    this.nextStep = function() {
        if (this.currentIndex == (this.steps.length - 1)) {
            // This is actually finish!
            if (this.finishCallback != null) {
                this.stop();
                (this.finishCallback)();
            }
            return;
        }
        Collactive.DomUtils.removeAllListeners("keypress");
        this.currentIndex++;
        this.showWizard();
    };


    // Called for the "prev" button in the wizard
    this.prevStep = function() {
        if (this.currentIndex == 0) {
            return;
        }
        Collactive.DomUtils.removeAllListeners("keypress");
        this.currentIndex--;
        this.showWizard();
    };

    // Called to handle keypresses while we're in the wizard
    this.keyHandler = function(e) {
        // TODO: shift-enter in MSIE generates keypress, not keydown. Aargh!
        if (e.keyCode == 13 || e.keyCode == 9) { // Tab, enter
            if (e.shiftKey) {
                this.prevStep();
            } else {
                this.nextStep();
            }
            return false;
        }

        return true;
    };
};
