/* $Cambridge: hermes/src/prayer/cmd/cmd_abook_list.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 void process_remove(struct session *session)
{
    struct options *options = session->options;
    struct abook *abook = options->abook;
    struct request *request = session->request;
    struct pool *pool = request->pool;
    unsigned long count;
    char *key, *tmp;

    assoc_scan_reset(request->form);

    count = 0;
    while (assoc_scan_next(request->form, &key, NIL)) {
        if (strncmp(key, "remove_", strlen("remove_")) != 0)
            continue;

        tmp = pool_strdup(pool, key + strlen("remove_"));
        string_canon_decode(tmp);

        abook_remove(abook, tmp);
        count++;
    }

    if (count > 0)
        session->options->save = T;

    if (count != 1)
        session_message(session,
                        "Removed %lu entries from addressbook", count);
    else
        session_message(session, "Added 1 entry from addressbook");
}

static void process_add_address(struct session *session)
{
    struct options *options = session->options;
    struct abook *abook = options->abook;
    struct request *request = session->request;
    struct draft *draft = session->draft;
    unsigned long num;
    unsigned long count;
    struct abook_entry *abe;
    char *key;

    assoc_scan_reset(request->form);

    count = 0;
    while (assoc_scan_next(request->form, &key, NIL)) {
        if (!strncmp(key, "to_", strlen("to_"))) {
            num = atoi(key + strlen("to_")) - 1;
            if ((abe = abook_lookup_byoffset(abook, num))) {
                draft_add_to(draft, abook_entry_to_string(request->pool, abe));
                count++;
            }
        } else if (!strncmp(key, "cc_", strlen("cc_"))) {
            num = atoi(key + strlen("cc_")) - 1;
            if ((abe = abook_lookup_byoffset(abook, num))) {
                draft_add_cc(draft, abook_entry_to_string(request->pool, abe));
                count++;
            }
        } else if (!strncmp(key, "bcc_", strlen("bcc_"))) {
            num = atoi(key + strlen("bcc_")) - 1;
            if ((abe = abook_lookup_byoffset(abook, num))) {
                draft_add_bcc(draft, abook_entry_to_string(request->pool, abe));
                count++;
            }
        }
    }
    if (count != 1)
        session_message(session, "Added %lu addresses to draft", count);
    else
        session_message(session, "Added 1 address to draft");
}

static BOOL
cmd_abook_list_addnav(struct template_vals *tvals,
                      unsigned long offset,
                      unsigned long count,
                      unsigned long per_page)
{
    unsigned long page;
    unsigned long pages;

    if (count > 0) {
        page = ((offset - 1) / per_page) + 1;
        pages = ((count - 1) / per_page) + 1;
    } else {
        page = 0;
        pages = 0;
    }

    template_vals_ulong(tvals, "entries", count);
    template_vals_ulong(tvals, "page_current", page);
    template_vals_ulong(tvals, "page_total", pages);

    if (page > 1) {
        template_vals_hash_ulong(tvals, "$nav", "first_page", 1);
        template_vals_hash_ulong(tvals, "$nav", "prev_page", offset-per_page);
    }
    if (page < pages) {
        template_vals_hash_ulong(tvals, "$nav", "next_page", offset+per_page);
        template_vals_hash_ulong(tvals, "$nav", "last_page", count);
    }
    return(T);
}

static void
cmd_abook_list_single(struct template_vals *tvals,
                      struct abook_entry *abe,
                      unsigned long i)
{
    template_vals_foreach_init(tvals, "@abook",   i);
    template_vals_foreach_ulong(tvals, "@abook",  i, "num", abe->position);
    template_vals_foreach_string(tvals, "@abook", i, "alias", abe->alias);
    template_vals_foreach_string(tvals, "@abook", i, "name", abe->name);
    template_vals_foreach_string(tvals, "@abook", i, "comment", abe->comment);
    template_vals_foreach_string(tvals, "@abook", i, "email", abe->email);
    if (i % 2 == 0)
        template_vals_foreach_ulong(tvals, "@abook", i, "even_row", 1);
}

void cmd_abook_list(struct session *session)
{
    struct template_vals *tvals = session->template_vals;
    struct request *request = session->request;
    struct buffer *b = request->write_buffer;
    struct options *options = session->options;
    struct abook *abook = options->abook;
    struct prefs *prefs = options->prefs;
    struct abook_entry *abe;
    unsigned long offset;
    unsigned long first, last, count, i;

    /* Save options if anything changed */
    if (options->save)
        session_streams_save_options(session);

    if (request->method == POST) {
        request_decode_form(request);

        if (assoc_lookup(request->form, "sub_remove")) {
            process_remove(session);
        } else if (assoc_lookup(request->form, "sub_add_address")) {
            process_add_address(session);
        } else {
            char *pstr = assoc_lookup(request->form, "page");
            unsigned long page = pstr ? atoi(pstr) : 0;
            unsigned long size = list_length(abook->list);
            unsigned long pages = (size / prefs->abook_per_page) + 1;

            if ((page > 0) && (page <= pages))
                abook->current = (page - 1) * prefs->abook_per_page + 1;

            if (abook->current > size)
                abook->current = size;
        }
    } else if (request->argc == 2)
        abook->current = atoi(request->argv[1]);        /* Move to page */

    /* Record last command for compose/cancel and friends */
    if (!session->draft->have_draft)
        session->compose_parent_cmd = "abook_list";

    /* Work out if "current" entry still exists. If not, make the last
     * address on the list current. */
    if ((count = list_length(abook->list)) > 0) {
        if (abook->current > count)
            abook->current = count;
        else if (abook->current == 0)
            abook->current = 1;
    } else
        abook->current = 0;

    /* Calculate first and last entry on page. */
    offset = abook->current;

    if (offset >= prefs->abook_per_page)
        first = (offset - ((offset - 1) % prefs->abook_per_page));
    else
        first = 1;

    last = (((first + (prefs->abook_per_page - 1)) <= count)
            ? (first + (prefs->abook_per_page - 1)) : count);

    cmd_abook_list_addnav(tvals, first, count, prefs->abook_per_page);
    abook_sort(abook);

    i = 0;
    offset = first;
    while (offset <= last) {
        if (!(abe = abook_lookup_sorted_byoffset(abook, offset - 1)))
            break;

        cmd_abook_list_single(tvals, abe, i);
        offset++;
        i++;
    }

    session_seed_template(session, tvals);
    template_expand("abook_list", tvals, b);
    response_html(request, 200);        /* Success */
}
