/* JSLint global defs (for debugging) */
/*global r, $j, jQuery, window, document*/

/* DEGUG CODE CHECKS 
 * The following code checks to see if Firebug is available.
 * If it isn't it does two things
 *    1 - create a dummy console object with dummy log function
 *    2 - create a dummy fireunit object with dummy unit test functions
 * This means that tests can be left in the code and nothing will break.
 * Obviously debug code should be kept out of the code, but this makes sure that
 * if it does happen - nothing breaks.
 * */
if (typeof(console) === undefined){
    var console = {log:function(){}};
    var fireunit = {
      ok : function(){},
      compare : function(){},
      reCompare : function(){},
      testDone : function(){},
      forceHttp : function(){},
      registerPathHandler : function(){},
      id : function(){},
      test : function(){},
      value : function(){},
      runTests : function(){},
      mouseDown : function(){},
      click : function(){},
      focus : function(){},
      key : function(){},
      panel : function(){},
      privilege : function(){}
    };
}
/* END DEGUG CODE CHECKS */

function regNS(ns) { //register namespace for objects.
    var nsParts = ns.split(".");
    var root = window;
    for (var i=0; i< nsParts.length; i++) {
        if(typeof root[nsParts[i]] === 'undefined'){
            root[nsParts[i]] = {};
        }
        root = root[nsParts[i]];
    }
}

regNS('r.page'); // setup for individual page namespaces
r.page.location = function(){
    var priv = {
        parsequerystring : function(query) {
          var qsParam = [];
          var parms = query.split('&');
          for (var i=0; i<parms.length; i++) {
            var pos = parms[i].indexOf('=');
            if (pos > 0) {
              var key = parms[i].substring(0,pos);
              var val = parms[i].substring(pos+1);
              qsParam[key] = val;
            }
          }
          return qsParam;
        },
        strloc : window.location.toString(),
        locall : "",
        loc : ""
    };
    priv.locall = priv.strloc.substring(7); //remove "http://"
    if (priv.locall.indexOf('?') > 0){
        priv.loc = priv.locall.substring(0, priv.locall.indexOf('?')); //remove query string
    } else {
        priv.loc = priv.locall;
    }
    var pub = {
        protocol : priv.strloc.substring(0, priv.strloc.indexOf(':')),
        path : priv.loc.substring(priv.loc.indexOf('/'), priv.loc.lastIndexOf('/')+1),
        host : priv.loc.substring(0, priv.loc.indexOf('/')),
        query : window.location.search.substring(1)
    };
    if (priv.loc.lastIndexOf('/') > priv.loc.lastIndexOf('?') && priv.loc.lastIndexOf('/') < (priv.loc.length -1 )){
        pub.path = priv.loc.substring(priv.loc.indexOf('/'), priv.loc.length) + "/";
    } //fixes dropped slashes
    pub.querydata = priv.parsequerystring(pub.query);

    return pub;
}();

/* Radar UI code */
regNS('r.ui');
r.ui.version = "0.1";
r.ui.description = "UI code that is generic across the site.";

r.ui.page = $j('body');
r.ui.viewport = $j(window);

//UI Functions
r.ui.getView = function(vtype){
    vtype = (typeof vtype === 'undefined') ? 'view' : vtype;
    return (vtype === 'view') ? this.viewport : this.page;
}; 
r.ui.ctrHoriz = function(elem, vtype){
    var view = this.getView(vtype);
    var obj = $j(elem); 
    obj.css({left : ((view.width()/2) - obj.width()/2)});
};
r.ui.ctrVer = function(elem, vtype){
    var view = this.getView(vtype);
    var obj = $j(elem); 
    obj.css({top : ((view.height()/2) - obj.height()/2)});
};
r.ui.ctrInView = function(elem){
    r.ui.ctrVer(elem);
    r.ui.ctrHoriz(elem);
};
r.ui.ctrOnPage = function(elem){
    r.ui.ctrVer(elem, "page");
    r.ui.ctrHoriz(elem, "page");
};

r.ui.qtrVer = function(elem, vtype){
    var view = this.getView(vtype);
    var obj = $j(elem); 
    r.ui.ctrHoriz(elem, vtype);
    obj.css({top : ((view.height()/4) - obj.height()/2)});
};

