/*
 * ftop - show progress of open files and file systems
 * Copyright (C) 2009  Jason Todd <jtodd1@earthlink.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/* log.c - ftop log facility and log screen */

#include <stdarg.h>         /* va_list, va_start, va_end */
#include <stdio.h>          /* vsnprintf, vprintf */
#include <stdlib.h>         /* malloc, free */
#include <string.h>         /* memset, memcpy, strchr */

#include "ftop.h"
#include "ui.h"
#include "options.h"
#include "log.h"

static const char *log_prefix[] =
    {"", "Error: ", "Warning: ", "Info: ", "Debug: "};

int snapshot_log(snapshot *s, uint32_t level, const char *fmt, ...)
{
    size_t bytes, level_idx;
    uint32_t tmp_level;
    va_list arg;
    char *old_log;

    if (level != 0)
    {
        if (!(s->log_flags & level))
            return 1;

        tmp_level = level;
        for (level_idx = 0; tmp_level != 0; level_idx++)
            tmp_level >>= 1;

        snapshot_log(s, 0, log_prefix[level_idx]);
    }

    va_start(arg, fmt);
#if 1
    bytes = vsnprintf(s->log + s->log_used, s->log_size - s->log_used, fmt,
                      arg);
#else
    bytes = vprintf(fmt, arg);
#endif
    va_end(arg);
    if (bytes >= (s->log_size - s->log_used))
    {
        old_log = s->log;
        if (s->log_size == 0)
            s->log_size = INITIAL_LOG;

        while ((s->log_used + bytes + 1) >= s->log_size)
            s->log_size <<= 1;

        if ((s->log = malloc(s->log_size)) == NULL)
        {
            s->log_size = 0;
            return 0;
        }

        memset(s->log, 0, s->log_size);
        if (old_log != NULL)
        {
            memcpy(s->log, old_log, s->log_used);
            free(old_log);
        }

        va_start(arg, fmt);
        vsnprintf(s->log + s->log_used, s->log_size - s->log_used, fmt, arg);
        va_end(arg);
    }

    s->log_used += bytes;
    if (level != 0)
        snapshot_log(s, 0, "\n");

    return 1;
}

int show_log(ftop_data *p)
{
    snapshot *s;
    char *next, *tmp_str;

    screen_title(p, "LOG", OPT_VIEW_LOG_CHAR);

    s = &(p->s[p->s_idx]);
    if (s->log_used != 0)
    {
        next = s->log;
        while ((next != NULL) && (*next != '\0'))
        {
            if ((tmp_str = strchr(next, '\n')) != NULL)
                *tmp_str = '\0';

            p_printf(p, "%s", next);
            p_eol(p, 1);
            if (tmp_str != NULL)
            {
                *(tmp_str++) = '\n';
                next = tmp_str;
            }
        }
    }

    return 1;
}
