/**
 * Lightbox constructor
 *
 * @param Element|string node
 * @param Object options
 *
 * @returns {Lightbox}
 */
function Lightbox (node, options) {

    Ext.apply(this, options);

    this.node = Ext.get(node);
    if (!Ext.isEmpty(this.node) && Ext.isEmpty(this.url)) {
        this.url = this.node.getAttributeNS(null, 'href');;
    }

    this.body = Ext.getBody();

    this.addEvents('load');
};

Lightbox.CONTAINER_CLASS = 'lightbox-border';

if (typeof TEXT_LOADING_FORM == 'string') {
    Lightbox.TEXT_LOADING_FORM = TEXT_LOADING_FORM;
} else {
    Lightbox.TEXT_LOADING_FORM = 'Loading...';
}

/**
 * Assign lightbox instance to element
 *
 * @param Element|string node
 * @param Object options
 * @param bool addEvents
 *
 * @returns void
 */
Lightbox.assign = function(node, options, addEvents) {
    if (Ext.isEmpty(node)) {
        return;
    }

    if (Ext.isEmpty(node.lightbox)) {
        node.lightbox = new Lightbox(node, options);
        if (!Ext.isEmpty(addEvents)) {
            node.on('click', node.lightbox.show, node.lightbox);
        }
    } else {
        Ext.apply(node.lightbox, options);
    }
};


/**
 * Unassign lightbox instance at the element
 *
 * @param Element|string node
 * @returns void
 */
Lightbox.unassign = function(node) {
    if (Ext.isEmpty(node)) {
        return;
    }
    if (!Ext.isEmpty(node.lightbox)) {
        node.lightbox = null;
    }
};

/**
 * Retrieve node's lightbox instance
 *
 * @param Element node
 *
 * @returns null|Lightbox
 */
Lightbox.get = function(node) {
    if (!Ext.isEmpty(node.lightbox)) {
        return node.lightbox;
    }

    var el = Ext.get(Ext.get(node).findParent('.' + Lightbox.CONTAINER_CLASS));

    if (!Ext.isEmpty(el) && !Ext.isEmpty(el.lightbox)) {
        return el.lightbox;
    }

    return null;
};

/**
 * Assign lightbox instances to each element who have class .lightbox-link
 *
 * @param Object options
 *
 * @returns void
 */
Lightbox.init = function(options) {
    Ext.each(Ext.query('.lightbox-link'), function(node) {
        Lightbox.assign(node, options);
    }, Lightbox);
};

/**
 * extended to add fire events functionality ('onload' event)
 */
