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

/**
 * Lightboxer Class
 *
 * @static
 */
nl.code.lightbox.Lightboxer = {
    /**
     * @var Pager, a refrence to this site's pager
     */
    pager: null,

    /**
     * @var boolean, if the lightbox becomes bigger then the visible screen, then make it fit the screen
     */
    fit_screen: false,

    /**
     * @var integer, the depth (z-index) at which the lightboxes are displayed
     */
    zIndex: 800,

    /**
     * @var array
     */
    lightbox_arr: [],

    /**
     * @var array
     */
    visible_lightbox_arr: [],

    /**
     * @var Object
     */
    lightbox_options: {
        ajax: {
        },
        image: {
        },
        gallery: {
        },
        element: {
        }
    },

    /**
     * The Lightboxer has it's own parseLinks method
     * The PageData class does not contain this method because there would be a from of "tight coupling" between Lightboxer and PageData
     * This is a piece of functionality that stands on it's own
     *
     * @param Pager, refrence to this site's pager
     * @param Element, the html element to scan for anchors that refer to a lightbox, defaults to body
     * @param Object, options for the lightbox
     * @return void
     */
    parseLightboxLinks: function(pager, root, lightbox_options) {
        // store the reference to the pager in the static attribute
        nl.code.lightbox.Lightboxer.pager = pager;
        root                              = root || document.id(document.body);
        lightbox_options                  = lightbox_options || {};

        nl.code.lightbox.Lightboxer.lightbox_options = $merge(nl.code.lightbox.Lightboxer.lightbox_options, lightbox_options);

        // get all anchors and loop through them
        var anchor_arr = root.getElements('a');
        var lightbox_re = new RegExp('\-lightbox');
        for (var i = 0; i < anchor_arr.length; i++) {
            // we only need enchors with an rel attribute with a value "image-lightbox" or "ajax-lightbox" or "element-lightbox"
            var rel = anchor_arr[i].get('rel');

            if (!rel || !lightbox_re.test(rel)) {
                continue;
            }

            nl.code.lightbox.Lightboxer.parseLightboxLink(anchor_arr[i], rel, nl.code.lightbox.Lightboxer.lightbox_options);
        }

        nl.code.lightbox.Lightboxer.addEvents();
    },

    /**
     * @return void
     */
    addEvents: function() {
        // if the user presses "ESC" hide the active lightbox
        // document.removeEvents();
        document.addEvent('keydown', function(e) {
            var event = new Event(e);

            if (event.key == 'esc') {
                nl.code.lightbox.Lightboxer.hideLightbox();
            }
        });
    },

    /**
     * @param Element
     * @param Object
     * @return void
     */
    parseLightboxLink: function(anchor, rel, lightbox_options) {
        // remove all already attached onclick events
        anchor.removeEvents('click');

        if (rel == 'image-lightbox') {
            nl.code.lightbox.ImageLightbox.createTrigger(anchor, lightbox_options.image);
        } else if (rel.indexOf('gallery-lightbox') != -1) {
            nl.code.lightbox.GalleryLightbox.createTrigger(anchor, lightbox_options.gallery);
        } else if (rel == 'element-lightbox') {
            var element = document.id(anchor.get('href'));
            if (element) {
                nl.code.lightbox.ElementLightbox.createTrigger(anchor, element, lightbox_options.element);
            }
        } else if (rel == 'ajax-lightbox') {
            nl.code.lightbox.AjaxLightbox.createTrigger(anchor, lightbox_options.ajax);
        }
    },

    /**
     * json request completed
     * called as a result of nl.code.pager.PageData.request
     *
     * @param Object, the response json object {'id': id, 'width': width, 'height': height, 'content': content}
     * @paran string, the response json as text
     * @paran Element, the trigger
     * @return void
     */
    setContent: function(json, text, trigger) {
        nl.code.lightbox.Lightboxer.openLightbox(json.id, json.width, json.height, json.content, trigger, nl.code.lightbox.AjaxLightbox, nl.code.lightbox.Lightboxer.lightbox_options.ajax);
    },

    /**
     * @param int, the identifier
     * @param int, the width of the lightbox
     * @param int, the height of the lightbox
     * @param string, the content of the lightbox
     * @param Element, the element that triggers the lightbox
     * @param Fuction, the class constructor
     * @param Object, the options for the lightbox
     * @retrun void
     */
    openLightbox: function(id, width, height, content, trigger, lightbox_class, options) {
        // check if the lightbox is already generated and in the cache
        var lightbox = nl.code.lightbox.Lightboxer.findLightbox(id);

        // create the lightbox if it is not found in the cache
        if (! lightbox) {
            lightbox = new lightbox_class(id, options);

            nl.code.lightbox.Lightboxer.lightbox_arr.push(lightbox);
        } else if (nl.code.lightbox.Lightboxer.visible_lightbox_arr.contains(lightbox) && nl.code.lightbox.Lightboxer.visible_lightbox_arr[nl.code.lightbox.Lightboxer.visible_lightbox_arr.length - 1] != lightbox) {
            // if the lightbox was already in the visible array then remove it from the visible lightboxes array
            nl.code.lightbox.Lightboxer.visible_lightbox_arr.erase(lightbox);
        }

        // set the z-index for the lightbox
        lightbox.setZIndex(nl.code.lightbox.Lightboxer.zIndex++);

        // add the lightbox to the stack array
        nl.code.lightbox.Lightboxer.visible_lightbox_arr.push(lightbox);

        // width, height, content, trigger
        lightbox.show({
            width: width,
            height: height,
            content: content,
            trigger: trigger
        });
    },

    /**
     * Try to find a lightbox in the cache
     *
     * @param string, the id of the lightbox
     * @return Lightbox or false
     */
    findLightbox: function(id) {
        for (var i = 0; i < nl.code.lightbox.Lightboxer.lightbox_arr.length; i++) {
            if (nl.code.lightbox.Lightboxer.lightbox_arr[i].id == id) {
                return nl.code.lightbox.Lightboxer.lightbox_arr[i];
            }
        }

        return false;
    },

    /**
     * @param int
     * @return int
     */
    calculateCanvasXPosition: function(width) {
        var x = (window.getSize().x - width) / 2;

        if (x < 10) {
            x = 10;
        }

        x += window.getScroll().x;

        return x;
    },

    /**
     * @param int
     * @return int
     */
    calculateCanvasYPosition: function(height) {
        var y = (window.getSize().y - height) / 2;

        if (y < 10)  {
            y = 10;
        }

        y += window.getScroll().y;

        return y;
    },

    /**
     * A Lightbox can be bigger (width/height) then the window
     *
     * @param int
     * @return int
     */
    calculateWindowWidth: function(canvas_width) {
        var x         = nl.code.lightbox.Lightboxer.calculateCanvasXPosition(canvas_width);
        var min_width = 2 + canvas_width;
        var win_width = window.getScrollSize().x;

        if (min_width > win_width) {
            return min_width;
        }

        return win_width;
    },

    /**
     * A Lightbox can be bigger then the window size
     *
     * @param int
     * @return int
     */
    calculateWindowHeight: function(canvas_height) {
        var y          = nl.code.lightbox.Lightboxer.calculateCanvasYPosition(canvas_height);
        var min_height = y + canvas_height;
        var win_height = window.getScrollSize().y;

        if (min_height > win_height) {
            return min_height;
        }

        return win_height;
    },

    /**
     * Removes the focus of the currently active lightbox
     *
     * @return void
     */
    hideLightbox: function() {
        if (! nl.code.lightbox.Lightboxer.visible_lightbox_arr.length) {
            return;
        }

        var index = nl.code.lightbox.Lightboxer.visible_lightbox_arr.length - 1;

        nl.code.lightbox.Lightboxer.visible_lightbox_arr[index].hide();
        nl.code.lightbox.Lightboxer.visible_lightbox_arr.erase(nl.code.lightbox.Lightboxer.visible_lightbox_arr[index]);
    },

    /**
     * Remove the focus of all lightboxes
     *
     * @return void
     */
    hideAllLightboxes: function() {
        for (var i = 0; i < nl.code.lightbox.Lightboxer.visible_lightbox_arr.length; i++) {
            nl.code.lightbox.Lightboxer.visible_lightbox_arr[i].hide();
        }

        nl.code.lightbox.Lightboxer.visible_lightbox_arr = [];
    }
};