﻿/* Fnac Framework*/
/**************** EXEMPLE **************** /
AppCore.ready(function(){
AppCore.register('testmodule', function(){
//Private elements
var private_var = 17;
function private_function()
{
return private_var;
}
//Public elements
return {
public_var: 0,
init: function()
{
this.public_var = private_function();
},
destroy: function()
{
                
},
public_function: function()
{
alert("Hello je suis public"+this.public_var); 
}
}
});
//Launching init module function
AppCore.start('testmodule');
AppCore.modules.testmodule.public_function();
//Trying to register existing modules -> throw error.
AppCore.register('testmodule', function(){});
});
/***************************************** /
Waiting for the named module to be ready.
AppCore.modules.ready('nomDuModule', function(){
    
});*/
//Checking Base Component(actually JQuery)
if(!jQuery) { throw new Error("Jquery not included") } else
{
    var AppCore = AppCore || function()
    {
        var modules = {
            stackCallbacks: {},
            ready: function(moduleName, callback)
            {
                if(this[moduleName] && this[moduleName]["isready"] == true)
                {
                    this[moduleName]["callbackFunction"] = callback;
                    this[moduleName]["callbackFunction"]();
                    delete this[moduleName]["callbackFunction"];
                    //callback();
                }
                else
                {
                    this.stackCallbacks[moduleName] ? this.stackCallbacks[moduleName].push(callback) : this.stackCallbacks[moduleName] = [callback];
                }
            }
        };
        function setModulesInheritParams(module)
        {
            module["$"] = AppCore.$;
            module["isready"] = true;
            module["Me"] = module;
            module["parent"] = AppCore;
            module["core"] = AppCore;
        }
        function fireModuleReady(moduleName)
        {
            if(modules.stackCallbacks[moduleName])
            {
                var len = modules.stackCallbacks[moduleName].length;
                for(var i = 0;i < len;i++)
                {
                    modules.stackCallbacks[moduleName][i]();
                }
            }
        };
        //Registering Module
        return {
            modules: modules,
            //Accessing Jquery framework.
            $: window.jQuery,
            /* @param moduleName : namespace of module
            @param moduleContent : object containing properties, functions of the module */
            register: function(moduleName, moduleContent)
            {
                var rReturn = false;
                if(!modules[moduleName])
                {
                    modules[moduleName] = moduleContent();
                    setModulesInheritParams(modules[moduleName]);
                    fireModuleReady(moduleName);
                    rReturn = true;
                }
                return rReturn;
            },
            //Launching module action
            unregister: function(moduleName)
            {
                try
                {
                    modules[moduleName]["destroy"]();
                }
                catch(error)
                {
                    throw new Error("AppCore : Module " + moduleName + " not registered or module's destroy function missing");
                }
                delete modules[moduleName];
            },
            start: function(moduleName, args)
            {
                var rReturn = null;
                if(modules[moduleName])
                {
                    modules[moduleName].init(args);
                    rReturn = modules[moduleName];
                }
                else
                {
                    modules.ready(moduleName, function() { modules[moduleName].init(args); });
                }
                //else throw new Error("Module "+moduleName+" not registered");

                return rReturn;
            },
            //Embed your code in ready function only if you need to use JQuery in init process.
            ready: function(handler)
            {
                AppCore.$(document).ready(handler);
            },
            //Add function
            extend: function(extendName, functionToAdd)
            {
                if(!this[extendName])
                {
                    this[extendName] = functionToAdd;
                }
                else
                {
                    //throw new Error("AppCore : Extension " + extendName + " is existing");
                }
            },
            extend$: function(extendName, functionToAdd)
            {
                if(!this[extendName])
                {
                    var obj = {};
                    obj[extendName] = functionToAdd;
                    this.$.fn.extend(obj);
                }
                else
                {
                    //throw new Error("AppCore.$ : Extension " + extendName + " is existing");
                }
            }
        };
    } ();
}
//Extensions
AppCore.extend$("exists", function(selector)
{
    return !this.length == 0;
});
AppCore.extend("KeyCode", {
        BACKSPACE: 8,
        CAPS_LOCK: 20,
        COMMA: 188,
        CONTROL: 17,
        DELETE: 46,
        DOWN: 40,
        END: 35,
        ENTER: 13,
        ESCAPE: 27,
        HOME: 36,
        INSERT: 45,
        LEFT: 37,
        NUMPAD_ADD: 107,
        NUMPAD_DECIMAL: 110,
        NUMPAD_DIVIDE: 111,
        NUMPAD_ENTER: 108,
        NUMPAD_MULTIPLY: 106,
        NUMPAD_SUBTRACT: 109,
        PAGE_DOWN: 34,
        PAGE_UP: 33,
        PERIOD: 190,
        RIGHT: 39,
        SHIFT: 16,
        SPACE: 32,
        TAB: 9,
        UP: 38
    });