r.ui.ctrInViewAbsolute = function(elem){
    //IE6 workaround as it doesn't support position: fixed.
    var view = r.ui.viewport;
    var obj = $j(elem); 
    obj.css({top : (((view.height()/2) - obj.height()/2) + view.scrollTop())});
    obj.css({left : (((view.width()/2) - obj.width()/2) + view.scrollLeft())});
    obj.css({position: "absolute"});
};

r.ui.createLimitTextCount = function(limit, textbox, limitbox){
    var currval = $j(textbox).val();
    if (currval === undefined){currval = "";} 
    $j(limitbox).html(currval.length + "/" + limit);
    $j(textbox).bind("keyup", function(e){
        var currlength = $j(textbox).val().length;
        var limittext = "";
        if (currlength > limit){
            limittext = "<span class=\"over\">" + currlength + "</span>";
        } else {
            limittext = currlength;
        }
        $j(limitbox).html( limittext + "/" + limit);
    });
};

/* Mouse & Cursor methods and data */
r.ui.mouse = function(){
    var pub = {
        x : 0,
        y : 0
    };
    
    $j().mousemove(function(e){
      pub.x = e.pageX;
      pub.y = e.pageY;
    });
    
    return pub;
}();

regNS('r.ui.msgbox');

//MESSAGEBOX FUNCTIONS
r.ui.msgbox.create = function(id){
    if(id === "undefined"){id = "uiMsgbox";}
    var htmltxt = '<div id="' + id + '"></div>';
    $j('body').append(htmltxt);
    var msgbox = $j('#'+id);
    msgbox.css({
        position : "fixed",
        display : "none"
    });
    return msgbox;
};

//MESSAGEBOX TYPES/CLASSES

r.ui.overlay = function(){
    var initOverlay = function(){
        var overlay = r.ui.msgbox.create('overlay');
        overlay.css({
            width: "100%", 
            height: "100%", 
            background: "black", 
            opacity: "0.7", 
            top: 0, 
            left: 0
        });
        return overlay;
    };
    
    var priv = {
        
    };
    
    var pub = {
        show : function(){
            priv.overlay.fadeIn(100);
        },
        hide : function(){
            priv.overlay.fadeOut(100);
        }
    };
    
    $j(document).ready(function(){
       priv.overlay = initOverlay();
    });
    
    return pub;
}();

r.ui.msgbox.lightbox = function(){
    var priv = {
    
    };
    var pub = { 
      fullsizeadjust : function (popup, content) {
          var imgwidth = $j('#fullSizeImage').width();
          $j(popup).css({top : 30});
          $j(content).css({height: "auto", width: imgwidth});
        }
    };
    $j(document).ready(function(){
        $j('.lbOn').bind("click", function(e){
            // TODO: disabled overlay because it shows up on top of the image in IE7. 2009-02-25 rlathanh 
            // r.ui.overlay.show();
            pub.content = $j(this).attr("rel");
            $j('#' + pub.content).show();
            if(pub.content == "fullSizePopup"){
              pub.fullsizeadjust('#fullSizePopup', '#' + pub.content);
            }
            
        });
        $j('.lbAction').bind("click", function(e){
            $j('#' + pub.content).hide();
            r.ui.overlay.hide();
        });
    });
    
    return pub;
}();

r.ui.msgbox.slide = function(){
    var initSlideWindow = function(){
        var slideObj = r.ui.msgbox.create('uiSlide');
        slideObj.css({
            top : 0,
            "border-top" : 0
        });
        return slideObj;
    };
    
    var priv = {
        slideObj : {},
        init : initSlideWindow
    };
    
    var pub = {
        create : function(){
            priv.slideObj = priv.init();
        },
        add : function(val){
            priv.slideObj.append(val);
        },
        clear : function(){
            priv.slideObj.empty();
        },
        remove : function(val){
            priv.slideObj.remove(val);
        },
        toggle : function(){
            priv.slideObj.slideToggle();
        },
        open : function(){
            r.ui.ctrHoriz(priv.slideObj);
            priv.slideObj.slideDown();
        },
        close : function(){
            priv.slideObj.slideUp();
        },
        openTrigger : function(event, obj){
            obj.bind(event, this.open);
        },
        closeTrigger : function(event, obj){
            if (obj === "self"){obj = priv.slideObj;}
            obj.bind(event, this.close);
        } 
    };
    
    return pub;
}(); //module method

