/* $Cambridge: hermes/src/prayer/cmd/cmd_aggregate_tmp.c,v 1.2 2008/05/19 15:55:54 dpc22 Exp $ */
/************************************************
 *    Prayer - a Webmail Interface              *
 ************************************************/

/* Copyright (c) University of Cambridge 2000 - 2008 */
/* See the file NOTICE for conditions of use and distribution. */

#include "prayer_session.h"

static BOOL
make_sequence(struct session *session, char **seqp, unsigned long *countp)
{
    struct request *request = session->request;
    MAILSTREAM *stream = session->stream;
    struct buffer *seq = buffer_create(request->pool, 128);
    unsigned long count = 0;
    char *key;

    assoc_scan_reset(request->form);

    while (assoc_scan_next(request->form, &key, NIL)) {
        char *s;
        unsigned long msgno, msguid;

        if ((!key) || (!Uisdigit(key[0]))
            || !strcmp(key, "0@0"))
            continue;

        if (!(s = strchr(key, '@')))
            continue;

        msgno = atoi(key);
        msguid = atoi(s + 1);

        if ((msgno == 0) || (msguid == 0))
            continue;

        if (!(msgno = stream_check_uid(session, stream, msgno, msguid)))
            return (NIL);

        bprintf(seq, "%lu,", msgno);
        count++;
    }

    if (count > 0) {
        *seqp = buffer_fetch(seq, 0, buffer_size(seq) - 1, NIL);
        *countp = count;
    } else {
        *seqp = "";
        *countp = 0;
    }

    return (T);
}

/* ====================================================================== */

static BOOL
aggregate_delete(struct session *session, char *sequence,
                 unsigned long count)
{
    MAILSTREAM *stream = session->stream;

    if (!ml_flag(session, stream, sequence, "\\DELETED", ST_SET)) {
        session_message(session, "Failed to delete messages: %s",
                        ml_errmsg());
        session_log(session,
                    "[cmd_aggregate_tmp] Failed to delete messages: %s",
                    ml_errmsg());
        return (NIL);
    }

    if (count > 1) {
        session_message(session, "Deleted %lu messages", count);
        session_log(session,
                    "[cmd_aggregate_tmp] Deleted %lu messages from %s",
                    count, session->foldername);
    } else {
        session_message(session, "Deleted 1 message");
        session_log(session, "[cmd_aggregate_tmp] Deleted 1 message from %s",
                    session->foldername);
    }
    return (T);
}

static BOOL
aggregate_undelete(struct session *session,
                   char *sequence, unsigned long count)
{
    MAILSTREAM *stream = session->stream;

    if (!ml_flag(session, stream, sequence, "\\DELETED", 0)) {
        session_message(session, "Failed to undelete messages: %s",
                        ml_errmsg());
        session_log(session,
                    "[cmd_aggregate_tmp] Failed to undelete messages: %s",
                    ml_errmsg());
        return (NIL);
    }

    if (count > 1) {
        session_message(session, "Undeleted %lu messages", count);
        session_log(session,
                    "[cmd_aggregate_tmp] Undeleted %lu messages from %s",
                    count, session->foldername);
    } else {
        session_message(session, "Undeleted 1 message");
        session_log(session,
                    "[cmd_aggregate_tmp] Undeleted 1 message from %s",
                    session->foldername);
    }
    return (T);
}

static BOOL
aggregate_read(struct session *session, char *sequence,
               unsigned long count)
{
    MAILSTREAM *stream = session->stream;

    if (!ml_flag(session, stream, sequence, "\\SEEN", ST_SET)) {
        session_message(session,
                        "Failed to flag messages as read: %s",
                        ml_errmsg());
        session_log(session,
                    "[cmd_aggregate_tmp] Failed to flag messages as read: %s",
                    ml_errmsg());
        return (NIL);
    }

    if (count > 1) {
        session_message(session, "Flagged %lu messages as read", count);
        session_log(session,
                    "[cmd_aggregate_tmp] Flagged %lu messages as read from %s",
                    count, session->foldername);
    } else {
        session_message(session, "Flagged 1 message as read");
        session_log(session,
                    "[cmd_aggregate_tmp] Flagged 1 message as read from %s",
                    session->foldername);
    }
    return (T);
}

static BOOL
aggregate_unread(struct session *session, char *sequence,
                 unsigned long count)
{
    MAILSTREAM *stream = session->stream;

    if (!ml_flag(session, stream, sequence, "\\SEEN", 0)) {
        session_message(session,
                        "Failed to flag messages as unread: %s",
                        ml_errmsg());
        session_log(session,
                    "[cmd_aggregate_tmp] Failed to flag messages as unread: %s",
                    ml_errmsg());
        return (NIL);
    }

    if (count > 1) {
        session_message(session, "Flagged %lu messages as unread", count);
        session_log(session,
                    "[cmd_aggregate_tmp] Flagged %lu messages as unread from %s",
                    count, session->foldername);
    } else {
        session_message(session, "Flagged 1 message as unread");
        session_log(session,
                    "[cmd_aggregate_tmp] Flagged 1 message as unread from %s",
                    session->foldername);
    }
    return (T);
}

