<?_code
{
    use strict;
    use vars qw(%GET %POST $title $body);

    LJ::set_active_crumb('editfriendgrps');

    $title = $ML{'.title'};
    $body = "";

    my $err = sub {
        $title = "Error";
        $body = LJ::bad_input(@_);
        return;
    };

    # these are only used by the client-side for JS to play with.
    # we delete them because they may contain embedded NULLs, which
    # text_in won't like.
    delete $POST{'list_in'};
    delete $POST{'list_out'};
    
    unless (LJ::text_in(\%POST)) {
        $body = "<?badinput?>";
        return;
    }
    
    my $remote = LJ::get_remote();
    return $err->($ML{'error.noremote'})
        unless $remote;

    my $authas = $GET{'authas'} || $remote->{'user'};
    my $u = LJ::get_authas_user($authas);
    return $err->($ML{'error.invalidauth'})
        unless $u;

    # extra arguments for get requests
    my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : '';
    
    if ($POST{'mode'} eq "save") {
        my %res;
        $POST{'mode'} = "editfriendgroups";
        $POST{'user'} = $u->{'user'};
        $POST{'ver'} = $LJ::PROTOCOL_VER;
        LJ::do_request(\%POST, \%res, {
            'u' => $u,
            'noauth' => 1, 
        });
        
        if ($res{'success'} eq "OK") {
            $body .= "<?h1 $ML{'.saved.header'} h1?><?p $ML{'.saved.text'} p?>";
        } else {
            $body .= "<?h1 $ML{'Error'} h1?><?p $ML{'.error.text'} p?><?p $res{'errmsg'} p?>";
        }
        return;
    }
    
    my %res;
    LJ::do_request({ 'mode' => 'getfriends',
                     'user' => $u->{'user'}, 
                     'ver'  => $LJ::PROTOCOL_VER,
                     'includegroups' => 1 },
                   \%res, { 'u' => $u,
                            'noauth' => 1, });
    my @num_used;
    my @num_free;

    # authas switcher form
    $body .= "<form method='get' action='editgroups.bml'>\n";
    $body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n";
    $body .= "</form>\n\n";

    $body .= "<?h1 $ML{'.title'} h1?><?p $ML{'.text'} p?><?p $ML{'.text.sec'} p?><p>";
    $body .= "<form method='post' name='fg' action='editgroups.bml$getextra'>";
    $body .= "<input type='hidden' name='mode' value='save' />";
    for (my $i=1; $i<=30; $i++) {
        my $sort = 255;
        my $name = "";
        my $public = 0;
        if ($res{"frgrp_${i}_name"}) {
            $sort = $res{"frgrp_${i}_sortorder"}+0;
            $name = LJ::ehtml($res{"frgrp_${i}_name"});
            $public = $res{"frgrp_${i}_public"}+0;
            push @num_used, $i;
        } else {
            push @num_free, $i;
        }
        $body .= "<input type='hidden' name='efg_set_${i}_name' value='$name' />";
        $body .= "<input type='hidden' name='efg_set_${i}_sort' value='$sort' />";
        $body .= "<input type='hidden' name='efg_delete_${i}' value='0' />";
        $body .= "<input type='hidden' name='efg_set_${i}_public' value='$public' />";
    }
    for (my $i=1; $i<=$res{'friend_count'}; $i++) {
        my $user = $res{"friend_${i}_user"};
        my $mask = $res{"friend_${i}_groupmask"} || 1;
        $body .= "<input type='hidden' name='editfriend_groupmask_$user' value='$mask' />";
    }
    
    # escape strings for JavaScript
    my %T = qw(public  .group.public
               rename  .prompt.rename
               newname .prompt.newname
               delete  .confirm.delete
               max30   .error.max30
               );
    foreach (keys %T) { $T{$_} = LJ::ejs($ML{$T{$_}}); }
    
    $body .= <<"END_JS";
<SCRIPT LANGUAGE="JavaScript"><!--

 var selectedGroup = 0;

 function eraseList (list)
 {
     while (list.length) {
         list.options[0] = null;
     }
 }
 
 function groupClicked ()
 {
     var selIndex;

     var form = document.fg;
     var grouplist = form.list_groups;
     var inlist = form.list_in;
     var outlist = form.list_out;
     
     // figure out what they clicked, and bring their focus up to first free blank

     selIndex = grouplist.selectedIndex;
     if (selIndex == -1) { return; }
     var groupname = grouplist.options[selIndex].text;

     var newSelGroup = grouplist.options[selIndex].value;
     if (newSelGroup == selectedGroup) { return; }
     selectedGroup = newSelGroup;
     
     // clears the other "not in" and "in" boxes
     eraseList(inlist);
     eraseList(outlist);
   
     // iterate over all friends, putting them in one group or the other
     var i;
     for (i=0; i<form.elements.length; i++) {
         var name = form.elements[i].name;
         var mask = form.elements[i].value;
         if (name.substring(0, 21) == "editfriend_groupmask_") {
             var user = name.substring(21, name.length);
             
             var list = mask & (1 << selectedGroup) ? inlist : outlist;
             var optionName = new Option(user, user, false, false)
                 list.options[list.length] = optionName;
         }
     }
 }

 function moveItems (from, to, bitstatus)
 {
     var selindex;
     while ((selindex=from.selectedIndex) != -1)
     {
         var i;
         var item = new Option(from.options[selindex].text,
                               from.options[selindex].value,
                               false, true);

         from.options[selindex] = null;
         //to.options[to.options.length] = item;

         // find spot to put new item
         for (i=0; i<to.options.length && to.options[i].text < item.text; i++) { }
         var newindex = i;

         // move everything else down
         for (i=to.options.length; i>newindex; i--) {
                  to.options[i] = new Option(to.options[i-1].text,
                                        to.options[i-1].value,
                                        false,
                                        to.options[i-1].selected);
         }
         to.options[newindex] = item;

         // turn the groupmask bit on or off
         var user = item.value;
         var element = document.fg["editfriend_groupmask_"+user];
         var mask = element.value;
         if (bitstatus) {
             mask |= (1 << selectedGroup);
         } else {
             mask &= ~(1 << selectedGroup);
         }
         element.value = mask;
     }
 }

 function moveIn ()
 {
     if (! selectedGroup) { return; }
     var form = document.fg;
     var inlist = form.list_in;
     var outlist = form.list_out;
     moveItems(document.fg.list_out, document.fg.list_in, true);
 }
 function moveOut ()
 {
     if (! selectedGroup) { return; }
     moveItems(document.fg.list_in, document.fg.list_out, false);
 }

 function moveGroup (dir)
 {
     var list = document.fg.list_groups;
     var selindex = list.selectedIndex;
     if (selindex==-1) { return; }
     var toindex = selindex+dir;
     if (toindex < 0 || toindex >= list.options.length) { return; }
     var selopt = new Option(list.options[selindex].text,
                             list.options[selindex].value,
                             false,
                             list.options[selindex].selected);
     var toopt = new Option(list.options[toindex].text,
                            list.options[toindex].value,
                            false,
                            list.options[toindex].selected);
     list.options[toindex] = selopt;
     list.options[selindex] = toopt;    

     // stupid mozilla necessity:
     list.selectedIndex = toindex;

     setSortOrders();
 }

 function setSortOrders ()
 {
     var list = document.fg.list_groups;

     // set all their sort orders now
     var i;
     for (i=0; i<list.options.length; i++) {
         var item = list.options[i];
         var key = "efg_set_"+item.value+"_sort";
         document.fg[key].value = (i+1)*5;
     }
 }

 function realName (name)
 {
     var rname = name;
     var index = name.lastIndexOf(" $T{'public'}");
     if (index != -1) {
         rname = name.substr(0, index);
     }
     return rname;
 }
    
 function renameGroup ()
 {
     var list = document.fg.list_groups;
     var selindex = list.selectedIndex;
     if (selindex==-1) { return; }
     var item = list.options[selindex];

     var newtext = realName(item.text);
     newtext = prompt("$T{'rename'}", newtext);
     if (newtext==null || newtext == "") { return; }

     var gnum = item.value;
     document.fg["efg_set_"+gnum+"_name"].value = newtext;     
     if (document.fg["efg_set_"+gnum+"_public"].value == 1) {
         newtext = newtext + " $T{'public'}";
     }
     item.text = newtext;
 }

 function deleteGroup ()
 {
     var list = document.fg.list_groups;
     var selindex = list.selectedIndex;
     if (selindex==-1) { return; }
     var item = list.options[selindex];

     var conf = confirm("$T{'delete'}");
     if (!conf) { return; }

     // mark it to be deleted later
     var gnum = item.value;
     document.fg["efg_delete_"+gnum].value = "1";
     document.fg["efg_set_"+gnum+"_name"].value = "";

     // as per the protocol documentation, unset bit on all friends
     var i;
     var form = document.fg;
     for (i=0; i<form.elements.length; i++) {
         var name = form.elements[i].name;
         if (name.substring(0, 21) == "editfriend_groupmask_") {
             var user = name.substring(21, name.length);
             var mask = form.elements[i].value;
             mask &= ~(1 << gnum);
             form.elements[i].value = mask;
         }
     }

     // clean up the UI
     list.options[selindex] = null;
     eraseList(document.fg.list_in);
     eraseList(document.fg.list_out);
 }

 function makePublic ()
 {
     var list = document.fg.list_groups;
     var selindex = list.selectedIndex;
     if (selindex==-1) { return; }
     var item = list.options[selindex];

     var name = realName(item.text);
     item.text = name + " $T{'public'}";
   
     var gnum = item.value;
     document.fg["efg_set_"+gnum+"_public"].value = "1";
 }

 function makePrivate ()
 {
     var list = document.fg.list_groups;
     var selindex = list.selectedIndex;
     if (selindex==-1) { return; }
     var item = list.options[selindex];

     var name = realName(item.text);
     item.text = name;     

     var gnum = item.value;
     document.fg["efg_set_"+gnum+"_public"].value = "0";
 }

 function newGroup ()
 {
     var form = document.fg;
     var i;
     var foundg = false;
     for (i=1; i<=30; i++) {
         if (form["efg_delete_"+i].value==1) { continue; }
         if (form["efg_set_"+i+"_name"].value!="") { continue; }
         foundg = true;
         break;	 
     }
     if (! foundg) {
         alert("$T{'max30'}");
         return;
     }
     var gnum = i;
     var groupname = prompt("$T{'newname'}", "");
     if (groupname==null || groupname=="") { return; }

     form["efg_set_"+gnum+"_name"].value = groupname;
     var item = new Option(groupname, gnum, false, true);
     var list = form.list_groups;
     list.options[list.options.length] = item;
     list.options.selectedIndex = list.options.length-1;
     setSortOrders();
     groupClicked();
 }

// --></SCRIPT>
END_JS

    $body .= "<table cellspacing='5'><tr valign='bottom'>";
    $body .= "<td nowrap='1' colspan='2'><strong>$ML{'.yourgroups'}</strong></td>";
    $body .= "<td nowrap='1' colspan='2'><strong>$ML{'.ingroup.not'}</strong></td>";
    $body .= "<td nowrap='1'><strong>$ML{'.ingroup'}</strong></td></tr>";

    $body .= "<tr valign='top'>";
    $body .= "<td><select name='list_groups' style='width: 150px;' size='15' onchange='groupClicked();'>";
    foreach my $num (sort { $res{"frgrp_${a}_sortorder"} <=> 
                            $res{"frgrp_${b}_sortorder"} } @num_used) {

        my $listname = $res{"frgrp_${num}_name"};
        $listname .= " $ML{'.group.public'}" if $res{"frgrp_${num}_public"};
        $body .= "<option value='$num'>" . LJ::ehtml($listname);
    }

    $body .= "</select></td>";
 
    $body .= "<td valign='middle'>";
    $body .= "<input type='button' value='$ML{'.btn.mv.up'}' onClick='moveGroup(-1);' /><br /><br />";
    $body .= "<input type='button' value='$ML{'.btn.mv.down'}' onClick='moveGroup(1);' /></td>";

    $body .= "<td><select name='list_out' multiple='1' size='15'>";
    $body .= "<option value=''>---------------</option></select></td>";

    $body .= "<td valign='middle'>";
    $body .= "<input type='button' onClick='moveIn();' value='&gt;&gt;' /><br /><br />";
    $body .= "<input type='button' onClick='moveOut();' value='&lt;&lt;' /></td>";

    $body .= "<td><select name='list_in' multiple='1' size='15'>";
    $body .= "<option value=''>---------------</option></select></td>";

    $body .= "</tr><tr><td colspan='2'>";
    $body .= "<nobr>";
    $body .= "<input type='button' value='$ML{'.btn.ge.new'}' onClick='newGroup();' /> ";
    $body .= "<input type='button' value='$ML{'.btn.ge.del'}' onClick='deleteGroup();' /> ";
    $body .= "<input type='button' value='$ML{'.btn.ge.ren'}' onClick='renameGroup();' />";
    $body .= "</nobr><br /><nobr>";
    $body .= "<input type='button' value='$ML{'.btn.gs.public'}' onClick='makePublic();' /> ";
    $body .= "<input type='button' value='$ML{'.btn.gs.private'}' onClick='makePrivate();' />";
    $body .= "</nobr></td><td></td><td></td><td></td>";

    $body .= "</tr></table>";

    $body .= "<?h1 $ML{'.done.header'} h1?><?p $ML{'.done.text'} p?>";
    $body .= "<?p <input type='submit' value='$ML{'.done.btn'}' /> p?>";
    $body .= "</form>";

    return;
}
_code?><?page
title=><?_code return $title; _code?>
body=><?_code return $body; _code?>
page?><?_c <LJDEP>
link: htdocs/login.bml
post: htdocs/friends/editgroups.bml
</LJDEP> _c?>
