/**
 * highlight canvas element by fading out background
 */
var Overlay = new Class({
    Implements: Options,
    
    options: {
        opacity: 0.8,        // target overlay background opacity
        duration: 200,       // overlay background fade time
        color: "#000",       // overlay background color
        onClick: null,       // function to call when clicking background (null=default:hide(), use $empty() to ignore)
        onEscape: null       // function to call when pressing escape (null=default:hide(), use $empty() to ignore)
    },
    
    /**
     * initialize overlay
     * 
     * @param Element canvas canvas element to highlight
     * @param Object  options optional options object
     */
    initialize: function(canvas,options){
        if(!$defined(options)){
            options = {};
        }
        if(!$defined(options.onClick)){
            options.onClick = this.hide;
        }
        if(!$defined(options.onEscape)){
            options.onEscape = this.hide;
        }
        this.setOptions(options);
        
        this.onClick  = options.onClick;
        this.onEscape = options.onEscape;
        
        this.active     = false;
        this.busy       = false;
        this.compatible = (Browser.Engine.trident4 ? true : false); // MSIE6 needs some special care (as always...)
        
        this.background = new Element("div").setStyles({
            "opacity":          0,
            "visibility":       "visible",
            "overflow":         "hidden",
            "position":         (this.compatible ? "absolute" : "fixed"),
            "background-color": this.options.color,
            "top":              "0px",
            "left":             "0px",
            "width":            (this.compatible ? window.getWidth() : "100%"),
            "height":           "100%",
            "z-index":          900
        }).set("tween",{duration:this.options.duration,link:"cancel"});
        
        this.canvas = $(canvas).setStyles({
            "position": "absolute",
            "z-index":  999
        }).addClass("canvas");
        
        // bind overlay background click event
        if($defined(this.onClick) && this.onClick != $empty){
            this.background.setStyle("cursor","pointer").addEvent("click",function(){
                if(this.active){ this.onClick(); }
            }.bindWithEvent(this));
        }
        
        // bind escape key
        if($defined(this.onEscape) && this.onEscape != $empty){
            $(window.document).addEvent("keydown",function(event){
                if(event.key == "esc" && this.active){ this.onEscape(); }
            }.bindWithEvent(this));
        }
        
        // background onComplete
        this.background.get("tween").addEvent("onComplete",function(){
            this.busy = false;
            if(this.background.getStyle("opacity") == this.options.opacity){ 
                //
            } else if(this.background.getStyle("opacity") == 0) {
                this.background.dispose();
            };
        }.bindWithEvent(this));
        
        // reset position onResize
        window.addEvent("resize",function(){
            if(this.active || this.busy){ this.position(); }
        }.bindWithEvent(this));
    },
    
    /**
     * adjust position of canvas (and fix overlay background when in compatibility mode)
     * 
     * @return Overlay
     */
    position: function(){
        var scroll = $(window).getScroll();
        var size   = $(window).getSize();
        
        this.canvas.setStyles({
            "left": Math.max(/*scroll.x +*/ (size.x / 2) -(this.canvas.getSize().x / 2),0),
            "top": Math.max(/*scroll.y +*/ (size.y / 2) - (this.canvas.getSize().y / 2),0)
        });
        if(this.compatible){
            this.background.setStyles({left: scroll.x, top: scroll.y, width: size.x, height: size.y});
        }
        return this;
    },
    
    /**
     * event called when clicking on background
     */
    onClick: null,
    
    /**
     * event called when hitting escape key
     */
    onEscape: null,
    
    /**
     * show overlay
     * 
     * @return Overlay
     */
    show: function(){
        if(!this.active){
            this.active = true;
            this.busy   = true;
            
            this.background.inject($(document.body)).tween("opacity",this.options.opacity);
            this.canvas.inject($(document.body));
            this.position();
        }
        return this;
    },
    
    /**
     * hide overlay
     * 
     * @return Overlay
     */
    hide: function(){
        if(this.active){
            this.active = false;
            this.busy   = true;
            
            this.canvas.dispose();
            this.background.tween("opacity",0); // onComplete: dispose
        }        
        return this;
    }
});

/**
 * special overlay requiring user interaction
 */
Overlay.Question = new Class({
    Extends: Overlay,
    
    options: {
        classname: "question",
        title:     "Question",
        onAnswer:  function(value,overlay){ overlay.hide(); },
        answers:   {"1":"Ok","0":"Cancel"}
    },
   
    /**
     * initialize error overlay and display
     * 
     * @param string message error message
     * @param Object options optional options object
     */
    initialize: function(message,options){
        this.setOptions(options);
        
        this.onAnswer = this.options.onAnswer;
        delete this.options.onAnswer;
        
        // escape and click will issue onAnswer(null)
        this.options.onClick = this.options.onEscape = function(){
            this.onAnswer(null,this);
        };
        
        if($defined(Setting) && !Setting.get("overlay",true)){
            if($H(this.options.answers).getLength() == 1){
                alert(this.options.title+":\n"+message);
                this.onAnswer("1",this);
                return;
            }else if($H(this.options.answers).getLength() == 2){
                if(confirm(this.options.title+":\n"+message)){
                    this.onAnswer("1",this);
                }else{
                    this.onAnswer("0",this);
                }
                return;
            }
        }
        
        var buttons = new Element("div",{
            "class": "buttons"
        });
        
        $each(this.options.answers,function(label,value){
            new Element("button",{
                "text": label           // "value":value will set the label for IE, duh :>
            }).addEvent("click",function(event,value){
                this.onAnswer(value,this);
            }.bindWithEvent(this,value)).inject(buttons);
        }.bind(this));
        
        var canvas = new Element("div",{
            "class": this.options.classname
        }).grab(new Element("h1",{
            text: this.options.title
        })).grab(new Element("p",{
            text: message
        })).grab(buttons);
        
        this.parent(canvas,this.options);
        this.show();
        
        buttons.getFirst().focus();
    },
    
    /**
     * event called when hitting button (value = object key)
     * 
     * @param string   value    object key
     * @param Overview overview this overview object
     */
    onAnswer: function(value,overview){
        overview.hide();
    }
});

/**
 * special error overlay
 */
Overlay.Error = new Class({
    Extends: Overlay.Question,
    
    options: {
        classname: "error",
        title:     "Error",
        button:    "Ok"
    },
   
    /**
     * initialize error overlay and display
     * 
     * @param string message error message
     * @param Object options optional options object
     */
    initialize: function(message,options){ 
        this.setOptions(options);
        this.options.answers = { "1":this.options.button };        
        
        this.parent(message,this.options);
    }
});

/**
 * special confirmation overlay (ok and cancel button)
 */
Overlay.Confirm = new Class({
    Extends: Overlay.Question,
    
    options: {
        classname:    "confirm",
        title:        "Confirmation required",
        buttonOk:     "Ok",
        buttonCancel: "Cancel"
    },
    
    /**
     * initialize confirmation overlay and display
     * 
     * @param string message confirmation message
     * @param Object options optional options object
     */
    initialize: function(message,options){
        this.setOptions(options);
        this.options.answers = { "1":this.options.buttonOk, "0":this.options.buttonCancel };
        
        this.parent(message,this.options);
    }
});
