// create namespace
Core.createNamespace('nl.code.lightbox');

/**
 * Lightbox Class
 */
nl.code.lightbox.Lightbox = new Class({
    /**
     * @implements Options
     */
    Implements: Options,

    /**
     * @var int
     */
    id: null,

    /**
     * @var Object
     */
    options: {
        css_class: '',
        overlay_opacity: 0.4,
        overlay_color: '#000000',
        show_loading: true,
        animation_class: null,
        autostart_animation: false,
        autostart_animation_width: 0,
        autostart_animation_height: 0
    },

    /**
     * @var Boolean
     */
    visible: false,

    /**
     * @var Element
     */
    container: null,

    /**
     * @var Element
     */
    overlay: null,

    /**
     * @var Element
     */
    canvas: null,

    /**
     * @var Element
     */
    content: null,

    /**
     * @var LightboxAnimation
     */
    animation: null,

    /**
     * @var Object, {width, height, content, trigger}
     */
    data: null,

    /**
     * @var array
     */
    selectbox_arr: null,

    /**
     * Constructor
     *
     * @param int, the identifier
     * @param Object, the options
     */
    initialize: function(id, options) {
        this.id = id;
        this.setOptions(options);

        // get the containers
        this.container = this.getContainer();
        this.overlay   = this.container.getElement('div.js-lightbox-overlay');
        this.canvas    = this.container.getElement('div.js-lightbox-canvas');
        this.content   = this.container.getElement('div.js-lightbox-content-wrapper');

        // check if there is an animation
        if (this.options.animation_class) {
            try {
                var animation_class = this.options.animation_class;
                this.animation = new animation_class(this, this.options);
            } catch (e) {
                this.animation = null;
            }
        }

        // add events
        this.addEvents();
    },

    /**
     * Add a resize event to the window object and add a click event to the overlay to close the lightbox
     *
     * @return void
     */
    addEvents: function() {
        var thisObject = this;

        this.overlay.addEvent('click', function(event) {
            event.stop();

            thisObject.hide();
        });

        var current_height = 0;
        var current_width  = 0;
        window.addEvent('resize', function() {
            // if the dimensions of the window are changed then call the lightboxes resize method
            if (current_height != window.getSize().y || current_width != window.getSize().x) {
                thisObject.setSize();
            }

            current_height = window.getSize().y;
            current_width  = window.getSize().x;
        });
    },

    /**
     * @param integer
     * @return void
     */
    setZIndex: function(zIndex) {
        this.container.setStyle('z-index', zIndex);
    },

    /**
     * Preload the lightbox
     *
     * @param Object, {width, height, content, trigger}
     * @return void
     */
    preload: function(data) {
        data = $merge({css_class: this.options.css_class}, data);

        if (this.canvas.getSize().x && this.options.show_loading) {
            this.content.set('html', '<div class="js-loading"></div>');
        }

        if (data.content) {
            var thisObject = this;
            var preloader = new nl.code.lightbox.Preloader(data, {
                onPreloadComplete: function(data) {
                    thisObject.show(data);
                }
            });
        }
    },

    /**
     * Show the lightbox
     *
     * @param Object, {width, height, content, trigger}
     * @return void
     */
    show: function(data) {
        if (!data.width || !data.height) {
            this.preload(data);

            return;
        }

        // store the data
        this.data = data;

        // set additional css class
        if (this.options.css_class) {
            this.container.addClass(this.options.css_class);
        }

        if (this.animation) {
            this.animation.show(this.data);
        } else {
            this.setContent();
            this.setSize();
            this.setOptionStyles();
            this.showContent();
        }

        // ie 6 selectbox fix
        this.hideSelectboxes();
    },

    /**
     * @return void
     */
    hideSelectboxes: function() {
        if (Browser.Engine.trident4 || (Browser.Engine.gecko && Browser.Platform.mac)) {
            var selectbox_arr = this.getSelectboxes();
            selectbox_arr.setStyle('visibility', 'hidden');
        }
    },

    /**
     * @return void
     */
    showSelectboxes: function() {
        if (Browser.Engine.trident4 || (Browser.Engine.gecko && Browser.Platform.mac)) {
            var selectbox_arr = this.getSelectboxes();
            selectbox_arr.setStyle('visibility', 'visible');
        }
    },

    /**
     * @return array
     */
    getSelectboxes: function() {
        if (!this.selectbox_arr) {
            this.selectbox_arr = document.id(document.body).getElements('select');
        }

        return this.selectbox_arr;
    },

    /**
     * @return void
     */
    setOptionStyles: function() {
        if (this.options.overlay_color) {
            this.overlay.setStyle('background-color', this.options.overlay_color);imdb
        }
        if (this.options.overlay_opacity) {
            this.overlay.setStyle('opacity', this.options.overlay_opacity);
        }
    },

    /**
     * Show the content
     *
     * @return void
     */
    showContent: function() {
        if (!this.overlay.getStyle('opacity')) {
            this.overlay.setStyles({
                backgroundColor: 'transparent',
                opacity: 1
            });
        }

        this.content.setStyle('display', 'block');
        this.container.setStyle('display', 'block');
        this.visible = true;
    },

    /**
     * Set the content of the lightbox
     *
     * @param string
     * @return void
     */
    setContent: function() {
        this.content.set('html', this.data.content);

        var thisObject = this;
        var anchor_arr = this.container.getElements('a[rel=close]');
        for (var i = 0; i < anchor_arr.length; i++) {
            anchor_arr[i].addEvent('click', function(event) {
                event.stop();

                nl.code.lightbox.Lightboxer.hideLightbox(thisObject.id);
            });
        }

        var form_arr = this.container.getElements('form');
        for (var i = 0; i < form_arr.length; i++) {
            form_arr[i].addEvent('submit', function(event) {
                event.stop();

                nl.code.pager.PageData.request(this.get('action'), nl.code.lightbox.Lightboxer, this, this);
            });
        }

        nl.code.lightbox.Lightboxer.pager.scanContent(this.content);
    },

    /**
     * Remove the content of the lightbox
     *
     * @return void
     */
    hideContent: function() {
        this.visible = false;
        this.content.empty();
        this.content.setStyle('display', 'none');
        this.container.setStyle('display', 'none');
    },

    /**
     * @param JSON
     * @return void
     */
    setSize: function() {
        var width  = this.canvas.getSize().x;
        if (this.data && this.data.width) {
            width = this.data.width;
        }
        var height = this.canvas.getSize().y;
        if (this.data && this.data.height) {
            height = this.data.height;
        }

        this.overlay.setStyles({
            width: nl.code.lightbox.Lightboxer.calculateWindowWidth(width),
            height: nl.code.lightbox.Lightboxer.calculateWindowHeight(height)
        });

        this.canvas.setStyles({
            width: width,
            height: height,
            left: nl.code.lightbox.Lightboxer.calculateCanvasXPosition(width),
            top: nl.code.lightbox.Lightboxer.calculateCanvasYPosition(height)
        });
    },

    /**
     * Hide the lightbox
     *
     * @return void
     */
    hide: function() {
        if (this.animation && this.animation.animating) {
            return;
        }

        if (this.animation !== null) {
            this.animation.hide();
        } else {
            this.hideContent();
        }

        // ie 6 selectbox fix
        this.showSelectboxes();
    },

    /**
     * Get the container for the lightbox
     *
     * @return Element
     */
    getContainer: function() {
        var container = document.id('js-lightbox');

        // if no container in the document create one
        if (! container) {
            container = this.renderContainer();
        }

        // clone the html, in this way another lightbox can use the same html
        return container.clone().inject(document.id(document.body));
    },

    /**
     * Render the lightbox container
     *
     * @return Element
     */
    renderContainer: function() {
        var container = new Element('div', {'class': 'js-lightbox', 'id': 'js-lightbox'});
        var overlay = new Element('div', {'class': 'js-lightbox-overlay'});

        // use a canvas element, in this way you can animate the lightbox without showing the content
        var canvas = new Element('div', {'class': 'js-lightbox-canvas'});
        var content = new Element('div', {'class': 'js-lightbox-content-wrapper'});

        container.inject(document.id(document.body));
        overlay.inject(container);
        canvas.inject(container);
        content.inject(canvas);

        return container;
    }
});