/**
 * Meaningtool UI core components
 * @module UI
 * @requires none
 */

(function(){
    
    // initialize namespace
    MT.UI = {}
    
    /**
    * Encapsulates common Cloud ui behavior
    *
    * @Object Cloud
    * @namespace MT.UI
    */
    var Cloud = {};
    /**
    * cloud effects
    *
    * @Object Effects
    * @namespace MT.UI.Cloud
    */
    Cloud.Effects = {
        show: function(container) {
            container.removeClass("hidden");
        },
        
        hide: function (container) {
            container.addClass("hidden");
            container.css("display", "");
        },
        
        slideDown: function(container) {
            container.slideDown();
        },
        
        slideUp: function (container) {
            container.slideUp();
        },
        
        fadeIn: function(container, callback) {
            if (Utils.Browser.isIE7()) {
                this.show(container);
                callback && callback();
                return;
            }
            container.fadeIn("fast", callback);
            container.removeClass("hidden");
        },
        
        fadeOut: function(container) {
            container.fadeOut();
        }
    };
    
    /**
    * cloud status messages
    *
    * @requirements the viewport passed to the methods needs to have inside divs with
    *               the classes: success-message, error-message, empty-message, custom-message,
    *               init-message and spinner
    *               
    * @Object Messages
    * @namespace MT.UI.Cloud
    */
    Cloud.Messages = {
        ClassName: {
            IN_PROCESS: ".spinner",
            INIT: ".init-message",
            SUCCESS:".success-message",
            ERROR:".error-message",
            EMPTY: ".empty-message",
            CUSTOM: ".custom",
            CUSTOM_ERROR: ".error-message.custom"
        },
        hide: function(viewport) {
            if (viewport == undefined) debugger;
            $(this.ClassName.IN_PROCESS, viewport).addClass("hidden");
            $(this.ClassName.SUCCESS, viewport).addClass("hidden");
            $(this.ClassName.ERROR, viewport).addClass("hidden");
            $(this.ClassName.EMPTY, viewport).addClass("hidden");
            $(this.ClassName.INIT, viewport).addClass("hidden");
        },
        showInProcess: function(viewport, afterAction) {
            this.hide(viewport);
            $(this.ClassName.IN_PROCESS, viewport).removeClass("hidden");
            afterAction && afterAction();
        },
        hideInProcess: function(viewport, afterAction) {
            $(this.ClassName.IN_PROCESS, viewport).addClass("hidden");
            afterAction && afterAction();
        },
        showInit: function(viewport) {
            this.hideInProcess(viewport);
            $(this.ClassName.INIT, viewport).removeClass("hidden");
        },
        showError: function(viewport, afterAction) {
            this.hideInProcess(viewport);
            $(this.ClassName.ERROR, viewport).not(".custom").removeClass("hidden");
            afterAction && afterAction();
        },
        showCustomError: function(viewport, message, afterAction) {
            this.hide(viewport);
            $(this.ClassName.CUSTOM_ERROR, viewport).removeClass("hidden").text(message);
            afterAction && afterAction();
        },
        showSuccess: function(viewport, afterAction) {
            this.hideInProcess(viewport);
            $(this.ClassName.SUCCESS, viewport).removeClass("hidden");
            afterAction && afterAction();
        },
        showEmpty: function(viewport) {
            this.hideInProcess(viewport);
            $(this.ClassName.EMPTY, viewport).removeClass("hidden");
        }
    };
    
    /**
    * image markup generation
    *
    * @Object ImageProvider
    * @namespace MT.UI.ImageProvider
    */
    var ImageProvider = {
        Flags: {
            TEMPLATE: '<img src="/images/b.gif" class="flag ${LANG}" />',
            get: function(lang) {
                return this.TEMPLATE.replace("${LANG}", lang);
            }
        }
    };
    
    /**
    * Common js actions
    *
    * @Object Utils
    * @namespace MT
    */    
    var Utils = {
        Regex: {
            EMAIL_VALIDATOR: function() { return /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i}
        },
        Json:{
            evaluate: function(s) {
                return eval("(" + s + ")");
            }
        },
        
        Browser: {
            _ie: null,
            _ie7: null,
            isIE: function() {
                this._ie = this._ie || (window.ActiveXObject ? true : false);
                return this._ie
            },
            isIE7: function() {
                this._ie7 = this._ie7 || (this.isIE() ? (navigator.appVersion.match(/MSIE (\d)\.(\d)/)[1] == "7") : false);
                return this._ie7
            },
            // returns a string with the IE version or false if not IE
            ieVersion: function() {
                return (this.ie ? navigator.appVersion.match(/MSIE (\d\.\d)/)[1] : false)
            },
            isOpera: function() {
                return window.opera;
            }
        },
        
        Cookie: {
            /**
            * @method get
            * @argument name {string} The key to search in the cookie.
            */
            get: function(key) {
                var v = '';
                var c = document.cookie;
                if (!c) return v;
                var i = c.indexOf(key + "=");
                var len = i + key.length + 1;
                if (i > -1) {
                    var end = c.indexOf(";", len);
                    if (end < 0) end = c.length;
                    v = c.substring(len, end);
                }
                return v;
            },
            
            /**
             * @method set
             * @argument name {string} The key to search in the cookie.
             */
            set: function(key, val, days) {
                if (days) {
                    var date = new Date();
                    /* 86400000 = 24*60*60*1000 */
                    date.setTime(date.getTime()+(days*86400000));
                    var expires = "; expires="+date.toGMTString();
                }
                else var expires = "";
    
                document.cookie = key + "=" + val + expires +"; path=/; domain=" + new String(document.domain);
            }
        },
        
        trim: function(s) {
            return $.trim(s);
        },
        
        /**
         * Truncate a string
         * @method truncate
         * @param {String} text The text to truncate
         * @param {int} maxChars The maxinum numbers of chars
         * @param {String} end optional The ending string. Default "..."
         */
        truncate: function(text, maxChars, end) {
            var r = text;
            if (text.length > maxChars) {
                r = text.substr(0, maxChars);
                r += end || "..."
            }
            return r;
        },
        
        /**
         * Extend one object with one or more others, returning the modified object.
         * @method extend
         * @param {arguments} one or more javascript 'Object'
         */
        extend: function() {
            return $.extend.apply(this, arguments);
        },
        
        getBlankPixel: function() {
            return "/images/b.gif";
        },
        
        pixel: function() {
            return "/images/b.gif";
        },
        
        LanguagesMap: {
            'en':'English',
            'es':'Spanish',
            'pt':'Portuguese'
        },
        
        // adds a timestamp to an url
        timestamp: function(url, isFirstParam) {
            if (isFirstParam) {
                return url + "?timestamp=" + new String(new Date().getTime())
            } else {
                return url + "&timestamp=" + new String(new Date().getTime())
            }
        },
        
        // groups a number separated by commas in groups of 3 digits
        addCommas: function(nStr) {
            nStr += '';
            x = nStr.split('.');
            x1 = x[0];
            x2 = x.length > 1 ? '.' + x[1] : '';
            var rgx = /(\d+)(\d{3})/;
            while (rgx.test(x1)) {
                x1 = x1.replace(rgx, '$1' + ',' + '$2');
            }
            return x1 + x2;
        }
    };
    
    /**
    * Wrapper for event handling, needs the Event Object to be added to the prototype of the dispat
    *
    * @Object Events
    * @namespace MT
    */    
    var Events = {
        dispatchEvent: function(evt, data) {
            $(self).trigger({type:evt, evtData:data});
        },
        
        addEvent: function(evt, callback) {
            $(self).bind(evt, callback);
        }
    };
    
    var StatusManager = function(el, options) {
        this.init(el, options);
    };
    
        StatusManager.Types = {OK: "ok", WARNING: "warning"};
    
        StatusManager.prototype = {
            init: function(el, options) {
                if (typeof el == "object") {
                    this.el = el;
                } else {
                    this.el = $(el);
                    if (this.el.length != 1) {
                        throw new Error('StatusManager.init: there must be one and only one element that matches the provided selector.');
                    }
                }
                this.el.hide();
            },
            
            type: function(t) {
                this.el.attr("class", t);
                return this;
            },
            
            show: function(text, delay) {
                var self = this;
                
                this.el.html(text).show();
                
                var pxsLeft = parseInt(($(window).width() - this.el.width())/2);
                this.el.css("left", new String(pxsLeft) + "px");
                
                if (!delay) {
                    return;
                }
                
                var timer = setTimeout(function() {
                    self.hide();
                }, delay)
            },
            
            hide: function() {
                this.el.hide();
            },
            
            isVisible: function() {
                return this.el.css("display") != "none";
            }
        };

    
    // exports
    MT.Utils = Utils;
    MT.Events = Events;
    MT.UI.Cloud = Cloud;
    MT.UI.ImageProvider = ImageProvider;
    MT.UI.StatusManager = StatusManager;
})();