/* ====================================================================== */

static BOOL aggregate_copy(struct session *session)
{
    struct request *request = session->request;
    MAILSTREAM *stream = session->stream;
    char *key;
    char *s;
    unsigned long msgno, msguid;
    unsigned long count = 0;

    msgmap_tmp_unmark_all(session->zm);

    assoc_scan_reset(request->form);

    while (assoc_scan_next(request->form, &key, NIL)) {
        if ((!key) || (!Uisdigit(key[0])) || !strcmp(key, "0@0"))
            continue;

        if (!(s = strchr(key, '@')))
            continue;

        msgno = atoi(key);
        msguid = atoi(s + 1);

        if ((msgno == 0) || (msguid == 0))
            continue;

        if (!(msgno = stream_check_uid(session, stream, msgno, msguid)))
            return (NIL);

        msgmap_tmp_mark(session->zm, msgno);
        count++;
    }

    if (count == 0) {
        session_message(session, "No messages marked");
        session_redirect(session, request, "list");
    } else
        session_redirect(session, request, "copy/aggregate");


    return (T);
}

/* ====================================================================== */

static BOOL aggregate_forward(struct session *session)
{
    struct request *request = session->request;
    MAILSTREAM *stream = session->stream;
    char *key;
    char *s;
    unsigned long msgno, msguid;
    unsigned long count = 0;

    msgmap_tmp_unmark_all(session->zm);

    assoc_scan_reset(request->form);

    while (assoc_scan_next(request->form, &key, NIL)) {
        if ((!key) || (!Uisdigit(key[0])) || !strcmp(key, "0@0"))
            continue;

        if (!(s = strchr(key, '@')))
            continue;

        msgno = atoi(key);
        msguid = atoi(s + 1);

        if ((msgno == 0) || (msguid == 0))
            continue;

        if (!(msgno = stream_check_uid(session, stream, msgno, msguid)))
            return (NIL);

        msgmap_tmp_mark(session->zm, msgno);
        count++;
    }

    if (count == 0) {
        session_message(session, "No messages marked");
        session_redirect(session, request, "list");
    } else
        session_redirect(session, request, "forward/aggregate");


    return (T);
}

/* ====================================================================== */

void cmd_aggregate_tmp(struct session *session)
{
    struct request *request = session->request;
    struct options *options = session->options;
    struct prefs *prefs = options->prefs;
    char *cmd;
    char *sequence;
    unsigned long count;
    BOOL rc;

    if (request->method != POST) {
        session_redirect(session, request, "list");
        return;
    }

    request_decode_form(request);

    if (assoc_lookup(request->form, "sub_aggregate"))
        cmd = assoc_lookup(request->form, "aggregate");
    else if (assoc_lookup(request->form, "sub_aggregate2"))
        cmd = assoc_lookup(request->form, "aggregate2");
    else {
        char *pstr = assoc_lookup(request->form, "page");
        unsigned long page = pstr ? atoi(pstr) : 0;
        unsigned long size = msgmap_size(session->zm);
        unsigned long pages = (size / prefs->msgs_per_page) + 1;

        if ((page > 0) && (page <= pages)) {
            session->current
                =
                msgmap_value(session->zm,
                             ((page - 1) * prefs->msgs_per_page) + 1);
            session_message(session, "Switched to page: %lu", page);
        } else
            session_message(session, "Page out of range");
        session_redirect(session, request, "list");
        return;
    }

    if (!(cmd && cmd[0])) {
        session_message(session, "Invalid form input");
        session_log(session, "[cmd_aggregate_tmp] Invalid form input");
        session_redirect(session, request, "list");
        return;
    }

    if (!strcmp(cmd, "copy")) {
        if (!aggregate_copy(session))
            session_redirect(session, request, "restart");

        return;
    }

    if (!strcmp(cmd, "forward")) {
        if (!aggregate_forward(session))
            session_redirect(session, request, "restart");

        return;
    }

    if (!make_sequence(session, &sequence, &count)) {
        session_redirect(session, request, "restart");
        return;
    }

    if (count == 0) {
        session_message(session, "No messages marked");
        session_redirect(session, request, "list");
        return;
    }

    rc = NIL;
    if (!strcmp(cmd, "delete"))
        rc = aggregate_delete(session, sequence, count);
    else if (!strcmp(cmd, "undelete"))
        rc = aggregate_undelete(session, sequence, count);
    else if (!strcmp(cmd, "read"))
        rc = aggregate_read(session, sequence, count);
    else if (!strcmp(cmd, "unread"))
        rc = aggregate_unread(session, sequence, count);
    else {
        session_message(session, "Unknown action");
        rc = T;
    }

    session_redirect(session, request, (rc) ? "list" : "restart");
}