AppCore.extend("initEachArgs",function($initVar, $initArgs)
{
    for(var $prop in $initArgs)
    {
        $initVar[$prop]=$initArgs[$prop];
    }
    return $initVar;
});
//Overload Firebug logger.
AppCore.extend("logger", (function()
{
    var logFunctions = {
        0: "log",
        1: "info",
        2: "warn",
        3: "error"
        };
    function log(message, level)
    {
        level = level || 0;
        if(console)
        {
            console[logFunctions[level]](message);
        }
    };
    return {
        debug: function()
        {
            log(arguments, 0);
        },
        info: function()
        {
            log(arguments, 1);
        },
        warning: function()
        {
            log(arguments, 2);
        },
        error: function()
        {
            log(arguments, 3);
        }
    };
})());
/**
* Manage cookies. set/get/delete.
**/
AppCore.register('cookies',function()
{
    function setCookieValue(name,value,options)
    {
        if(typeof value!='undefined')
        { // name and value given, set cookie
            options=options||{};
            if(value===null)
            {
                value='';
                options.expires= -1;
            }
            var expires='';
            if(options.expires&&(typeof options.expires=='number'||options.expires.toUTCString))
            {
                var date;
                if(typeof options.expires=='number')
                {
                    date=new Date();
                    date.setTime(date.getTime()+(options.expires*24*60*60*1000));
                } else
                {
                    date=options.expires;
                }
                expires='; expires='+date.toUTCString(); // use expires attribute, max-age is not supported by IE
            }
            // CAUTION: Needed to parenthesize options.path and options.domain
            // in the following expressions, otherwise they evaluate to undefined
            // in the packed version for some reason...
            var path=options.path?'; path='+(options.path):'';
            var domain=options.domain?'; domain='+(options.domain):'';
            var secure=options.secure?'; secure':'';
            document.cookie=[name,'=',encodeURIComponent(value),expires,path,domain,secure].join('');
        } else
        { // only name given, get cookie
            var cookieValue=null;
            if(document.cookie&&document.cookie!='')
            {
                var cookies=document.cookie.split(';');
                for(var i=0;i<cookies.length;i++)
                {
                    //Triming -> Independant of Jquery
                    var cookie=cookies[i].replace(/^\s\s*/,'').replace(/\s\s*$/,'');
                    // Does this cookie string begin with the name we want?
                    if(cookie.substring(0,name.length+1)==(name+'='))
                    {
                        cookieValue=decodeURIComponent(cookie.substring(name.length+1));
                        break;
                    }
                }
            }
            return cookieValue;
        }
    }
    return {
        set: function(name,value,options)
        {
            setCookieValue(name,value,options);
        },
        get: function(name)
        {
            return setCookieValue(name);
        },
        del: function(name)
        {
            setCookieValue(name,null);
        }
    }
});
/**
* Grouping utilities
*
**/
AppCore.register('utilities',function(){
    //Private var, declared one time.
    var curleft=0, curtop=0;
    return {
        /* Find absolute position of an object.
        @param obj : object to find positions 
        @return : Object -> obj.left : leftPosition, obj.top : topPosition
        */
        findPos: function(obj)
        {
            if(obj.offsetParent)
            {
                curleft=obj.offsetLeft
                curtop=obj.offsetTop
                while(obj=obj.offsetParent)
                {
                    curleft+=obj.offsetLeft
                    curtop+=obj.offsetTop
                }
            }
            return { left: curleft,top: curtop };
        },
        /* Set the height of each group blocs with the max height
        @param group : Jquery bloc list group.
        */
        equalBlocHeight: function(groupSelector)
        {
            var tallestHeight=0,thisHeight;
            var group=AppCore.$(groupSelector);
            group.each(function()
            {
                thisHeight=$(this).height();
                if(thisHeight>tallestHeight)
                {
                    tallestHeight=thisHeight;
                }
            });
            group.height(tallestHeight);
        }
    };
});

