<?_code

 use strict;
 use vars qw(%GET %POST $title $body);

 my $dbr = LJ::get_db_reader();

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

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

 $POST{'oldkeywords'} = [ split('\0', $POST{'oldkeywords'}) ];

 unless (LJ::text_in(\%POST)) {
     return $err->("Invalid UTF-8 Input");
 }

 my $remote = LJ::get_remote();
 return $err->($ML{'error.noremote'})
     unless $remote;

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

 my %secopts = ( 'public' => $ML{'label.security.public'},
                 'friends' => $ML{'label.security.friends'},
                 'private' => $ML{'label.security.private'}, );

 if ($memoryu->{'journaltype'} eq "C") {
     $secopts{'private'} = $ML{'label.security.maintainers'};
     $secopts{'friends'} = $ML{'label.security.members'};
 }

 my $sth;
 my $journal = $GET{'journal'};
 my $ditemid = $GET{'itemid'}+0;

 # OK.  the memories schema is weird and stores *display* itemids in the database.
 # additionally, we distinguish precluster itemids because they're stored without a userid.
 # it's too late to fix it in the db, so we just work around it--
 # all new memories still get userid+ditemid because we can't change the ditemid/itemid problem,
 # but old-style itemids get fixed up to userid+ditemid.

 # *however*, when editing old itemids we need to keep around
 # the old-style ditemid so we can still edit it.

 # to keep this all sorted out, we fixup variables like this:
 #   - itemid -- real, new-style itemid
 #   - ditemid -- display itemid (with anum)
 #   - dbitemid -- itemid that is in the database;
 #                 usually same as ditemid, but different for old-style itemids.

 my $dbitemid = $ditemid;
 my $itemid;
 my $oldstyle = 0;
 my $ju;
 my $jid;

 my $anum;

 if ($journal) {
     $ju = LJ::load_user($journal);
     $jid = $ju->{'userid'};
     $anum = $ditemid % 256;
     $itemid = int($ditemid / 256);
 } else {
     # old-style item url?
     my $newids = LJ::get_newids('L', $ditemid);
     if ($newids) {
         ($jid,  $itemid) = @$newids;
         $ju = LJ::load_userid($jid);
         $oldstyle = 1;
     }
 }

 unless ($ju && $itemid) {
     $title = $ML{'Error'};
     $body = $ML{'error.nojournal'};
     return;
 }

 my $log = LJ::get_log2_row($ju, $itemid);
 unless ($log) {
     $title = $ML{'Error'};
     $body = "Error retrieving data to add a memory.";
     return;
 }

 # check to see if it already is memorable (thus we're editing, not adding);
 my $memory = LJ::Memories::get_by_ditemid($memoryu, $oldstyle ? 0 : $jid, $ditemid);

 if ($oldstyle) {
     # ditemid was an old-style itemid, so we update it to the new style.
     $anum = $log->{anum};
     $ditemid = $itemid<<8 + $anum;
 }

 # get keywords user has used
 my $exist_kw = LJ::Memories::get_keywords($memoryu);
 unless ($exist_kw) {
     $title = $ML{'Error'};
     $body = "Error fetching existing keywords.";
     return;
 }

 if ($POST{'mode'} eq "") 
 {
     my ($des, $keywords);

     my @all_keywords;
     my %selected_keyword;
     @all_keywords = sort values %$exist_kw;

     if (defined $memory) {
         $title = $ML{'.title.edit_memory'};
         $des = $memory->{'des'};
         my $kwids = LJ::Memories::get_keywordids($memoryu, $memory->{memid}) || [];
         foreach my $kwid (@$kwids) {
             my $kw = $exist_kw->{$kwid};
             next if ($kw eq "*");
             if ($keywords) { $keywords .= ", "; }
             $keywords .= $kw;
             $selected_keyword{$kw} = 1;
         }
         if (!$log || ($jid && $log->{'anum'} != $anum))
         {
             LJ::Memories::delete_by_id($memoryu, $memory->{memid});
             LJ::Memories::updated_keywords($memoryu);
             $title = $ML{'Error'};
             $body = $ML{'.error.entry_deleted'};
             return;
         }

     } 
     elsif (!$log || ($jid && $log->{'anum'} != $anum))
     {
         $title = $ML{'Error'};
         $body = $ML{'error.noentry'};
         return;
     }
     else
     {
         $title = $ML{'.title.add_memory'};

         # this is a new memory.
         my $user = LJ::get_username($log->{'journalid'});
         my $dt = substr($log->{'eventtime'}, 0, 10);
         my $item = LJ::Talk::get_journal_item($ju, $itemid);
         my $subject = $item->{'subject'};

         $des = "$dt: $user: $subject";
     }

     # it'd be nice to only show the authas form when adding an entry and not
     # when editing one, but if user u is logged in and has post p as a memory
     # already then wants to add it to community c, when u clicks the "add memory"
     # link on p, u gets the "edit entry" page and they need to be able to switch
     # to c.
     $body .= "<form method='get' action='memadd.bml'>\n";
     $body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n";
     $body .= LJ::html_hidden(journal => $GET{journal}) if $GET{journal};
     $body .= LJ::html_hidden(itemid => $GET{itemid});
     $body .= "</form>\n\n";

     LJ::text_out(\$des);
     LJ::text_out(\$keywords);

     $body .= $ML{'.add_previous'};

     my $getextra = "?itemid=$dbitemid";
     $getextra .= "&amp;authas=$authas" if $authas ne $remote->{'user'};
     # we still need to pass the dbitemid and not the itemid to ourself.
     $getextra .= "&amp;journal=$journal" unless $oldstyle;

     $body .= "<form method='post' action='memadd.bml$getextra'>";
     $body .= LJ::html_hidden(mode => "save");

     $body .= "<table cellpadding='4'>";
     $body .= "<tr><th align='right' valign='top'>$ML{'.description'}</th><td>";
     $body .= LJ::html_text({name => 'des', value => $des, maxlength => LJ::CMAX_MEMORY, size => 40});
     $body .= "<br /><small>$ML{'.description.text'}</small></td></tr>";

     $body .= "<tr><th align='right' valign='top'>$ML{'.keywords'}</th><td>";
     $body .= LJ::html_text({name => 'keywords', maxlength => LJ::CMAX_KEYWORD, size => 40, value => $keywords});
     $body .= "<br /><small>$ML{'.keywords.text'}</small><br />";

     if (@all_keywords) {
         my $size = scalar(@all_keywords);
         $size = 15 if $size > 15;
         $body .= "<small>$ML{'.keywords.select'}</small><div style='margin-left: 30px;'>";
         $body .= LJ::html_select( { name => 'oldkeywords', size => $size, multiple => 1,
                                     selected => [ keys %selected_keyword ], noescape => 1 },
                                   map { (LJ::ehtml($_), LJ::ehtml($_)) } @all_keywords);
         $body .= "</div><small>$ML{'.multiple_selections'}</small>";
     } else {
         $body .= "<small>$ML{'.keywords.example'}</small>";
     }

     $body .= "</td></tr>\n";
     $body .= "<tr><th align='right' valign='top'>$ML{'.security'}</th><td>";
     $body .= LJ::html_select({name => 'security', selected => defined $memory ? $memory->{'security'} : undef},
                              map { ($_, $secopts{$_}) } qw(public friends private));
     if ($memoryu->{'journaltype'} eq "C") {
         $body .= "<br /><small>$ML{'.whocansee.comm'}</small></td></tr><tr><th></th><td>\n";
     } else {
         $body .= "<br /><small>$ML{'.whocansee'}</small></td></tr><tr><th></th><td>\n";
     }
     $body .= LJ::html_submit(undef, $ML{'.form.submit'});
     $body .= LJ::html_submit(undef, $ML{'.form.reset'}, {type => 'reset'}) if defined $memory;
     $body .= "</td></tr></table></form>";

     return;
 }

 if ($POST{'mode'} eq "save") 
 {
     my $dbh = LJ::get_db_writer();

     if (! $POST{'des'}) {
         # then we're deleting.
         if (defined $memory) {
             LJ::Memories::delete_by_id($memoryu, $memory->{memid});
             LJ::Memories::updated_keywords($memoryu);
             $title = $ML{'.title.deleted'};
             $body = "<?h1 $ML{'.error.deleted.title'} h1?><?p " . 
                     BML::ml(".error.deleted.body", { 'desc' => $memory->{'des'} }) .
                     "p?>";
             return;	     
         } else {
             $title = $ML{'Error'};
             $body = "<?h1 $ML{'.error.nodescription.title'} h1?><?p ";
             $body .= BML::ml('.error.nodescription.body');
             $body .= " p?>";
             return;
         }
     }

     #### we're inserting/replacing now into memories
     my @keywords;
     { 
         my %kws;
         foreach (split(/\s*,\s*/, $POST{'keywords'})) { $kws{$_} = 1; }
         # oldkeywords were split at the beginning
         foreach (@{$POST{'oldkeywords'}}) { $kws{$_} = 1; }
         @keywords = keys %kws;
     }
     if (scalar(@keywords) > 5) { 
         $title = $ML{'Error'};
         $body = "<?h1 $ML{'Error'} h1?><?p $ML{'.error.fivekeywords'} p?>";
         return;
     }
     @keywords = grep { $_ } map { s/\s\s+/ /g; LJ::trim($_); } @keywords;
     push @keywords, "*" unless (@keywords);
     my @kwid;

     my $needflush = 0;
     foreach my $kw (@keywords) {
         if (length($kw) > 40) {
             $title = $ML{'Error'};
             $body = "<?h1 $ML{'Error'} h1?><?p " .
                     BML::ml(".error.maxsize", { 'keyword' => LJ::ehtml($kw) }) . "p?>";
             return;
         }

         my $kwid = LJ::get_keyword_id($memoryu, $kw);
         $needflush = 1 unless defined $exist_kw->{$kwid};
         push @kwid, $kwid;
     }

     unless (exists $secopts{$POST{'security'}}) {
         $title = $ML{'Error'};
         $body = $ML{'.error.invalid_security'};
         return;
     }

     my $des = LJ::text_trim($POST{'des'}, LJ::BMAX_MEMORY, LJ::CMAX_MEMORY);
     my $sec = $POST{'security'};

     # handle edits by deleting the old memory and recreating
     LJ::Memories::delete_by_id($memoryu, $memory->{memid})
         if defined $memory;
     LJ::Memories::create($memoryu, { 
                              journalid => $jid,
                              ditemid => $ditemid,
                              des => $des,
                              security => $sec,
                          }, \@kwid);
     LJ::Memories::updated_keywords($memoryu) if $needflush;

     $title = $ML{'.title.added'};
     $body = "<?h1 $ML{'.body.added.header'} h1?><?p ";

     my $backlink = LJ::item_link($ju->{user}, $itemid, $anum);
     $body .= BML::ml('.body.added.body2', {'aopts' => "href='$backlink'"});
     $body .= " p?>";

     return;
 }

 $title = $ML{'Error'};
 $body = $ML{'error.unknownmode'};

 return;
_code?>

<?page
title=><?_code return $title; _code?>
body=> <?_code return $body;  _code?>
page?>

<?_c <LJDEP>
link: htdocs/login.bml
post: htdocs/tools/memadd.bml
</LJDEP> _c?>
