/**
 * Convienence class that allows both coarse and fine grained controll,
 * to create (modal) and display "windows", thereby providing flexible style themes.
 *
 * @author Thorsten Schmitt-Rink <schmittrink@gmail.com>
 * @copyright
 * @licsense MIT
 * @version 0.6 Beta
 *
 * @todo API Doc!
 */
var Moo_CorporateWindow = new Class({

    Implements: [Options, Events],
    
    options: {
        title: '',
        content: '',
        width: 400,
        height: 275,
        draggable: false,
        modal: true,
        enableShadow: true,
        shadowThickness: 24,
        imageBasePath: '../../../images/products/surfacetags/window/images',
        klass: 'moo_window',
        hideOnModalClick: true,
        confirmClose: false,
        confirmText: '',
        fadeDuration: 200,
        transition: Fx.Transitions.linear,
        position: {
            x: 'center',
            y: 'middle'
        },
        titleBar: {
            klass: 'Moo_window_titlebar',
            closeTitle: ''
        }
    },

    isOpen: false,
    
    overlay: null,
    
    displayHandler: null,
    
    shadowBox: null,

    windowDiv: null,
    
    titleBar: null,

    closeButtons: null,
    
    shadowShapes: null,
    
    initialize: function (options)
    {
        this.setOptions(options);
    },
    
    show: function ()
    {
        if (this.isOpen) return; 
        this.isOpen = true;
        
        if (true === this.options.modal)
        {
            this.getOverlay().inject($(document.body), 'top').setStyle('opacity', '.5');
            //$(document.html).setStyle('overflow', 'hidden');
        }
        /*
            * This crappy piece of browser software won't handle png's correctly, 
            * so there is no fade effect here.
            */
        if ((Browser.Engine.trident && this.options.enableShadow) || 0 === this.options.fadeDuration)
        {
            this.getDisplayHandler().inject($(document.body));
            this.fireEvent('show');
            return;
        }
        
        this.getDisplayHandler().setStyle('opacity', '0').inject($(document.body)).get('tween', {
            'property': 'opacity',
            'duration': this.options.fadeDuration,
            'transition': this.options.fadeTransition
        }).start(1);
        
        this.fireEvent('show');
    },
    
    hide: function ()
    {
        if (!this.isOpen || !this.confirmClose()) return;
        this.isOpen = false;
        
        //$(document.html).setStyle('overflow', 'auto');
        /*
            * This crappy piece of browser software won't handle png's correctly, 
            * so there is no fade effect here.
            */
        if ((Browser.Engine.trident && this.options.enableShadow) || 0 === this.options.fadeDuration)
        {
            this.dispose();
            this.fireEvent('hide');
            return;
        }
        
        this.getOverlay().dispose();
        this.getDisplayHandler().get('tween', {
            'property': 'opacity',
            'duration': this.options.fadeDuration,
            'transition': this.options.fadeTransition,
            'onComplete': this.dispose.bind(this)
        }).start(0);
        
        this.fireEvent('hide');
    },
    
    getOverlay: function()
    {
        return this.overlay || (this.overlay = this.buildOverlay());
    },
    
    getDisplayHandler: function()
    {
        return this.displayHandler ||  (this.displayHandler = (true === this.options.enableShadow) ? this.getShadowBox() : this.getWindowDiv());
    },
    
    getShadowBox: function()
    {
        return this.shadowBox || (this.shadowBox = this.buildShadowBox());
    },
    
    getWindowDiv: function()
    {
        return this.windowDiv || (this.windowDiv = this.buildWindowDiv());
    },
    
    getTitleBar: function()
    {
        return this.titleBar || (this.titleBar = this.buildTitleBar());
    },
    
    getCloseButtons: function()
    {
        return this.closeButtons || (this.closeButtons = this.buildCloseButtons());
    },
    
    buildOverlay: function()
    {
        var overlay = new Element('div', {'class': 'window_overlay'});
        
        if (true === this.options.hideOnModalClick)
        {
            overlay.addEvent('click', this.hide.bind(this));
        }
        return overlay;
    },
    
    buildShadowBox: function()
    {
        var coords = this.getCoordinates(this.options.shadowThickness + 2);
        
        var shadowBox = new Element('div', {
            'class': 'Moo_window_shadowbox',
            'styles': {
                'width': coords.width,
                'height': coords.heigth,
                'overflow': 'hidden',
                'position': 'absolute',
                'top': coords.y,
                'left': coords.x,
                'z-index': 100
            }
        });
        
        $each(Moo_CorporateWindow.ShadowShapes, function(shapeStyle, klassName)
        {
            var bgStyleDef = 'transparent url({IMAGE}) {REPEAT}'.substitute({
                'IMAGE': this.options.imageBasePath + '/' + shapeStyle.image,
                'REPEAT': shapeStyle.repeat
            });
            
            shadowBox.grab(new Element('div', {
                'class': klassName + " " + 'shadow_shape',
                'styles':  $H(this.getShadowShapes()[shapeStyle.shapeType]).extend({
                    'float': 'left',
                    'background': bgStyleDef
                }) 
            } ));
        }.bind(this));
        
        this.getWindowDiv().inject(shadowBox.getElement('div.Moo_window_left'), 'after');
        
        if (true === this.options.draggable)
        {
            new Drag.Move(shadowBox, { handle: this.getTitleBar(), container: $(document.body) } );
        }
        return shadowBox;
    },
    
    buildWindowDiv: function()
    { 
        var element =  new Element('div', { 'class': this.options.klass, 'styles': this.getWindowStyles() } )
        .grab(this.getTitleBar())
        .grab(new Element('div', {
            'class': 'window_contentbox',
            'styles': {
                'margin': 0,
                'padding': 0,
                'width': this.options.width,
                'height': this.options.height - 27
            }
        }));
         
        if ('element' === $type(this.options.content))
        {
            element.getElement('.window_contentbox').grab(this.options.content);
        }
        else
        {
            element.getElement('.window_contentbox').set('html', this.options.content);
        }
        
        if (true === this.options.draggable && false === this.options.enableShadow)
        {
            new Drag.Move(element, { handle: this.getTitleBar(), container: $(document.body) } );
        }
        
        this.fireEvent('create');        
        return element;
    },

    buildTitleBar: function()
    {
        return new Element('div', { 
            'class': 'window_titlebar',
            'events': {
                'mouseenter': this.setCursor.bindWithEvent(this, 'move'),
                'mouseleave': this.setCursor.bindWithEvent(this, 'default')
            }
        })
        .grab(
            new Element('h3', { 'html': this.options.title, 'events': { 
                'mousedown': this.cancelEvent,
                'mouseenter': this.cancelEvent
            }})
        )
        .grab(
            this.getCloseButtons().global
        );
    },

    buildCloseButtons: function ()
    {
        return $H({ 'global': new Element('div', {
            'class': 'window_global_close_box', 
            'events': {
                'mousedown': this.cancelEvent,
                'mouseenter': this.cancelEvent
            }
        })
        .grab(
            new Element('span', { 'html': this.options.closeTitle } )
        )
        .grab(
            new Element('button', {
                'type': 'button',
                'class': 'window_global_close',
                'title': this.options.closeTitle,
                'events': { 
                    'click': this.hide.bind(this),
                    'mouseenter': this.setCursor.bindWithEvent(this, 'pointer'),
                    'mouseleave': this.setCursor.bindWithEvent(this, 'default')
                }
            })
        )});
    },
    
    getCoordinates: function(correctionValue)
    {
        var height = this.options.height + (2 * correctionValue);
        var width = this.options.width + (2 * correctionValue);
        var renderInfo = {
            'width': width,
            'height': height
        };
        
        if ('string' === $type(this.options.position.x))
        {
            renderInfo.x = this.getCoordinatesByString(this.options.position.x, width, height)
        }
        else
        {
            renderInfo.x = this.options.position.x;
        }
        
        if ('string' === $type(this.options.position.y))
        {
            renderInfo.y = this.getCoordinatesByString(this.options.position.y, width, height)
        }
        else
        {
            renderInfo.y = this.options.position.y;
        }
        return renderInfo;
    },
    
    getCoordinatesByString: function(coordString, calcWidth, calcHeight)
    {        
        switch(coordString)
        {
                case 'center':
                return (window.getSize().x - calcWidth) / 2;
                
                case 'right':
                return window.getSize().x - calcWidth;
                
                case 'middle':
                return (window.getSize().y - calcHeight) / 2;
                
                case 'bottom':
                return window.getSize().y - calcHeight;
                
                default:
                return 0;
        }
    },
    
    confirmClose: function()
    {
        if (true === this.options.confirmClose)
        {
            return confirm(this.options.confirmText);
        }
        return true;
    },
    
    cancelEvent: function(event)
    {
        new Event(event).stop();
    },
    
    stopSpaceBar: function(event)
    {
        event = new Event(event);        
        if (event.key === 'space') event.stop();
    },
    
    dispose: function()
    {
        if (true === this.options.modal)
        {
            var size = this.getOverlay().getSize();
            
            if (0 < size.x && 0 < size.y)
            {
                this.getOverlay().dispose();
            }
        }
        this.getDisplayHandler().dispose();
    },
    
    setCursor: function(event, cursor)
    {
        event = new Event(event);
        
        if (this.getTitleBar() === event.target && !this.options.draggable)
        {
            event.stop();
            return;
        }
        event.target.setStyle('cursor',  cursor);
    },
    
    getWindowStyles: function()
    {
        var coords = this.getCoordinates(0);
        
        var styles = {
            'width': coords.width,
            'height': coords.height,
            'float': 'left'
        };
        
        if (false === this.options.enableShadow)
        {
            styles = $H(styles).extend({
                'position': 'absolute',
                'top': coords.y,
                'left': coords.x,
                'z-index': 100
            }).erase('float');
        }        
        return styles;
    },
    
    getShadowShapes: function()
    {
        return this.shadowShapes || (this.shadowShapes = {
            'corner' : {
                'height': this.options.shadowThickness,
                'width': this.options.shadowThickness
            },
            'horizontalRect': {
                'height': this.options.shadowThickness,
                'width':  this.options.width + 2
            },
            'verticalRect': {
                'height': this.options.height + 2,
                'width':  this.options.shadowThickness
            }
        });
    }
});

Moo_CorporateWindow.ShadowShapes = {
    'Moo_window_upper_left' : {'shapeType': 'corner', 'image': 'tl.png', 'repeat': 'no-repeat'},
    'Moo_window_upper': {'shapeType': 'horizontalRect', 'image': 't.png', 'repeat': 'repeat-x'},
    'Moo_window_upper_right' : {'shapeType': 'corner', 'image': 'tr.png', 'repeat': 'no-repeat'},
    'Moo_window_left': {'shapeType':'verticalRect', 'image': 'l.png', 'repeat': 'repeat-y'},
    'Moo_window_right': {'shapeType':'verticalRect', 'image': 'r.png', 'repeat': 'repeat-y'},
    'Moo_window_bottom_left' : {'shapeType': 'corner', 'image': 'bl.png', 'repeat': 'no-repeat'},
    'Moo_window_bottom': {'shapeType': 'horizontalRect', 'image': 'b.png', 'repeat': 'repeat-x'},
    'Moo_window_bottom_right': {'shapeType': 'corner', 'image': 'br.png', 'repeat': 'no-repeat'}
};