/** 
 *                    _     
 *     __________    (_)____
 *    / ___/ ___/   / / ___/
 *   (__  ) /  _   / (__  ) 
 *  /____/_/  (_)_/ /____/  
 *             /___/        
 *  
 *  SchoolRack Common Javascript
 *  (c) Copyright 2007-2009 SchoolRack, LLC. All rights reserved.
 *  Written by Michael Whalen
 *
 */

var SR = {
    Util: {},
    GLOBAL: {},
    log: function(msg) {
        if (window.console && window.console.firebug) { console.log('[[SR]]: '+msg); }	
        else { alert('[[SR]]: '+msg); }
    }
};

if (typeof Cobra != 'undefined') { Cobra.install(); }

SR.Message = {
    init: function() {
        $('#content').bind('click', function(event) {
            var t = $(event.target);
            if (t.hasClass('close') && t.parent().hasClass('srMessage')) {
                t.parent().remove();
                return false;
            }
        });
    },

    create: function(type, message) {
        var skeleton =  '<div class="srMessage '+type+'"><div class="nw"></div>'+
                        '<div class="ne"></div><div class="sw"></div><div class="se">'+
                        '</div><a class="close" href="#">[X]</a>'+
                        '<div class="messageBody"><p>'+message+'</p></div></div>';
        
        var m = $(skeleton);

        $('#content .srMessage:not(.note)').remove();
        $('#content').prepend(m).show();
    },
    
    clearAll: function() {
        $('#content .srMessage:not(.note)').remove();
    }
};