r.ui.msgbox.modal = function(){
    var initModalWindow = function(){
        var modalObj = r.ui.msgbox.create('uiModal');
        modalObj.css({});
        return modalObj;
    };
    
    var bindtoResize = function(){
        r.ui.viewport.resize(function(e){
            r.ui.ctrInView(priv.modalObj);
        });
    };
    
    var priv = {
        modalObj : {},
        overlay : r.ui.overlay,
        init : initModalWindow,
        bindResize: bindtoResize
    };
    
    var pub = {
        create : function(){
            priv.modalObj = priv.init();
            priv.bindResize();
        },
        add : function(val){
            priv.modalObj.append(val);
        },
        clear : function(){
            priv.modalObj.empty();
        },
        remove : function(val){
            priv.modalObj.remove(val);
        },
        toggle : function(){
            priv.modalObj.slideToggle();
        },
        open : function(){
            priv.overlay.show();
            r.ui.ctrInView(priv.modalObj);
            priv.modalObj.fadeIn("fast");
        },
        close : function(){
            priv.overlay.hide();
            priv.modalObj.fadeOut("fast");
        },
        openTrigger : function(event, obj){
            obj.bind(event, this.open);
        },
        closeTrigger : function(event, obj){
            if (obj === "self"){obj = priv.modalObj;}
            obj.bind(event, this.close);
        } 
    };

    
    return pub;
}(); //module method

//INFOBOX (aka FOAF) Code
r.ui.msgbox.infoBox = function(){
    // TODO-X ONE infoox Object that shows the content from other elements injected into it
}();

//ALERTS code
r.alerts = function() {
    var pub = {
        accept : function(e) {
            e.preventDefault();
            var params = { action: "accept",
                           friendRequestId: $j(e.target).parent().parent().find("input[name='friendRequestId']").val(),
                           groupId: $j(e.target).parent().parent().find("select[name='groupId']").val() 
            };
            var friendname = $j(e.target).attr("username");
            $j.post("/confirmFriend.ajax", params, function(data){
                $j(e.target).parent().parent().parent().html('You are now friends with <a href="/people/'+ friendname + '">' + friendname + '</a>.');
            });
        },
        ignore : function(e) {
            e.preventDefault();    
            var params = { action: "ignore",
                           friendRequestId: $j(e.target).parent().parent().find("input[name='friendRequestId']").val() 
            };
            var friendname = $j(e.target).attr("username");
            $j.post("/confirmFriend.ajax", params, function(data){
                  $j(e.target).parent().parent().parent().html('You ignored a friend request from <a href="/people/'+ friendname + '">' + friendname + '</a>.');
            });
        }
    };

    $j(document).ready(function(){
        $j("button.friend_request_accept").bind("click", pub.accept);
        $j("a.friend_request_ignore").bind("click", pub.ignore);
        $j('.alert .request select').bind("change", function(e){
            //this should be able to be abstracted out (as it's basically a repeat of the addfriend popup).
              var gval = $j(this).find('option:selected').val();
              if (gval === "create"){
                $j(this).next().hide();
                $j(this).hide();
                $j(this).after('<span id="createList"><input type="text" maxlength="12"/>&nbsp;&nbsp;<button class="input_submit">Create</button></span>');
                $j('#createList button').bind("mouseover", function(e){$j(this).addClass('hover');});
                $j('#createList button').bind("mouseout", function(e){$j(this).removeClass('hover');});
                $j('#createList button').bind("newlist", function(e, listid){
                    var newlist = $j(this).siblings('input').val();
                    $j('#createList').hide();
                
                    var list = $j(this).parent().parent().find('select');
                    var options = list.find('option');
                    var divider = (options.length - 2);
                    $j('.alert .request select').map(function(){
                      $j(this).find('option:eq('+ divider +')').before('<option value="'+listid+'">'+newlist+'</option>');
                    });
                    list.find('option:eq('+ divider +')').attr("selected", true);
                    list.show();
                    list.siblings('span:not(#createList)').show();
                    $j('#createList').remove();
                });
                $j('#createList button').bind("click", function(e){
                    e.preventDefault();
                    var newlist = $j(this).siblings('input').val();
                    var options = {
                      trigger : this  
                    };
                    r.friendslist.create(newlist, options);
                });
              }
          });
            
    });
    
    return pub;
}();

//Form functions
regNS('r.forms');
r.forms.createParameterString = function(form, fieldIDs){ //Ajax methods don't really need this, but just in case.'
    var parameterString = "";
    var i;
    for (i = 0; i < fieldIDs.length; i++) {
        var field = form.children("#" + fieldIDs[i]);
        if (field.length > 0) {
            if (parameterString !== "") {
                parameterString = parameterString + '&';
            }
            parameterString = parameterString + fieldIDs[i] + '=' + encodeURIComponent($j.trim(field.val()));
        }
    }
    return parameterString;
};