Ext.extend(Lightbox, Ext.util.Observable, {

    isLoaded: false,
    loading: false,
    overlay : null,
    container : null,
    url : null,
    method : 'GET',
    params : {},
    showDelay: 500,
    showingTask: null,
    reloadContent: true,
    refreshToCenter: true,
    body: null,
    callback: null,
    allowRedirect: true,
    currentScrollHandler: null,
    silentClose: false,

    /**
     * Get node
     *
     * @returns Element
     */
    getNode : function() {
        return Ext.get(this.node);
    },

    /**
     * Show overlay
     *
     * @returns Lightbox
     */
    showOverlay : function() {

        this.body.mask();

        var scroll = this.body.getScroll();
        this.body._mask.setTop(scroll.top);
        this.saveCurrentScrollHandler();

        return this;
    },

    /**
     * Hide overlay
     *
     * @returns Lightbox
     */
    hideOverlay : function() {

        if (!Ext.get(this.body._mask)) {
            return this;
        }

        this.restoreCurrentScrollHandler();
        Ext.get(this.body._mask).setDisplayed(false);
        this.body.unmask();

        return this;
    },

    /**
     * save current scroll handler
     *
     * @return void
     */
    saveCurrentScrollHandler : function() {
        this.currentScrollHandler = window.onscroll;
        window.onscroll = function() {
            var scroll = this.body.getScroll();
            this.body._mask.setTop(scroll.top);
        }.createDelegate(this);
    },

    /**
     * restore current scroll handler
     *
     * @return void
     */
    restoreCurrentScrollHandler : function() {
        window.onscroll = this.currentScrollHandler;
        this.currentScrollHandler = null;
    },

    /**
     * Retrieve lightbox container
     *
     * @returns Element
     */
    getContainer : function() {
        if (null === this.container) {
            this.container = Ext.DomHelper.append(this.body, {
                tag: 'div',
                cls: Lightbox.CONTAINER_CLASS,
                style: "z-index: 20001",
                children: [
                    {tag: 'div', cls: 'lightbox', html: Lightbox.TEXT_LOADING_FORM}
                ]
            }, true);
            this.container.lightbox = this;
        }

        return this.container;
    },

    /**
     * Load content to container
     *
     * @param string url
     * @param Object params
     * @param string method
     * @param callback Function
     *
     * @returns Lightbox
     */
    load : function(url, params, method, callback) {

        if (this.isLoaded && !this.reloadContent) {
            return this;
        }

        if (this.loading) {
            return this;
        }

        if (!this.isLoaded || this.reloadContent) {

            if (Ext.isEmpty(url)) {
                url = this.url;
            }

            if (!Ext.isEmpty(params) && !Ext.isEmpty(this.params)) {
                var additionalParams = {};
                if (/^#.+/.test(this.params)) {
                    var form = new Ext.form.BasicForm(this.params.replace(/^#(.+)/, '$1'));
                    if (!Ext.isEmpty(form)) {
                        additionalParams = form.getValues();
                    }
                } else {
                    additionalParams = this.params;
                }

            } else if (Ext.isEmpty(params)) {
                if (/^#.+/.test(this.params)) {
                    var form = new Ext.form.BasicForm(this.params.replace(/^#(.+)/, '$1'));
                    if (!Ext.isEmpty(form)) {
                        params = form.getValues();
                    }
                } else {
                    params = this.params;
                }
            }

            if (Ext.isEmpty(method)) {
                method = this.method;
            }

            this.loading = true;

            var element = this.getContentContainer();

            var width = (element.getBox().width >= 40) ? element.getBox().width - 40 : 0;
            var height = ((element.getBox().height >= 40)) ? element.getBox().height - 40 : 0;

            element.applyStyles({
                width:  width + 'px',
                height: height + 'px'
            });
            element.update(Lightbox.TEXT_LOADING_FORM);

            this.callback = callback;

            Ext.Ajax.request({
                url : url,
                callback : this.updateContentRequest.createDelegate(this),
                method : method,
                scope : this,
                params : params
            });
        }

        return this;
    },

    /**
     * callback AJAX request function
     */
    updateContentRequest: function(options, success, response) {
        this.getContentContainer().setStyle({
            width:  'auto',
            height: null
        });

        this.isLoaded = true;
        this.loading  = false;

        var data = null;
        try {
            data = Ext.util.JSON.decode(response.responseText);
        } catch (e) {}

        if (!Ext.isEmpty(data) && !Ext.isEmpty(data.command)) {
            this.hide();
            if (!this.allowRedirect && !Ext.isEmpty(data.command.redirect)) {
                data.command = {refresh: true};
            }
            ResponseCommand.run(data.command, this);

            return false;

        } else {
            this.update(response.responseText);
            this.fireEvent('load', this, response);
        }

        if (!Ext.isEmpty(this.callback)) {
            this.callback(this.getContentContainer(), success, response);
        }
    },

    /**
     * Retrieve content container
     *
     * @returns Element
     */
    getContentContainer: function() {
        return this.getContainer().child('.lightbox');
    },

    /**
     * Puts content to container
     *
     * @param string content
     *
     * @returns Lightbox
     */
    update: function(content) {
        this.getContentContainer().update(content, true); //, true);
        this.initContent();
        return this;
    },

    /**
     * Show lightbox with delay
     *
     * @returns Lightbox
     */
    delayedShow : function() {
        this.load();
        this.showingTask = new Ext.util.DelayedTask(this.show, this, [true]);
        this.showingTask.delay(this.showDelay);

        return this;
    },

    /**
     * Show lightbox
     *
     * @param bool withoutLoad
     *
     * @returns Lightbox
     */
    show : function(withoutLoad) {
        this.showingTask = null;

        this.showOverlay();

        if (withoutLoad != true) {
            this.load();
        }

        this.getContainer().setDisplayed(true);
        this.refresh();
        this.getContainer().show({
            duration : 0.15
        });

        return false;
    },

    /**
     * Hide lightbox
     *
     * @returns Lightbox
     */
    hide : function() {

        this.fireEvent('beforehide', this);

/*		this.getContainer().setDisplayed(false);
    with "display: none" does not work second time click on link2object */
        this.getContainer().hide();
        this.hideOverlay();

        if (this.reloadContent) {
            this.getContentContainer().update(Lightbox.TEXT_LOADING_FORM);
        }

        return this;
    },

    /**
     * Reset included form (if presense)
     *
     *
     * @returns Lightbox
     */
    clearForm : function() {
        var form = this.getContentContainer().child('form');

        if (!Ext.isEmpty(form)) {
            form.dom.reset();
        }

        return this;
    },

    /**
     * Initialize content
     *
     * @returns {Lightbox}
     */
    initContent : function() {
        this.refresh();

        Ext.each(Ext.query('.lightbox-close'), function(btnClose) {
            Ext.get(btnClose).on('click', this.closeLightbox, this);
            if (Ext.get(btnClose).isVisible()) {
                Ext.get(btnClose).dom.focus();
            }

        }, this);

        Ext.getBody().on('keydown', this.checkEsc, this);
        Ext.getBody().on('keypress', this.checkEsc, this);

        /* stopping scrolling of new stickers */
        if (Ext.get('news-ticker-container') && typeof NewsTickers != 'undefined') {
            NewsTickers.stopScrolling();
        }

        return this;
    },

    /**
     * checks whether ESC is pressed
     *
     * @param {event} event
     */
    checkEsc: function(event) {
        if (event.keyCode == event.ESC) {
            this.closeLightbox(event);
        }
    },

    /**
     * close light box
     *
     * @param {event} event
     * @return {boolean}
     */
    closeLightbox: function(event) {
        event.stopEvent();

        this.hide();

        if (typeof CANCEL_MESSAGE != 'undefined' && !this.silentClose) {
            showError(CANCEL_MESSAGE, null, true);
        }

        Ext.getBody().removeListener('keydown', this.checkEsc, this);
        Ext.getBody().removeListener('keypress', this.checkEsc, this);

        Ext.each(Ext.getBody().select('input.it_ids').elements, function(checkbox) {
            checkbox = Ext.getDom(checkbox);
            if (checkbox.checked) {
                checkbox.click(); /* set unchecked */
            }
        }, this);

        /* starting scrolling of new stickers */
        if (Ext.get('news-ticker-container') && typeof NewsTickers != 'undefined') {
            NewsTickers.startScrollingLeft();
        }

        return false;
    },

    /**
     * Refresh lightbox position
     *
     * @returns Lightbox
     */
    refresh : function() {
        if (this.refreshToCenter || Ext.isIE7) {
            this.getContainer().center(this.body);
        }

        return this;
    }
});

