/**************************************************************
	Script		: ModalWindow
	Version		: 1.0
	Authors		: Pieter Soudan
	Desc		: a ModalWindow Class for controlling framed overlay content.
	Licence		: property of Red & Ivory
**************************************************************/

var ModalWindow = new Class({

    options: {
        container: $('body'),
        frameSize: 24,
        name: 'dialog',
        debug: $('debugbox'),
        backClr: '#fff',
        backOpacity: 0.8,
        startPos: {'x':0, 'y':0},
        startSize: {'w':150, 'h':150},
        onShow: Class.empty,
        onHide: Class.empty,
        onStateChanged: Class.empty,
        center: false,
        overlay: false,
        anim: true,
        focus: true,
        detach: true,
        useoverlay: false
    },
    
    initialize: function(options){
        this.setOptions(options);
        
        this.debugbox = this.options.debug;
        this.debugmode = false;
        
        this.imageDivs = [];
        this.states = [];
        this.activeState = 'bogus';
        
        this.states['bogus'] = {
            'width': 0,
            'height': 0,
            'left': 0,
            'top': 0,
            'detach': !(this.options.detach),
            'center': !(this.options.center),
            'overlay': !(this.options.overlay),
            'anim': !(this.options.anim),
            'focus': !(this.options.focus)
        };
        
        this.states['start'] = {
            'width': this.options.startSize.w,
            'height': this.options.startSize.h,
            'left': this.options.startPos.x,
            'top': this.options.startPos.y,
            'detach': this.options.detach,
            'center': this.options.center,
            'overlay': this.options.overlay,
            'anim': this.options.anim,
            'focus': this.options.focus
        };
        
        this.marginX = 0;
        this.marginY = 0;
        
	this.ff = false;
        
        //create overlay + container;
        this.options.container.setStyle('z-index', 9997);
        if(this.options.useoverlay){
            this.overlay = $('overlay');
            if(!this.overlay){
                this.overlay = new Element('div', {'id': 'overlay'});
                this.overlay.setStyle('position', 'absolute');
                this.overlay.setStyle('top',0);
                this.overlay.setStyle('left',0);
                this.overlay.setStyle('width', window.getWidth().toInt());
                this.overlay.setStyle('height', window.getScrollHeight().toInt());
                this.overlay.setStyle('z-index', 9998);
                this.overlay.setStyle('background-color', this.options.backClr);
                this.overlay.setStyle('cursor', 'pointer');
                this.overlay.setStyle('visibility', 'hidden');
                this.overlay.setOpacity(0);
                this.debug('overlay created for '+this.options.name);
                this.overlay.injectInside(this.options.container);
            }
        }
        
        if(window.getScrollHeight() <= window.getHeight()) {
            this.marginX = 8;
            this.debug('srolling detected');
        }
       
        //create layers and hide them
        this.frame = new Element('div', {'id': this.options.name, 'class': 'frame'});
            this.frame.setStyle('z-index', 9999);    
            //this.frame.setOpacity(0.9);
        
	this.innerFrame = new Element('div', {'class': 'innerFrame'});
        
        this.tl = new Element('div', {'class': 'tl t l fixPNG'});
            this.tl.injectInside(this.innerFrame);	
            this.imageDivs.push(this.tl);
        
        this.tc = new Element('div', {'class': 'tc t c fixPNG'});
            this.tc.injectInside(this.innerFrame);
            this.imageDivs.push(this.tc);
        
        this.tr = new Element('div', {'class': 'tr t r fixPNG'});
            this.tr.injectInside(this.innerFrame);
            this.imageDivs.push(this.tr);
        
        this.ml = new Element('div', {'class': 'ml m l fixPNG'});
            this.ml.injectInside(this.innerFrame);
            this.imageDivs.push(this.ml);
       
        this.content = new Element('div', {'class': 'mc m c fixPNG'});
            this.content.injectInside(this.innerFrame);
            this.content.setStyle('overflow', 'hidden');
            this.imageDivs.push(this.content);
        
        this.mr = new Element('div', {'class': 'mr m r fixPNG'});
            this.mr.injectInside(this.innerFrame);
            this.imageDivs.push(this.mr);
        
        this.bl = new Element('div', {'class': 'bl b l fixPNG'});
            this.bl.injectInside(this.innerFrame);
            this.imageDivs.push(this.bl);
        
        this.bc = new Element('div', {'class': 'bc b c fixPNG'});
            this.bc.injectInside(this.innerFrame);
            this.imageDivs.push(this.bc);
        
        this.br = new Element('div', {'class': 'br b r fixPNG'});
            this.br.injectInside(this.innerFrame);
            this.imageDivs.push(this.br);
        
        this.imageDivs.push(this.frame);
        if(this.overlay) this.imageDivs.push(this.overlay);
        
        this.innerFrame.injectInside(this.frame);
        
        this.frame.injectInside(this.options.container);
        
        //create all animation objects
        this.moveFx = new Fx.Morph(this.frame, {wait: false, duration: 400, transition: Fx.Transitions.Cubic.easeOut});
        this.stateFx = new Fx.Elements(this.imageDivs, {wait: false, duration: 400, transition: Fx.Transitions.Cubic.easeOut});	
            this.stateFx.ref = this;
            
        this.addEvent('onStateChanged', this.setState.bind(this));
        
        this.changeState('start', false);
    },
            
    changeState: function(state, anim){
        if(this.states[this.activeState].detach != this.states[state].detach){
            if(!this.states[state].detach){
                window.removeEvents('resize');
                window.removeEvents('scroll');
            }
        }
        if(this.states[this.activeState].focus != this.states[state].focus){
            if(!this.states[state].focus) {
                this.defocus();
                this.frame.removeEvents('mouseenter');
                this.frame.removeEvents('mouseleave');
            }
        }
        if(anim) this.stateFx.start(this.getStyles(this.states[state])).chain(function(){this.ref.fireEvent('onStateChanged', state)});
        else {
            this.stateFx.set(this.getStyles(this.states[state]));
            this.fireEvent('onStateChanged', state);
        }
    },
    
    setState: function(state){
        if(this.states[this.activeState].detach != this.states[state].detach){
            if(this.states[state].detach){
                window.addEvents({
                    'resize': this.resize.bindWithEvent(this),
                    'scroll': this.scroll.bindWithEvent(this)
                });
            }
        }
        if(this.states[state].detach) this.scroll();
        if(this.overlay && this.states[this.activeState].overlay != this.states[state].overlay){
            if(!this.states[state].overlay){
                this.overlay.setStyle('visibility', 'hidden');
            }
        }
        if(this.states[this.activeState].focus != this.states[state].focus){
            if(this.states[state].focus){
                this.frame.addEvent('mouseenter', this.focus.bindWithEvent(this));
                this.frame.addEvent('mouseleave', this.defocus.bindWithEvent(this));
            }
        }
        this.debug('state changed: '+state);
        this.activeState = state;
    },
    
    getStyles: function(state){
        //1. size dimensions
        var ow = {
            '1': {'width': state.width - 2*this.options.frameSize},
            '2': {'left': state.width - this.options.frameSize},
            '3': {'height': state.height - 2*this.options.frameSize},
            '4': {'width':state.width - 2*this.options.frameSize, 'height':state.height - 2*this.options.frameSize},
            '5': {'height': state.height - 2*this.options.frameSize, 'left': state.width - this.options.frameSize},
            '6': {'top': state.height - this.options.frameSize},
            '7': {'width':state.width - 2*this.options.frameSize,'top': state.height - this.options.frameSize},
            '8': {'top': state.height - this.options.frameSize, 'left': state.width - this.options.frameSize}
        };
        //2. position
        if(state.center){
            ow['9'] = {
                'left': Math.round((window.getWidth()-state.width)/2),
                'top': Math.round((window.getHeight()-state.height)/2 + this.marginY)
            }
        } else {
            ow['9'] = {
                /*
                'left': Math.round(state.left - ((this.states[this.activeState].width - state.width)/2)),
                'top': Math.round(state.top - ((this.states[this.activeState].height - state.height)/2))
                */
                'left': state.left,
                'top': state.top
            }
        }
        //3. overlay
        if(this.overlay && this.states[this.activeState].overlay != state.overlay){
                ow['10'] = {
                    'opacity' : state.overlay?this.options.backOpacity:0
                }
                this.debug('overlay activates for state'+this.options.name);
        }
        this.debug(ow['9'].left);
        return ow;
    },
    
    scroll: function(e){
        if(e){
            var event = new Event(e).stop();
        }
        this.slide.delay(300,this);
    },
    
    resize: function(e){
        
    },
    
    slide: function(){
        var o = {'top':(window.getHeight()-(this.states[this.activeState].height))/2 + window.getScrollTop().toInt()};
        this.moveFx.start(o);
    },
    
    center: function(){
        this.frame.setStyle('left', (window.getWidth()-this.frame.getStyle('width').toInt())/2);
        this.frame.setStyle('top', (window.getHeight()-this.frame.getStyle('height').toInt())/2);
    },
    
    setContent: function(el, copy){
        if(copy){
	    this.ff = new Element('div');
	    this.ff.innerHTML = el.innerHTML;
            this.ff.injectInside(this.content);
	    
            el.setStyle('visibility', 'hidden');
        } else {
            $(el).injectInside(this.content);
            $(el).setStyle('display', 'block');
        }
    },
    
    focus:function(){
        this.frame.addClass('focus');
    },
    defocus:function(){
        this.frame.removeClass('focus');
    },
    
    debug: function(msg){
        if(this.debugmode) this.debugbox.setHTML(this.debugbox.innerHTML + '<br/>' + msg);
        //dbug.log(msg);
    },
    setOpacity: function(amt){
        this.frame.setOpacity(amt);
    }
});

ModalWindow.implement(new Options, new Events);
