<?_code

 use strict;
 use vars qw($title $body %FORM);

 LJ::set_active_crumb('addtodo');

 my $dbh = LJ::get_db_writer();

 $title = "";
 $body = "";

 my ($sth, $hval, $disabled);
 my %permission;
 my $u;
 my $remote = LJ::get_remote();

 if ($FORM{'user'}) {
     $u = LJ::load_user($FORM{'user'});
 }

 my $mode;
 my $it;

 if ($FORM{'id'} =~ /^\d+$/ && $FORM{'id'}) {
     my $id = $FORM{'id'}+0;
     my $dbr = LJ::get_db_reader();
     $sth = $dbr->prepare("SELECT t.*, up.user AS 'posteruser' FROM todo t, useridmap up WHERE t.posterid=up.userid AND t.todoid=$id");
     $sth->execute;
     $it = $sth->fetchrow_hashref;
     unless ($it) {
         $title = "Not found";
         $body = "<?h1 Not found h1?><?p The requested to-do item was not found. p?>";
         return;
     }
     
     $u = LJ::load_userid($it->{'journalid'});

     if ($it->{'security'} eq "private") {
         unless ($remote && $remote->{'userid'} == $it->{'journalid'}) {
             $title = "Sorry...";
             $body = "<?h1 Security h1?><?p The requested to-do item is private and can only be viewed by the owner. p?>";
             return;
         }
     }
     if ($it->{'security'} eq "friends") {
         unless (LJ::is_friend($u, $remote)) {
             $title = "Sorry...";
             $body = "<?h1 Security h1?><?p The requested to-do item marked 'friends only' by the owner. p?>";
             return;
         }
     }

     $sth = $dbh->prepare("SELECT k.keyword FROM todokeyword tk, keywords k WHERE tk.todoid=$id AND tk.kwid=k.kwid ORDER BY k.keyword");
     $sth->execute;
     my @kws;
     push @kws, $_ while ($_ = $sth->fetchrow_array);
     $it->{'_cats'} = join(", ", @kws);
 }

 $sth = $dbh->prepare("SELECT COUNT(*) FROM todo WHERE journalid=$u->{'userid'}");
 $sth->execute;
 my ($todo_count) = $sth->fetchrow_array;

 LJ::Todo::get_permissions($dbh, \%permission, { 'user' => $u,
                                                 'remote' => $remote,
                                                 'item' => $it });

 if ($FORM{'mode'} eq "save") {

     unless ($FORM{'subject'} =~ /\S+/) {
         $title = "Error";
         $body = "<?h1 Need a subject! h1?><?p You can't have a to-do item without a subject.  That's the one mandatory field. p?>";
         return;
     }

     my $todoid = $FORM{'id'}+0;
     my %q;
     foreach my $key (qw(statusline security subject des priority datedue progress)) {
         $q{$key} = $dbh->quote($FORM{$key});
     }
     $q{'datedue'} = $dbh->quote(LJ::html_datetime_decode({ 'name' => 'datedue' }, \%FORM));

     if ($todoid) {
         unless ($permission{'edit'}) {
             $title = "Error";
             $body = "<?h1 Permission Denied h1?><?p You don't have permission to edit a to-do item in this journal. p?>";
             return;
         }

         $sth = $dbh->prepare("UPDATE todo SET statusline=$q{'statusline'}, subject=$q{'subject'}, security=$q{'security'}, des=$q{'des'}, priority=$q{'priority'}, datedue=$q{'datedue'}, progress=$q{'progress'}, dateupdate=NOW() WHERE todoid=$todoid");
         $sth->execute;
         if ($dbh->err) { $title = "Error"; $body = $dbh->errstr; return; }
         
         $title = "Modified";
         $body = "<?h1 Success h1?><?p The todo item was modified.  You can view it <a href=\"item.bml?id=$todoid\">here</a> or view the <a href=\"./?user=$u->{'user'}\">updated list</a>. p?>";

     } else {
         unless ($permission{'add'}) {
             $title = "Error";
             $body .= "<?h1 Permission Denied h1?><?p You don't have permission to add a to-do item to this journal. p?>";
             return;
         }
         
         ## check to see if user's todo list is full
         my $max_items = LJ::get_cap($u, "todomax");
         if (defined $max_items && $todo_count >= $max_items) {
             $title = "Sorry...";
             my $atype = "account type";
             if ($LJ::HELPURL{'accounttype'}) {
                 $atype = "<a href=\"$LJ::HELPURL{'accounttype'}\">$atype</a>";
             }
             $body .= "<?h1 Too many items... h1?><?p Your $atype is limited to $max_items to-do items at a time.  p?>";
             return;
         }

         $sth = $dbh->prepare("INSERT INTO todo (todoid, journalid, posterid, ownerid, statusline, security, subject, des, priority, datecreate, dateupdate, datedue, dateclosed, progress) VALUES (NULL, $u->{'userid'}, $remote->{'userid'}, $u->{'userid'}, $q{'statusline'}, $q{'security'}, $q{'subject'}, $q{'des'}, $q{'priority'}, NOW(), NULL, $q{'datedue'}, NULL, $q{'progress'})");
         $sth->execute;
         if ($dbh->err) { return "<b>db error:</b> " . $dbh->errstr; }
         $todoid = $sth->{'mysql_insertid'};

         $title = "Added";
         $body = "<?h1 Success h1?><?p The todo item was added.  You can view it <a href=\"item.bml?id=$todoid\">here</a> or view the <a href=\"./?user=$u->{'user'}\">updated list</a>. p?>";
     }

     if ($it->{'_cats'} ne $FORM{'categories'}) 
     {
         #### we're inserting/replacing now into memories
         my @keywords = split(/\s*,\s*/, $FORM{'categories'});
         if (scalar(@keywords) > 10) { 
             $title = "Error";
             $body = "<?h1 Error h1?><?p Only 10 categories are allowed per to-do item. p?>";
             return;
         }
         @keywords = grep { s/^\s+//; s/\s+$//; $_; } @keywords;
         my @kwid;
         
         foreach my $kw (@keywords) {
             if (length($kw) > 20) {
                 $title = "Error";
                 $body = "<?h1 Error h1?><?p This category exceeds the maximum allowed size: \"$kw\" p?>";
                 return;
             }
             
             my $kwid = LJ::get_keyword_id($kw);
             push @kwid, $kwid;
         }
         
         $dbh->do("DELETE FROM todokeyword WHERE todoid=$todoid");
         if (@kwid) {
             my $sql = "INSERT IGNORE INTO todokeyword (todoid, kwid) VALUES ";
             # why IGNORE above?  with mysql 3.23.x replication, a
             # partial insert (some in, some dup -> fail) causes all
             # slaves _not_ replicating that table to stop.  fucked
             # up, huh?  so with IGNORE no error is generated.
             $sql .= join(",", map { "($todoid,$_)" } @kwid);
             $dbh->do($sql);
         }

     }
     return;
 }

 if ($FORM{'mode'} eq "add") { 
     $title = "Add To-Do Item";
     $it = { 'todoid' => 0,
             'security' => 'public',
             'priority' => 3,
             'progress' => 0,
             'datedue' => '0000-00-00 00:00:00',
             '_cats' => $FORM{'cat'},
         };

     unless ($permission{'add'}) {
         $disabled = "DISABLED";
     }
     
     my $max_items = LJ::get_cap($u, "todomax");
     if (defined $max_items && $todo_count >= $max_items) {
         $title = "Sorry...";
         my $atype = "account type";
         if ($LJ::HELPURL{'accounttype'}) {
             $atype = "<a href=\"$LJ::HELPURL{'accounttype'}\">$atype</a>";
         }
         $body .= "<?h1 Too many items... h1?><?p Your $atype is limited to $max_items to-do items at a time. p?>";
         return;
     }

 } else {
     unless ($permission{'edit'}) {
         $disabled = "DISABLED";
     }
 }

 $body .= "<FORM METHOD=POST ACTION=\"item.bml\">\n";
 $body .= "<INPUT TYPE=HIDDEN NAME=mode VALUE=\"save\">\n";
 $body .= "<INPUT TYPE=HIDDEN NAME=user VALUE=\"$u->{'user'}\">\n";
 $body .= "<INPUT TYPE=HIDDEN NAME=id VALUE=\"$it->{'todoid'}\">\n";
 
 $body .= "<a href=\"./?user=$u->{'user'}\">&lt;&lt; Back to To-Do List</a>";
 if ($FORM{'mode'} eq "add") {
     $body .= "<?h1 Add To-Do Item... h1?><?p All you need to fill out is the subject.  Everything else is optional.  p?>";
 } else {
     $body .= "<div style='margin-bottom: 20px;'><?h1 To-Do Item \#$it->{'todoid'} h1?></div>";
     if ($permission{'edit'}) {
         $title = "Edit To-Do Item";
     } else {
         $title = "View To-Do Item";
     }
 }

 $body .= "<table>";
 
 ## subject
 $hval = LJ::ehtml($it->{'subject'});
 $body .= "<tr><td><b>Subject:</b></td><td><input type=text name=subject value=\"$hval\" size=30 maxlength=40 $disabled>";
 $body .= " <b>Priority:</b> ";
 $body .= LJ::html_select({ 'name' => 'priority', 'selected' => $it->{'priority'}, 'disabled' => $disabled },
                       5, "++ High", 4, "+", 3, "Normal", 2, "-", 1, "-- Low");
 $body .= "</td></tr>\n";

 ## des
 $hval = LJ::ehtml($it->{'des'});
 $body .= "<tr><td><b>Details:</b></td><td><input type=text name=des value=\"$hval\" size=50 maxlength=80 $disabled></td></tr>\n";

 ## statusline
 $hval = LJ::ehtml($it->{'statusline'});
 $body .= "<tr><td><b>Status:</b></td><td>";
 $body .= "<input type=text name=statusline value=\"$hval\" size=15 maxlength=15 $disabled>";

 ## progress (percent complete)
 $hval = LJ::ehtml($it->{'progress'});
 $body .= " <b>Percent Done:</b> <input type=text name=progress value=\"$hval\" size=3 maxlength=3 $disabled>%";
 $body .= "</td></tr>\n";

 ## date due
 $body .= "<tr><td><b>Due Date:</b></td><td>";
 $body .= LJ::html_datetime({ 'name' => 'datedue', 'default' => $it->{'datedue'}, 'disabled' => $disabled }),
 $body .= "</td></tr>";

 ## categories
 $body .= "<tr valign=top><td><b>Categories:</b></td><td>";
 $hval = LJ::ehtml($it->{'_cats'});
 $body .= "<input type=text name=categories value=\"$hval\" size=60 maxlength=80 $disabled><br><?de Up to 10 comma separated categories de?>";
 $body .= "</td></tr>";

 ## categories
 $body .= "<tr valign=top><td><b>Security:</b></td><td>";
 {
     my $todosec = LJ::get_cap($u, "todosec");
     if ($todosec) {
         $body .= LJ::html_select({ 'name' => 'security', 
                                    'selected' => $it->{'security'}, 
                                    'disabled' => $disabled },
                               "public" => "Public",
                               "private" => "Private", 
                               "friends" => $u->{'journaltype'} eq "C" ? "Community Members" : "Friends");
     } else {
         $body .= "<input type=hidden name=security value=\"public\">Your account type doesn't permit non-public to-do items.";
     }
 }
 $body .= "</td></tr>";

 ## poster
 if (($u->{'journaltype'} eq "C" || $it->{'posteruser'} != $u->{'user'}) && $it->{'posteruser'}) {
     $body .= "<tr><td><b>Poster:</b></td><td><?ljuser $it->{'posteruser'} ljuser?></td></tr>\n";
 }

 ## submit buttton
 {
     my $permission = 0;
     my $action = "";
     if ($it->{'todoid'}) { $action = "edit"; } else { 
         $action = "add"; 
         $title = "Add To-Do Item";
     }
     $permission = $permission{$action};
     if ($permission) {
         $body .= "<tr><td><b>Done?</b></td><td>";
         $body .= "<INPUT TYPE=SUBMIT VALUE=\"" . ucfirst($action) . "\">\n";
         $body .= "</td></tr>\n";
     }
 }
     
 $body .= "</table>";


 $body .= "</FORM>\n";

 return;

_code?><?page
title=><?_code return $title; _code?>
body=><?_code return $body; _code?><p><?standout <B>Note:</B> The to-do list system is in beta.  We're well aware it has a lot of work needed, and it definitely needs to be documented-- especially the security related things. standout?>
page?><?_c <LJDEP>
link: htdocs/todo/index.bml, htdocs/todo/item.bml
post: htdocs/todo/item.bml
</LJDEP> _c?>
