/* $Cambridge: hermes/src/prayer/cmd/cmd_copy_msg.c,v 1.4 2008/09/17 17:20:25 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"

void cmd_copy_msg(struct session *session)
{
    struct request *request = session->request;
    MAILSTREAM *stream = session->stream;
    struct prefs *prefs = session->options->prefs;
    char *mailbox;
    unsigned long count = 0;
    unsigned long next;
    struct pool *pool = request->pool;
    unsigned long msgno;
    char *s;
    struct msgmap *zm = session->zm;
    unsigned long zm_offset;

    if (request->argc < 2) {
        session_redirect(session, request, "error");
        return;
    }

    mailbox = pool_strdup(request->pool, request->argv[1]);
    string_canon_decode(mailbox);

    if (!string_filename_valid(mailbox)) {
        session_alert(session, "Path contained illegal characters");
        session_redirect(session, request, "display");
        return;
    }

    ml_clear_error();
    ml_clear_try_create();

    if (session->aggregate) {
        char *seq;

        if (prefs->use_mark_persist)
            seq = msgmap_mark_sequence(session->zm);
        else
            seq = msgmap_tmp_mark_sequence(session->zm);

        if (seq && seq[0]
            && !ml_copy(session, stream, seq, mailbox, CP_MOVE)) {
            if (ml_have_close()) {
                session_redirect(session, request, "restart");
                return;
            }
            if (ml_have_error()) {
                session_alert(session, "Copy failed: %s", ml_errmsg());
                session_log(session,
                            "[cmd_copy_msg] Copy failed to %s: %s",
                            mailbox, ml_errmsg());
                session_redirect(session, request,
                                 session->copy_parent_cmd);
                return;
            }
        }

        if (prefs->use_mark_persist) {
            count = msgmap_marked_count(session->zm);

            /* Unmark messages unless error occurred */
            if (!ml_have_error() && prefs->use_agg_unmark) {
                msgmap_unmark_all(session->zm);
                msgmap_disable_zoom(session->zm);
            }
        } else {
            count = msgmap_tmp_marked_count(session->zm);
            msgmap_tmp_unmark_all(session->zm);
        }
    } else {
        if (!ml_copy(session, stream,
                     string_itoa_tmp(session->current), mailbox, CP_MOVE))
        {
            if (ml_have_close()) {
                session_redirect(session, request, "restart");
                return;
            }
            if (ml_have_error()) {
                session_alert(session, "Copy failed: %s", ml_errmsg());
                session_log(session,
                            "[cmd_copy_msg] Copy failed to %s: %s",
                            mailbox, ml_errmsg());
                session_redirect(session, request,
                                 session->copy_parent_cmd);
                return;
            }
        }
        count = 1;
    }

    /* Need to ping target stream if we are saving to an active folder */
    if (!session_streams_ping(session, mailbox)) {
        session_redirect(session, request, "restart");
        return;
    }

    if (ml_have_try_create()) {
        session_alert(session,
                      "Copy failed (need to create folder first)");
        session_log(session, "[cmd_copy_msg] Copy failed [TRYCREATE]");
        session_redirect(session, request, session->copy_parent_cmd);
        return;
    }

    if (ml_have_error()) {
        session_alert(session, "Copy operation failed: %s", ml_errmsg());
        session_log(session,
                    "[cmd_copy_msg] Copy operation failed: %s",
                    ml_errmsg());
        session_redirect(session, request, session->copy_parent_cmd);
        return;
    }

    if (!(!strcmp(session->copy_parent_cmd, "display")
          && !session->aggregate)) {
        /* Keep current message */
        if (count > 1) {
            session_message(session, "Copied %lu messages to %s", count,
                            utf8_from_imaputf7(request->pool, mailbox));
            session_log(session,
                        "[cmd_copy_msg] Copied %lu messages to %s", count,
                        mailbox);
        } else if (count == 1) {
            session_message(session, "Copied 1 message to %s",
                            utf8_from_imaputf7(request->pool, mailbox));
            session_log(session, "[cmd_copy_msg] Copied 1 message to %s",
                        mailbox);
        } else {
            session_message(session, "No messages marked to copy");
            session_log(session,
                        "[cmd_copy_msg] No messages marked to copy");
        }
        session_redirect(session, request, session->copy_parent_cmd);
        return;
    }

    /* Locate next message */
    msgno = session->current;
    zm_offset = msgmap_find(zm, msgno);

    if (zm->sort_reverse && (zm_offset > 1))
        next = msgmap_value(zm, zm_offset - 1);
    else if (!zm->sort_reverse && (zm_offset < msgmap_size(zm)))
        next = msgmap_value(zm, zm_offset + 1);
    else {
        /* No next message */
        session_message(session, "Copied message %lu to \"%s\", no more messages",
                        msgno, utf8_from_imaputf7(request->pool, mailbox));
        session_log(session, "[cmd_copy_msg] Copied message %lu to %s",
                    msgno, mailbox);
        session->current = msgno;
        session_redirect(session, request, "list");
        return;
    }

    session_message(session, "Copied message %lu to \"%s\", displaying %lu out of %lu",
                    msgno, utf8_from_imaputf7(request->pool, mailbox), next, zm->nmsgs);
    session_log(session, "[cmd_copy_msg] Copied message %lu to %s",
                msgno, mailbox);

    s = pool_printf(pool, "display/%lu/%lu",
                    next, ml_uid(session, stream, next));

    session_redirect(session, request, s);
}