AppCore.register("popins", function()
{
    var params = {
        //Id given to the popin container created
        idPopinContainer: "popin_container",
        //Classes added at the popin container
        classes: [],
        //z-index de la popin
        zIndex: 1001,
        //Offset of position
        offset: { left: 0, top: 0 },
        //Content of the popin - string or jquery object
        content: "",
        //Time in milliseconds of opening fader
        openFader: 0,
        //Time in milliseconds of closing fader
        closeFader: 0,
        //Reference object of where to place the popin
        positionReferer: null,
        //Time before automatically close the popin. In milliseconds
        closeTimer: null,
        //Offset popin left position if too large.
        manageLeftOverride: true,
        //Layer object : hasLay : bool. If layer is an html object, give to layerObject property the jquery object reference.
        //cssLayer : css object set to the layer ex : {"background-color": "black"}
        layer: { hasLayer: false, layerObject: null, cssLayer: null },
        //If popin closing on pressing escape key.
        closeOnEscapeKey: true,
        //If popin closing on clicking on layer.
        closeOnClickLayer: true
    };
    var listCurrentPopins = {};
    function getPositionPopin(args, popin)
    {
        var pos = { top: 0, left: 0 };
        if(args.positionReferer != null)
        {
            pos = args.positionReferer.offset();
        }
        else
        {
            //Centering popin
            pos.left = ($(window).width() - popin.width()) / 2;
            pos.top = (($(window).height() - popin.height()) / 2) + popin.offset().top;
        }
        //Adding offset
        pos.top += args.offset.top;
        pos.left += args.offset.left;
        if(args.manageLeftOverride)
        {
            var overflow = $(window).width() - (popin.width() + pos.left);
            if(overflow < 0)
            {
                pos.left += overflow;
            }
        }
        return pos;
    }
    function showPopin(args)
    {
        if(!AppCore.$("#" + args.idPopinContainer).exists()) //TODO RSA : pb ajax "this" object.
        {
            var append = "<div id='" + args.idPopinContainer + "' style='position:absolute;display:none;' class='" + (args.classes.join(" ")) + "'></div>";
            $("body").append(append);
        }
        var popin = $("#" + args.idPopinContainer);
        if(args.content["detach"])
        {
            args.content.show().detach();
        }
        popin.html(args.content);
        var pos = getPositionPopin(args, popin);
        popin.css({
            top: pos.top + "px",
            left: pos.left + "px",
            "z-index": args.zIndex
        });
        var layer = null;
        if(args.layer.hasLayer)
        {
            if(args.layer.layerObject != null)
            {
                layer = args.layer.layerObject;
                layer.detach();
                $("body").append(layer);
                layer.css("position", "fixed");
            }
            else
            {
                $("body").append("<div id='" + args.idPopinContainer + "_layer' style='position:fixed'></div>");
                layer = $("#" + args.idPopinContainer + "_layer");
                if(args.layer.cssLayer) layer.css(args.layer.cssLayer);
            }
            layer.css({
                height: "100%",
                width: "100%",
                top: 0,
                left: 0,
                "z-index": args.zIndex - 1
            });
            layer.fadeTo(args.openFader, layer.css('opacity'));
            //layer.fadeIn(args.openFader);
            if(args.closeOnClickLayer)
            {
                layer.unbind("click").click(function(e)
                {
                    e.preventDefault();
                    hidePopin(popin, layer, args.closeFader);
                    return false;
                });
            }
        }
        popin.fadeIn(args.openFader);
        listCurrentPopins[args.idPopinContainer] = args;
        if(args.closeTimer != null)
        {
            setTimeout(function() { hidePopin(popin, layer, args.closeFader); }, args.closeTimer);
        }
        //If escape key defined -> listen keypress event.
        if(args.closeOnEscapeKey)
        {
            $(document).unbind("keypress").keypress(function(key)
            {
                if(key.keyCode == AppCore.KeyCode.ESCAPE)
                {
                    hidePopin(popin, layer, args.closeFader);
                }
            });
        }
        //If close button -> listen click event on this close button.
        if(args.closeButton != null)
        {
            args.closeButton.die("click").live("click", function(e)
            {
                e.preventDefault();
                hidePopin(popin, layer, args.closeFader);
                return false;
            });
        }
        return popin;
    }
    function hidePopin(popinContainer, layer, closeFader)
    {
        popinContainer.fadeOut(closeFader);
        popinContainer.children().fadeOut(closeFader);
        if(layer != null && typeof layer != "undefined")
        {
            layer.fadeOut(closeFader);
        }
        //delete listCurrentPopins[popinContainer.attr("id")];
    }
    function initArgs(args)
    {
        var prop;
        for(prop in params)
        {
            //If no property overriden in showPopin use default
            if(!args[prop])
            {
                args[prop] = params[prop];
            }
        }
        return args;
    }
    return {
        /**
        * @params 
        **/
        showPopin: function(args)
        {
            var args = initArgs(args);
            return showPopin(args);
        },
        closePopin: function(popin)
        {
            if(popin)
            {
                var args = listCurrentPopins[popin.attr("id")];
                if(args)
                {
                    var layer = null;
                    if(args.layer.hasLayer)
                    {
                        layer = args.layer.layerObject != null ? args.layer.layerObject : $("#" + args.idPopinContainer + "_layer");
                    }
                    hidePopin(popin, layer, args.closeFader);
                }
            }
        }
    };
});
