/**
 * Fabuleos.js
 *
 * @category   Fabuleos_JS
 * @package    Fabuleos
 * @copyright  Copyright (c) 2010 Elma
 * @author     Hervé Piedvache (herve)
 */

if (typeof Fabuleos == "undefined") var Fabuleos = {};
if (typeof Fabuleos.Class == "undefined") Fabuleos.Class = {};
if (typeof Fabuleos.Helper == "undefined") Fabuleos.Helper = {};

// Some vars
Fabuleos.version = '1.1';
Fabuleos.debug = false;

// Debug and log function
Fabuleos.log = function() {

}

// Js GetText handler
if (typeof _ == "undefined") {
  var _ = function(s) {
    return s
  };
}

//
//

/**
 * AjaxLink Helper Class
 */
Fabuleos.AjaxLink = new Class({

    Implements: [Options],

    initialize: function(root, options) {

        if (!$type(root) || $type(root) == 'string') {
            var root = document;
        }


        root.getElements('a.ajaxLink').each(function(element) {
            this.initializeElement(element, options);
        }, this);

        // has loading element
        if (!$type($('loading'))) {
            return;
        }

        // store loading element
        this.loadingElement = $('loading');

        // init loading if needed
        if (!$('loading').retrieve('ajaxAbstract:semaphore')) {
            this.initLoading();
        }
    },

    initLoading: function()
    {
        this.loadingElement.setStyles({
            'position': 'fixed',
            'top': '0px',
            'left': '0px'
        });

        this.loadingElement.store('ajaxAbstract:semaphore', true);
        this.loadingElement.store('ajaxAbstract:nbActiveRequest', 0);

        this.hideLoading(true);
    },

    hideLoading: function(force) {

        // has loading element
        if (!$type(this.loadingElement)) {
            return;
        }

        // get current transation level
        var nbActiveRequest = this.loadingElement.store(
            'ajaxAbstract:nbActiveRequest',
            this.loadingElement.retrieve('ajaxAbstract:nbActiveRequest', 0) - 1
        );

        if (
           this.loadingElement &&
            (
            $type(force) ||
            (nbActiveRequest <= 0 && this.loadingElement.hasClass('loading'))
            )
        ) {

            // hide loading
            this.loadingElement.removeClass('loading');
            this.loadingElement.fade(0);

            this.loadingElement.store('ajaxAbstract:nbActiveRequest', 0);
        }
    },

    showLoading: function() {

        // has loading element
        if (!$type(this.loadingElement)) {
            return;
        }

        var nbActiveRequest = this.loadingElement.store(
            'ajaxAbstract:nbActiveRequest',
            this.loadingElement.retrieve('ajaxAbstract:nbActiveRequest', 0) + 1
        );

        if (this.loadingElement && !this.loadingElement.hasClass('loading')) {
            this.loadingElement.addClass('loading');
            this.loadingElement.fade(1);
        }
    },

    getRequest: function(options, type, origin) {

        // add default options
        var options = $merge({
            method: 'get',
            evalScripts: false,
            noCache: true,
            link: 'cancel'
        }
        , options);

        // update request instance options
        if ($type(this.myRequest)) {

            this.myRequest.setOptions(options);

        // create this.request instance
        } else {

            switch (type) {
                case 'JSON':
                this.myRequest = new Request.JSON(options);
                break;

                case 'HTML':
                this.myRequest = new Request.HTML(options);
                break;

                default:
                this.myRequest = new Request(options);
                break;
            }

            // add events
            this.myRequest.addEvent('request', this.showLoading.bind(this));
            this.myRequest.addEvent('exception', this.showLoading.bind(this));
            this.myRequest.addEvent('failure', this.hideLoading.bind(this));
        }

        // set callback origin
        if (typeof(origin) != 'undefined') {
           requestCallback = this.requestCallback.bindWithEvent(origin)
        } else {
           requestCallback = this.requestCallback.bind(this)
        }

        // add callback event for success
        this.myRequest.removeEvents('success');
        this.myRequest.addEvent('success', this.hideLoading.bind(this));
        this.myRequest.addEvent('success', requestCallback);

        return this.myRequest;
    },

    initializeElement: function(element, options) {

        if (element.retrieve('ajaxlink:semaphore')) {
            return;
        }

        var that = this;

        element.addEvent('click', function(e)
        {
            new Event(e).stop();

            var myRequest = that.getRequest({
                url: this.href
            }, 'HTML', this);

            myRequest.send();

            return false;

        });

        element.retrieve('ajaxlink:semaphore', true);
    },

    requestCallback: function(responseTree, responseElements, responseHTML, responseJavaScript) {
        var originElement = ($type(this) == 'element' ? $(this) : null)

        try {

            if ($type(responseJavaScript) && responseJavaScript.length > 0) {
                eval(responseJavaScript);
            }

            if ($type(responseHTML) && responseHTML.length > 0) {
                new Fabuleos.AjaxLink(responseHTML);
            }

        } catch (e) {
            throw e;
        }
    }
});

// launch at domready
window.addEvent('domready', function() {
    new Fabuleos.AjaxLink();
});