//Validaton functions
regNS('r.valid'); 
r.valid.illegalChars = /[^A-Za-z0-9]/;
r.valid.notAlphaNumOrSpace = /[^A-Za-z0-9 ]/;
r.valid.passwordPtn = /^\w{1,30}$/;

r.valid.email = function(email) {
    //basic, and permissive, email address validation
    if (email.length === 0) {
        return true;
    }
    // TLD checking turned off by default
    var i = 0;
    var checkTLD=0;
    var knownDomsPat=/^(com|net|org|edu|int|mil|gov|arpa|biz|aero|name|coop|info|pro|museum)$/;
    var emailPat=/^(.+)@(.+)$/;
    var specialChars="\\(\\)><@,;:\\\\\\\"\\.\\[\\]";
    var validChars="\[^\\s" + specialChars + "\]";
    var invalidChars=/[!%,;:<>$#&`|{}~?\"\'\(\)\/\\\]\[]/;
    var quotedUser="(\"[^\"]*\")";
    var ipDomainPat=/^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/;
    var atom=validChars + '+';
    var word="(" + atom + "|" + quotedUser + ")";
    var userPat=new RegExp("^" + word + "(\\." + word + ")*$");
    var domainPat=new RegExp("^" + atom + "(\\." + atom +")*$");
    var matchArray=email.match(invalidChars);
    if (matchArray !== null) {
        return false;
    }
    
    matchArray=email.match(emailPat);
    if (matchArray===null) {
        return false;
    }
    var user=matchArray[1];
    var domain=matchArray[2];
    for (i=0; i<user.length; i++) {
        if (user.charCodeAt(i)>127) {
            return false;
        }
    }
    for (i=0; i<domain.length; i++) {
        if (domain.charCodeAt(i)>127) {
            return false;
        }
    }
    if (user.match(userPat)===null) {
        return false;
    }
    var IPArray=domain.match(ipDomainPat);
    if (IPArray!==null) {
        for (i=1;i<=4;i++) {
            if (IPArray[i]>255) {
                return false;
            }
        }
        return true;
    }
    var atomPat=new RegExp("^" + atom + "$");
    var domArr=domain.split(".");
    var len=domArr.length;
    for (i=0;i<len;i++) {
        if (domArr[i].search(atomPat)==-1) {
            return false;
        }
    }
    if (checkTLD && domArr[domArr.length-1].length!=2 && 
        domArr[domArr.length-1].search(knownDomsPat)==-1) {
        return false;
    }
    if (len<2) {
        return false;
    }
    return true;
};

r.valid.radarname = function(elem) {
    var name = $j(elem).val();
    var data = {radarname : name};
    
    $j.get("/validateRadarName.ajax", data, function(data){
        if (data.errorCode === "") {
            r.page.current.displayStatus($j(elem), true);
        } else {
            r.page.current.displayStatus($j(elem), false);                    
        }
    }, "json");   
};

// Site wide Events setup
regNS('r.events');
regNS('r.events.utils'); //helper functions

r.events.apply = function(rules, dom, space){
    if (dom === undefined){
        dom = document;
    }
    if (space !== undefined){ //unbind the events for that handler in that namespace before reapplying
        jQuery.each(rules, function(selector, bind){
          $j(selector+space, dom).unbind(bind.trigger);
        });  
    } else {
        space = "";
    }
    var unsupportedLive = /^blur|focus|mouseenter|mouseleave|change|submit$/ ;
    
    jQuery.each(rules, function(selector, bind){
        $j(selector+space, dom).bind(bind.trigger, bind.call);
    });
};

r.events.utils.toggletip = function(elem){
    var tip =$j(elem).parents('.input_row').find('.tip');
    if (tip) {
      tip.toggle();
    }
};

r.events.navigation = function(){
    var priv = {
        isTyping : false
    };
    var pub = {
        currentPost : undefined,
        getCurrentPost : function(){
            var sTop = $j('html').scrollTop(); 
            if ($j('body').scrollTop() > 0 && $j('html').scrollTop() === 0){
                sTop = $j('body').scrollTop(); 
            }
            var pagepos = sTop;
            var posttop = 0;
            var i;
            for (i=0;i<priv.posts.length;i++){
                posttop = $j(priv.posts[i]).offset().top;
                if (posttop > pagepos){
                    pub.currentPost = priv.posts[i];
                    pub.currentPostIndex = i;
                    break;
                }
            }
            var currscroll = sTop;
        },
        scrollPosts : function(delta){
            pub.getCurrentPost();
            var htmltop = $j('html').scrollTop();
            var index = pub.currentPostIndex+delta;
            if (index >= 0 && index < (priv.posts.length)){
              try {
                  var topoffset = $j(priv.posts[index]).offset().top;
                  $j('html,body').animate({scrollTop: topoffset - 19},100);
              } catch(err){
                  //fail silently
              }
            }
            if (index < 0 || index >=priv.posts.length){
                var pagedelta = 0;
                if (index < 0){ pagedelta = -1;}
                if (index >=priv.posts.length){ pagedelta = 1;}
                pub.moveToPage(pagedelta);
            }
        },
        moveToPage : function(delta){
            var href = "";
            if (delta === -1){
                href = $j('.navigation a.newer').attr('href');
                if (href !== "" && href !== undefined ){
                  window.location = href;
                }
            }
            if (delta === 1){
                href = $j('.navigation a.older').attr('href');
                if (href !== "" && href !== undefined){
                  window.location = href;
                }
            }
        }
    };
    $j(document).ready(function(e){
      priv.posts = $j('table.post');
      var diff = 90 + ($j(priv.posts[priv.posts.length-1]).height()) + ($j('body').height() - $j(priv.posts[priv.posts.length-1]).offset().top);
      $j('body').css({paddingBottom:diff});
      $j('input[type=text]').focus(function(e){
          priv.isTyping = true;
      });
      $j('input[type=text]').blur(function(e){
          priv.isTyping = false;
      });
      $j(document).keypress(function(e){
          if ((e.which === 106 || e.keyCode === 106)&& priv.isTyping === false){ //j
            pub.scrollPosts(1);
          }
          if ((e.which === 107 || e.keyCode === 107) && priv.isTyping === false){ //k
            pub.scrollPosts(-1);
          }
          if (e.keyCode === 9 && priv.isTyping === false){ //tab
            pub.getCurrentPost();
            $j(priv.posts[pub.currentPostIndex]).find('.commentForm input[type=text]').focus();
            e.preventDefault();
            e.stopPropagation();
            return false;
          }
      });
      $j('.toolbar select.filter').bind("change",function(e){
          var val = $j(this).find('option:selected').val();
          if (val > 0){
            window.location = "/my-radar/posts/lists/"+val+"/";
          }
      });
    });
    return pub;
}; // add () to get it to run on load.

r.events.onload = function(){
    var priv = {
        runonload : function(){
              $j('.action').mouseover(function(e) {
                  $j(this).addClass("hover");
              });
              $j('.action').mouseout(function(e) {
                  $j(this).removeClass("hover");
              });
        }
    };
    
    $j(document).ready(function(){
        priv.runonload();
    });
    
}();

r.events.forms = function() {
    var priv = {
      setup : function(){
        $j('.input_submit').mouseover(function(e){
          $j(this).addClass('hover');
        });
        $j('.input_submit').mouseout(function(e){
          $j(this).removeClass('hover');
        });

        $j('.input_text').focus(function(e) {
          $j(this).addClass('focus');
          r.events.utils.toggletip(this);
        });
        $j('.input_text').blur(function(e) {
          $j(this).removeClass('focus');
          r.events.utils.toggletip(this);
        });
      }
    };
    // TODO-X validation code should get ported to here.
    $j(document).ready(priv.setup);
}();

r.events.reportcontrol = function(){
    var priv = {
        setup : function(){
            $j('button.reportuserpopup').bind("click",function(e){
                $j('#reportuserpopup').css({position: "fixed"});
                r.ui.qtrVer($j('#reportuserpopup'));
                if (typeof document.body.style.maxHeight === "undefined") { //if IE6
                    r.ui.ctrInViewAbsolute($j('#reportuserpopup'));
                }

                // TODO: disabled overlay because it shows up on top of the dialog in IE7. 2009-02-25 rlathanh
                // $j('#overlay').show();
                $j('button.reportuser').attr('token', $j(e.target).attr('token'));
                $j('#reportuserpopup').fadeIn("fast");
            });

            $j('button.reportuser').bind("click",function(e){
              var data = { token : $j(e.target).attr('token') };
              r.users.report(data);
              //now the UI/Visual part
              $j('#reportuserpopup .input_row').hide();
              $j('#reportuserpopup .input_row').next().show();
              $j('#reportuserpopup').animate({opacity: 0.9}, 4000, function(e){
                  $j('#reportuserpopup').fadeOut("fast", function(){
                      $j('#overlay').hide();
                      $j('#reportuserpopup span.highlighted').remove();
                      $j('#reportuserpopup .input_row').show();
                      $j(this).fadeOut();
                  });        
              });
            });

            $j('#reportuserpopup .cancel').bind("click",function(e){
                $j('#reportuserpopup').fadeOut("slow", function(e){
                  r.ui.overlay.hide();
                });   
            });
        }
    };
    // TODO-X use dedicated msgbox control to build this - get it out of the html code.
    $j(document).ready(priv.setup);
}();

regNS('r.users');
r.users.report = function(data) {
    $j.post("/reportUser.ajax", data);
};

regNS('r.users.friends'); //Users friends Namespace
r.users.friends = function(){
  var pub = {
      invite : function(data){
          $j.post("/addAsFriend.ajax", data);  
      },
      redirectToRegister : function(uname, eid){
          if (eid === undefined){ eid = "";}
          var locstring = "/register/add-friend/" + uname + "/people/" + uname + "/" + eid;
          if ($j('button.addfriendpopup').attr("gallery") == "true"){
              locstring = "/register/subscribe/" + uname;
          }
          window.location = (locstring);
      }
  };
  
  var priv = {
      addFriendSetup : function(name, buttonclass){
          $j('button.'+name).bind("click",function(e){
              var uname = $j(e.target).attr("username");
              if ($j('#'+name).hasClass('notregistered')){
                  var eid = $j('#entryContainer').attr('entryId');
                  pub.redirectToRegister(uname, eid);
              } else {
                  var popupdata = $j('#'+name).html();
                  $j('#'+name).remove();
                  $j('#overlay').after('<div id="'+name+'" class="ajaxpopup"></div>');
                  $j('#'+name).html(popupdata);
                  $j('#'+name+' .action').mouseover(function(e) {
                    $j(this).addClass("hover");
                  });
                  $j('#'+name+' .action').mouseout(function(e) {
                    $j(this).removeClass("hover");
                  });
                  priv.addFriendEvents(name, buttonclass, this);
                  $j('#'+name).css({position: "fixed"});
                  r.ui.qtrVer($j('#'+name));
                  if (typeof document.body.style.maxHeight === "undefined") { //if IE6
                      r.ui.ctrInViewAbsolute($j('#'+name));
                  }
                  $j('#'+name+'-true').hide();
                  $j('#'+name+'-false').hide();
                  $j('#'+name+'-'+$j(e.target).attr("gallery")).show();
                  r.ui.overlay.show();
                  $j('#'+name+' .username').html('<a href="/people/'+ uname +'/" target="_blank">' + uname + '</a> ');
                  $j('button.'+buttonclass).attr('gallery', $j(e.target).attr("gallery"));
                  $j('button.'+buttonclass).attr('token', $j(e.target).attr('token'));
                  $j('#'+name).fadeIn("fast");
              }
          });
      },
      addFriendEvents : function(name, buttonclass, popupButton) {
          //-- Bind to 'cancel' of creating a new list event
          $j('#'+name+' #createList .cancel').bind("click", function(e) {
              e.preventDefault();

              // hide the create a friend list
              $j('#'+name +' #createList').hide();

              // re-reveal the multi-select
              $j('#'+name +' select').show();
              // todo: change the selection of the multi-select back to index 0 
              // (so the user can choose "Create a new list..." again
          });

          //-- Bind to selection of "Create a new list..." event
          $j('#'+name+' select').bind("change", function(e){
              var gval = $j(this).find('option:selected').val();
              if (gval === "create") {

                  // hide the multi-select
                  $j(this).hide();
                  // reveal the createList div
                  $j('#createList').show();

                  // make "Create" button highlight on mouseover
                  $j('#createList button').bind("mouseover", function(e){$j(this).addClass('hover');});
                  $j('#createList button').bind("mouseout", function(e){$j(this).removeClass('hover');});

                  // Bind to the successful list creation: add the list to the options
                  $j('#createList button').bind("newlist", function(e, listid){
                    var newlist = $j(this).siblings('input').val();
                    $j('#createList').hide();

                    var options = $j('#'+name+' select option');
                    var divider = (options.length - 2);

                    $j('#'+name+' select option:eq('+ divider +')').before('<option value="'+listid+'">'+newlist+'</option>');
                    $j('#'+name+' select option:eq('+ divider +')').attr("selected", true);
                    $j('#'+name+' select').show();
                  });

                  // Bind to the "Create" button click
                  $j('#createList button').bind("click", function(e){
                      var newlist = $j(this).siblings('input').val();
                      r.friendslist.create(newlist, $j('#createList button'));
                  });
              }
          });

          //-- Bind to clicking on "Add as friend" (the one in the pop-up)
          $j('button.'+buttonclass).bind("click",function(e){
              var data = {};
              var gval = $j('#'+name+' option:selected').val();
              if (gval === "create"){
                  gval = $j('#newlist').attr('listid');
                  gval = gval*1; //make sure it's a number.
              }
              if ( gval > 0 && !isNaN(gval) ){ 
                  data.groupId = gval;
              }
              data.token = $j(e.target).attr('token');

              //-- Submit the friend request
              pub.invite(data);

              //-- Now the UI/Visual part
              // show a confirmation message 
              if ($j(e.target).attr('gallery') == "true"){
                $j('#'+name+' .input_row').after('<span class="highlighted">Added to My Radar.<span>');
              } else {
                $j('#'+name+' .input_row').after('<span class="highlighted">Friend request sent.<span>');
              }
              // hide the "Add as Friend" button (the one that opened the popup)
              $j(popupButton).hide();
              // hide the "Add as Friend" button (the one in the popup)
              $j(this).hide();
              // hide the row containing the "Add as Friend" button (that's now hidden)
              $j('#'+name+' .input_row').hide();
              // hide the popup
              $j('#'+name).animate({opacity: 0.9}, 2000, function(e){
                  $j('#'+name).fadeOut("fast", function(){
                      // un-lightbox
                      $j('#overlay').hide();
                      // remove the confirmation message
                      $j('#'+name+' span.highlighted').remove();
                      // re-allow the row containing the (hidden) "Add as Friend" button to show
                      $j('#'+name+' .input_row').show();
                      // fade out the pop-up
                      $j(this).fadeOut();
                  });
              });
          }); // end click handler for "Add as Friend" button (in the popup)  

          //-- Bind to clicking on "cancel" (the one in the pop-up)
          $j('#'+name+' p .cancel').bind("click",function(e){
              e.preventDefault();
              $j('#'+name+'').fadeOut("fast", function(e){
                r.ui.overlay.hide();
              });   
          });
      }
  };
  
  $j(document).ready(function(){
      priv.addFriendSetup('addfriendpopup', 'addfriend');
  });
  
  return pub;
}();

regNS('r.friendslist'); //Share to user Namespace
r.friendslist = function(){
  var pub = {
      create : function(newname, options) {
          if (options !== undefined){
              if(options.trigger !== undefined){ 
                options.success = function(data, txt){
                    if (data !== undefined){
                      $j(options).trigger('newlist', data);
                    }
                };
              }
          } else {
              options = {};
          }
          options.type = "post";
          options.url = "/createFriendList.ajax";
          options.data = {
              name : newname  
          };
          
          $j.ajax(options);
          
      },
      remove : function(gid){
          $j.post("/deleteFriendList.ajax", {groupId : gid});
      },
      rename : function(gid, newname, options){
          if (options === undefined){options = {};}
          options.url = "/renameFriendList.ajax";
          options.type = "post";
          options.data = {
              groupId : gid,
              name : newname  
          };
          $j.ajax(options);
      }
  };
  
  return pub;
 }();

regNS('r.users.share'); //Share to user Namespace
r.users.share = function(){
  var pub = {
      submit : function(){
          var params = {
            senderEmail : $j('#friendPickerForm #senderEmail').val(),
            addresses : $j('#friendPickerForm #addresses').val(),
            message : $j('#friendPickerForm #message').val(),
            entryId : $j('#friendPickerForm #entryId').val()
          };
          $j.post("/sendToEmail.ajax", params, function(data){
              $j('#addressesError').html(data.addressesError);
              $j('#senderEmailError').html(data.senderEmailError);
              if (data.addressesError === "" && data.senderEmailError === "") {
                  showFriendPickerSendSuccess();
                  //eventually this will look like the following line:
                  //r.page.current.shareSuccess();
              }
          }, "json");
      }
  };
  return pub;
}();


//=============================================================================
//== Commenting ===============================================================
//=============================================================================

regNS('r.users.comments'); //User commenting namespace
r.users.comments.post = function(elem, comForm, comWorking, comError, comText,
                                 cType, eid, onSuccess, tweet, fbPublish,
                                 ajaxType) {
    var comFilter = $j(elem).attr("commentFilter");
    if (comFilter == undefined){comFilter = "";}
    var text = comText.val();
    var urlid = "";
    if ($j.trim(text) === "") { return; } 
    var params = {
        newCommentEntryId : eid,
        newCommentText : text,
        pageEnding : "s",
        maximise : true,
        newCommentType : cType,
        tweet : tweet,
        fbPublish : fbPublish,
        cf : comFilter
    };
    if (ajaxType == "list") {
        urlid = "postCommentListPage";
    } else {
        urlid = "postComment";
    }
    $j.ajax({
        type: "POST",
        url: "/"+urlid+".ajax",
        data: params,
        beforeSend : function(xhr){
            comForm.height(comForm.height());
            comForm.children('div').css({opacity: 0.2});
            comForm.children('div .input_text').attr('disabled', true);
            comForm.children().unbind('click');
            comWorking.css({position:"absolute", right:"70px", top:"38px"});
            comWorking.show();
        },
        success: function(data){
          comText.val("").blur();
          onSuccess(data);
        },
        error: function (XMLHttpRequest, textStatus, errorThrown) {
          comError.children('#commentErrorText').html('Sorry, we could not post the comment.');
          comWorking.fadeOut();
          comError.fadeIn();
          comForm.children('div .input_text').removeAttr('disabled');
          comForm.children('div').css({opacity: 1});
        }
    });
};

function onPublitweetChange(entryId) {
    var tweet_e = $j('#commentTweet_' + entryId);
    var fbPublish_e = $j('#commentFbPublish_' + entryId);
    var whisperButton_e = $j('#whisperButton_' + entryId);

    var tweet = tweet_e.is(':checked');
    var fbPublish = fbPublish_e.is(':checked');
//    var tweet = tweet_e.attr('checked');
//    var fbPublish = fbPublish_e.attr('checked');
    if (tweet || fbPublish) {
        // disable whisper
        whisperButton_e.animate({ opacity : '0.3' }, 'slow');
        whisperButton_e.attr('disabled', true);
    } else {
        // enable whisper
        whisperButton_e.removeAttr('disabled');
        whisperButton_e.animate({ opacity : '1' }, 'fast');
    }
}


//=============================================================================
//== New User Prompts =========================================================
//=============================================================================

function r_nup_show(name) {
    var popup = $j("#prompt_popup_" + name);
    popup.fadeIn();
}

function r_nup_hide(name) {
    var popup = $j("#prompt_popup_" + name);
    popup.hide();
}

function r_nup_dismiss(name) {
    //-- get elements
    var masterDiv = $j("#newUserPrompts");
    var listDiv = $j("#newUserPromptsList");
    var promptDiv = $j("#prompt_" + name);

    // TODO- remove the HTML for these unused hidden elements
//    var successHeaderDiv = $j("#dynamicSuccessMessageBox");
//    var successDiv = $j("#prompt_success_" + name);


    //-- prepare request
    var params = {
        type : "post",
        url : "/newUserPrompts.ajax",
        data : {
            dismiss : name
        },
        beforeSend : function() {
            promptDiv.hide();
        },
        success : function(data) {
            if (!data)
                masterDiv.hide();
            else
                listDiv.html(data);
        }
    };


    //-- Perform task
    $j.ajax(params);

    return false;
}

function r_newUserRadarName_reveal() {
    var callback = function() {
        $j("#prompt_popup_newUserRadarName").fadeIn('slow');
    };
    setTimeout(callback, 2000);
}

function r_newUserRadarName_no() {
    var popupDiv = $j("#prompt_popup_newUserRadarName");

    //-- prepare request
    var params = {
        type : "post",
        url : "/newUserPrompts.ajax",
        data : {
            dismiss : "already_have_radar_name",
            noReplacements : "true"
        },
        beforeSend : function() {
            popupDiv.hide();
        }
    };


    //-- Perform task
    $j.ajax(params);

    return false;
}


function r_newUserFriends_reveal() {
    var callback = function() { $j('#thirdPartyFriendsLightbox').fadeIn('slow'); }
    setTimeout( callback, 2000 );
}

function r_newUserFriends_done() {
    $j('#thirdPartyFriendsLightbox').fadeOut('slow');
}