SR.Util = {
    objProperties: function(obj, parent) {
        var msg;
        if (obj) {
            for (var i in obj) { 
                if (parent) { msg = parent + "." + i + "\n" + obj[i]; } else { msg = i + "\n" + obj[i]; } 
                if (!confirm(msg)) { return; } 
                if (typeof obj[i] == "object") { 
                    if (parent) { dumpProps(obj[i], parent + "." + i); } else { dumpProps(obj[i], i); } 
                }
            }
        }
    },
    
    isArray: function(obj) {
        return (obj.constructor.toString().indexOf("Array") != -1);
    },
    
    get_id: function(target, type) {
        return $(target).attr(type).split('-')[1];
    },
    
    restripeList: function(target) {
        $(target).removeClass('even').removeClass('odd');
        $(target+':even').addClass('odd');
        $(target+':odd').addClass('even');
    },
    
    removeEmptyList: function(target) {
        if ($(target).children('li').size() == 1) {
            $(target).parent().remove();
        }
    },
    
    validEmail: function(email) {
        var emailFilter=/^(("[\w-\s]+")|([\w-]+(?:\.[\w-]+)*)|("[\w-\s]+")([\w-]+(?:\.[\w-]+)*))(@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|(@\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)/i;
        if (emailFilter.test(email)) { return true; } 
        else { return false; }
    }
};

/**
 *  SR Dialog System --------------------------------------------------------
 *
 *  Versatile modal dialog popup to offer an easy and fast
 *  way to edit teeny bits of info that might not require an entire page
 *
 */

SR.Dialog = {
    settings: {},
    overlay: $('<div/>').attr('id', 'srDialogOverlay'),
    skeleton: $('<div/>').attr('id', 'srDialog').hide().html('Loading...'),
    animation: {
        html: '<div id="srDialogLoading"><img id="zoomSpinner" src="/img/dialog/zoomSpinner-1.png" alt="Loading..."/>',
        id: '#srDialogLoading',
        spinner: 'img#zoomSpinner',
        frame: 1
    },
    
    // Initialize the dialog birthing
    init: function(type) {
        if (this.settings.initialized) { return true; } 
        else { this.settings.initialized = true; }
        
        // Prepend the overlay, loading animation, as well as the dialog skeleton to the body.
        $('body').prepend(this.overlay).prepend(this.skeleton);
        
        // Set the height of the overlay to the browser window height
        this.overlay.css('height', $(document).height());
        
        // Bind the close event for the dialog
        $(document).bind('keydown.dialog', function(e) { if (e.keyCode == 27) { SR.Dialog.destroy(); } });
        
        $(document).bind('close.dialog', function() {
            $(document).unbind('keydown.dialog');
            SR.Dialog.destroy();
        });
        
        $('.closeDialog').bind('click', function(event) { global.destroy(); return false; });
        $('#srDialog form').bind('submit', function(event) { return false; });
        
    },
    
    // Create a new dialog
    createWithPayload: function(payload, target) {
        var global = this;
        
        SR.GLOBAL.dialogTarget = target;
        
        this.init();
        this.overlay.show();
        if (payload.onLoad) {
            global.reveal(global.parsePayload(payload), payload.onLoad);
        } else {
            global.reveal(global.parsePayload(payload));
        }
    },
    
    createWithURL: function(url, target) {
        var global = this;
        
        SR.GLOBAL.dialogTarget = target;
        
        this.init();
        $('body').prepend(this.animation.html);
        this.loadingTimer = setInterval(function() {
            SR.Dialog.loading();
        }, 100);
        this.overlay.show();
        $.get(url, function(payload) { 
            global.reveal(payload);
        });
    },
    
    reloadWithPayload: function(payload, onLoadCallback) {
        var global = this;

        if (onLoadCallback) {
            global.reveal(global.parsePayload(payload), onLoadCallback);
        } else {
            global.reveal(global.parsePayload(payload));
        }
    },
    
    reloadWithURL: function(url) {
        var global = this;
        $('body').prepend(this.animation.html);
        this.loadingTimer = setInterval(function() {
            SR.Dialog.loading();
        }, 100);
        this.overlay.show();
        global.util.isLoading();
        $.get(url, function(payload) { 
            global.reveal(payload);
            global.util.isDoneLoading();
        });
    },
    
    // Simple call to reload a dialog with an error message from an ajax respose.
    reloadWithError: function(msg) {
        this.reloadWithPayload({
            title: 'Error',
            content: '<p>'+msg+'</p>',
            buttons: [{
                label: 'Close', type: 'target',
                callback: function() { SR.Dialog.destroy(); } 
            }]
        });
    },
    
    createWithError: function(msg) {
        this.createWithPayload({
            title: 'Error',
            content: '<p>'+msg+'</p>',
            buttons: [{
                label: 'Close', type: 'target',
                callback: function() { SR.Dialog.destroy(); } 
            }]
        });
    },
    

    // Prepare the dialog for reveal
    loading: function() {
        if (this.settings.loaded) {
            clearInterval(this.loadingTimer);
            $(this.animation.id).hide();
            this.animation.frame = 1;
        } else {
            $(this.animation.id).show();
            $(this.animation.spinner).attr('src', '/img/dialog/zoomSpinner-'+this.animation.frame+'.png');
            this.animation.frame++;
            if (this.animation.frame > 12) { this.animation.frame = 1; }
        }
    },
    
    reposition: function() {
        var global = this;
        // Determine the proper offset to give the puppet so it's displayed in the center of the pages
        var dialogPos = { h: this.skeleton.height() / 2, w: this.skeleton.width() / 2 };

        // Reposition the puppet now that it's been given its payload and then display it
        this.skeleton.css({ marginTop: -dialogPos.h, marginLeft: -dialogPos.w });
    },
    
    // Reveal a loaded and ready to rock dialog
    reveal: function(payload, onLoadCallback) {
        var global = this;
        this.settings.loaded = true;

        this.skeleton.empty().append(payload);

        // Determine the proper offset to give the puppet so it's displayed in the center of the pages
        var dialogPos = { h: this.skeleton.height() / 2, w: this.skeleton.width() / 2 };

        // Reposition the puppet now that it's been given its payload and then display it
        this.reposition();
        this.skeleton.fadeIn(500);
        
        // If a load callback is sent, execute it after the dialog has been shown.
        if (onLoadCallback) { onLoadCallback(); }
    },
        
    // Destroy a currently open dialog
    destroy: function() {
        $('#srDialogOverlay').hide();
        $('#srDialog').fadeOut(200, function(){
            $('#srDialog').empty();
            SR.Dialog.settings.loaded = false;
            SR.GLOBAL.dialogTarget = null;
        });
    },
    
    parsePayload: function(payload) {
        var global = this;
        
        var title = payload.title || 'Empty Title',
            content = payload.content || 'Empty Content',
            buttons = payload.buttons || [ 
                { label: 'Cancel', type: 'target', callback: function() { global.destroy(); } } 
            ];
        
        var dialogHeader = $('<div/>').attr('class', 'srDialogHeader').html('<h3>'+title+'</h3>');
        var dialogBody = $('<div/>').attr('class', 'srDialogBody').html(content).append(payload.quickMenu || null);
        var dialogFooter = null;
        
        // If no buttons, don't include a footer:
        if (!payload.noFooter || payload.noFooter === false) {
            dialogFooter = $('<div/>').attr('class', 'srDialogFooter').html('<div class="buttons small"></div>');
            
            // Create a DOM element from the buttons array passed in the payload
            for (var i=0; i < buttons.length; i++) {
                if (!buttons[i].type) { buttons[i].type = ''; }
                var b = $('<a class="btn '+buttons[i].type+'"><span><span>'+buttons[i].label+'</span></span></a>').click(buttons[i].callback);
                $(dialogFooter).children('div.buttons').append(b);
            }
        }
        
        payload = $('<div/>').append(dialogHeader).append(dialogBody).append(dialogFooter);
            
        return payload;
    },
    
    // Toggle the modules within a dialog
    toggleModule: function() {
        
    },
    
    // quickMenu, creates an iphone-esque menu of big buttons
    quickMenu: {
        standard: function(payload) {
            
            var global = this;

            var id = payload.id || 'quickMenu',
                buttons = payload.buttons || [ 
                    { label: 'Yes', _class: 'yes', click: function() { alert('YES'); } },
                    { label: 'No', _class: 'no', click: function() { alert('NO'); } }
                ];

            var quickMenu = $('<del/>').attr('class', 'dialogQuickMenu').html('<ul></ul>');
            
            $(quickMenu).children('ul').attr('id', id);

            // Small function to create a DOM element from the buttons array passed in the payload
            function createButton(button) {
                $(quickMenu).children('ul').append(
                    $('<li><a class="quickMenuButton '+button._class+'"><span></span>'+button.label+'</a></li>').click(function() { button.callback(); return false; })
                );
            }

            for (var i=0; i < buttons.length; i++) { createButton(buttons[i]); }

            return quickMenu;
            
        },
        
        yesNo: function(buttons) {
            var global = this;
            
            if (!buttons) { 
                buttons = [ 
                    { label: 'Yes', _class: 'yes', click: function() { alert('YES'); } },
                    { label: 'No', _class: 'no', click: function() { alert('NO'); } }
                ];
            }

            var quickMenu = $('<del/>').attr('class', 'dialogQuickMenu').html('<ul class="yesno"></ul>');
            
            // Small function to create a DOM element from the buttons array passed in the payload
            function createButton(button) {
                $(quickMenu).children('ul').append(
                    $('<li><a class="quickMenuButton '+button._class+'"><span></span>'+button.label+'</a></li>').click(function() { button.callback(); return false; })
                );
            }

            for (var i=0; i < buttons.length; i++) { createButton(buttons[i]); }

            return quickMenu;
            
        }
    },
    
    util: {
        isLoading: function() {
            // Add a little loading wheel contraption to the upper right of the dialog.
            $('.srDialogHeader').prepend('<span class="loadingStatus">Loading...</span>');
        },
        isDoneLoading: function() {
            // Remove the little loading wheel contraption in the upper right of the dialog.
            $('.srDialogHeader span.loadingStatus').remove();
        }
    }
    
};

/**
 *  Extend the String object with a shorten method to concatenate a string to a desired length.
 *
 *  @param  n, the number of characters to shorten the string by.
 *  @param  i, the indicator to append to the concatenated string.
 *              this is optional, and defaults to &hellip;
 *  
 */
String.prototype.shorten = function(n, i) {
    var indicator = i || '…';
    return (this.length > n) ? String(this.substr(0, n)+indicator) : String(this);
};

/**
 *  Extend the Number object with an apnumber method which converts an integer to an "apnumber".
 *      - Ex) 1 => One
 *      - Ex) 2 => Two
 *
 */
Number.prototype.apnumber = function() {
    var numberMap = 
        [ 'Zero', 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 
          'Seven', 'Eight', 'Nine', 'Ten', 'Eleven', 'Twelve', 'Thirteen' ];
          
    return (13 >= this) ? numberMap[this] : this;
};

/**
 *  Extend the Number object with a pluralize method which converts assists in making words plural based on a value.
 *  The parameters below are OPTIONAL. If both are included, then rather than simple appending an 's' it will use your
 *  given options. So, 'Cherry' and 'Cherries' would be a manual use case for these parameters.
 *
 *  @param  singular,   the singular version of the word you are pluralizing
 *  @param  plural,     the plural version of the word you are pluralizing
 *
 */
Number.prototype.pluralize = function(singular, plural) {
    var a = '', b = 's';
    if (singular && plural) { a = singular; b = plural; }
    return (this == 1) ? a : b;
};

Number.prototype._default = function(str) {
    // If the value of this is false, return the string
    if (this === false || 0) { return str; } else { return this; }
};


/**
 *  Extend the Array object with an inArray method which will return true if the passed value exists in the array.
 *
 *  @param  value,  the value to check against the array
 *
 */
Array.prototype.inArray = function(value) {
    for (var i=0; i < this.length; i++) {if (this[i] === value) { return true; }}
    return false;
};
/**
 *  Remove an item from an array, By John Resig (MIT Licensed)
 *
 */
Array.prototype.remove = function(from, to) {
    var rest = this.slice((to || from) + 1 || this.length);
    this.length = from < 0 ? this.length + from : from;
    return this.push.apply(this, rest);
};

jQuery.fn.getID = function(t) {
    var type = t || 'id';
    var id = this.attr(type).split('-')[1];
    return parseInt(id, 10);
};

jQuery.fn.activate = function() {
    this.addClass('active');
};

jQuery.fn.deactivate = function() {
    this.removeClass('active');
};

// Simple button creator.
var srButton = new Class({
    __init__: function(self, params){
        
        self.text       = params.text       || 'NO NAME';
        self.target     = params.target     || false;
        self.position   = params.position   || false;
        self.id         = params.id         || null;
        self.klass      = params.klass      || null;
        self.href       = params.href       || '#';
        self.callback   = params.callback   || null;
        
        self._button = $('<a/>').attr({
            'id': self.id,
            'class': 'btn',
            'href': self.href
        }).html('<span><span>'+self.text+'</span></span>');
        
        if (self.callback) {
            self._button.click(self.callback);
        }
        
        if (self.klass) { self._button.addClass(self.klass); }
        if (self.position) { self._button.addClass(self.position); }
        if (self.target) { self._button.addClass('target'); }
        
        return self._button;
    }
});

var EntProfile = new Class({
    __init__: function(self, member_id){
        self.id = member_id;
        
        SR.Dialog.createWithPayload({
            title: 'Member Profile',
            content: '<p>Fetching profile, please wait...</p>',
            buttons: [
                { label: 'Close', type: 'target', callback: function() { SR.Dialog.destroy(); }}
            ]
        });
        
        SR.Dialog.util.isLoading();
        
        // Get the profile
        self.getProfile();
    },
    
    getProfile: function(self){
        $.ajax({
            url: '/dashboard/ents/rpc/get_profile/'+self.id+'/',
            type: 'GET',
            data: {},
            dataType: 'json',
            success: function(json) {
                if (json.response == 'success') {
                    self.profile = json;
                    self.parseProfile();
                } else if (json.response == 'error') {
                    self.profile = false;
                    SR.Dialog.reloadWithError('<strong>An error occurred while requesting the user profile.</strong><br/>Explanation: '+json.reason);
                }
            },
            error: function(json) {
                self.profile = false;
                SR.Dialog.reloadWithError('An error occured while requesting the user profile.');
            }
        });
    },
    
    parseProfile: function(self){
        // Parse the groups and create a nice pretty array of group objects
        if (self.profile.groups) {
            self.groups = new Array();
            for (group in self.profile.groups) {
                self.groups.push({ id: group, name: self.profile.groups[group] || 'Untitled Group' });
            }
        } else {
            self.groups = false;
        }
        
        // Get all user properties and assign them directly to self
        for (key in self.profile.user) {
            self[key] = self.profile.user[key];
        }
        
        // If the user doesn't have an icon, replace it with the default one.
        if (!self.profile.user.icon) {
            self.icon = '/img/default_icon.png';
        }
        
        self.renderDialog();
    },
    
    getFullName: function(self){
        if (self.first_name && self.last_name) {
            return self.first_name+' '+self.last_name;
        } else if (self.first_name || self.last_name) {
            return self.first_name+self.last_name;
        } else {
            return self.username;
        }
    },
    
    getShortName: function(self){
        return (self.first_name) ? self.first_name : self.username;
    },
    
    renderDialog: function(self){
        self.content = new Array(
            '<div class="memberProfile clearafter">',
                '<div class="memberMeta clearafter">',
                    '<img class="memberIcon" src="'+self.icon+'" alt="" />',
                    '<h4 class="name">'+self.getFullName()+'</h4>',
                    '<h5 class="email">'+self.email+'</h5>');
                if (self.groups) {
                    var group_strings = new Array();
                    
                    for (var i=0; i < self.groups.length; i++) {
                        var suffix = ', ';
                        if (i == self.groups.length-1) {
                            suffix = '';
                        } else if (i == self.groups.length-2) {
                            suffix = ' and ';
                        }
                        var group_string = '<a href="/dashboard/ents/'+self.groups[i].id+'/">'+self.groups[i].name+'</a>'+suffix;
                        group_strings.push(group_string);
                    };
                    
                    self.content.push('<p>'+self.getShortName()+' belongs to the '+group_strings.join('')+' group'+self.groups.length.pluralize()+'.</p>');
                } else {
                    self.content.push('<p>This member isn\'t a part of a group.');
                };
        self.content.push('</div>'),
        
        SR.Dialog.util.isDoneLoading();
        SR.Dialog.reloadWithPayload({
            title: 'Member Profile',
            content: self.content.join('\n'),
            buttons: [
                { label: 'Close', type: 'target', callback: function() { SR.Dialog.destroy(); }}
            ]
        });
    }
});

//////////
// onLoad
//////////
$(document).ready( function() {
    SR.Message.init();
    
    $(function() {
        $('ul#srMenu > li > a.expandable').toggle(function() {
            $(this).parent().addClass('active');
            return false;
        }, function() {
            $(this).parent().removeClass('active');
            return false;
        });
    });
    
    $('a.memberProfile').bind('click', function(event) {
        var member_id = $(this).getID();
        var profile = new EntProfile(member_id);
        return false;
    });
    
});
