// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <fbl/algorithm.h>
#include <fbl/string.h>
#include <fbl/vector.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/directory.h>
#include <lib/log/log.h>
#include <lib/log/log_writer.h>
#include <memory>
#include <stdio.h>

namespace {

// Configuration for a logger object.
// Specifies the destination to which log messages should be written.
typedef struct log_config {
    // The minimum log level.
    // Log messages with lower severity will be discarded.
    // If this number is negative, it refers to a verbosity.
    log_level_t min_level;

    // The writer that logs will go to.
    log_writer_t* log_writer;

    // An array of tag strings to associate with all messages written
    // by this logger.  Tags will be truncated if they are (individually) longer
    // than |LOG_MAX_TAG_LEN|.
    fbl::Vector<fbl::String> tags;
} log_config_t;

std::unique_ptr<log_config_t> g_log_config_ptr =
    std::unique_ptr<log_config_t>(nullptr);

void log_write_message_helper(log_level_t level,
                              size_t num_tags, const char** tags_ptr,
                              const char* message, size_t message_len) {
    log_config_t* cfg = g_log_config_ptr.get();
    if (!cfg) {
        // Logging has not been initialized. Don't log anything.
        return;
    }

    fbl::Vector<const char*> static_tags;
    for (size_t i = 0; i < cfg->tags.size(); i++) {
        static_tags.push_back(cfg->tags[i].c_str());
    }

    log_message_t msg = {
        level,
        static_tags.get(),
        static_tags.size(),
        tags_ptr,
        num_tags,
        message,
        fbl::min(message_len, (size_t)LOG_MAX_MESSAGE_SIZE),
    };
    cfg->log_writer->ops->v1.write(cfg->log_writer, &msg);
}

} // namespace

bool log_level_is_enabled(log_level_t level) {
    log_config_t* cfg = g_log_config_ptr.get();
    return cfg && level >= cfg->min_level;
}

void log_set_min_level(log_level_t level) {
    log_config_t* cfg = g_log_config_ptr.get();
    if (cfg) {
        cfg->min_level = level;
    }
}

log_config_t* log_get_config(void) {
    return g_log_config_ptr.get();
}

void log_initialize(log_level_t min_level, log_writer_t* log_writer,
                    const size_t num_tags, const char** tags) {
    if (g_log_config_ptr.get() != nullptr) {
        log_shutdown();
    }
    log_config_t* config = new log_config_t;
    config->min_level = min_level;
    config->log_writer = log_writer;

    ZX_ASSERT(num_tags <= LOG_MAX_TAGS);

    for (size_t i = 0; i < num_tags; i++) {
        config->tags.push_back(fbl::String(tags[i]));
    }

    g_log_config_ptr = std::unique_ptr<log_config_t>(config);
}

void log_shutdown(void) {
    g_log_config_ptr = std::unique_ptr<log_config_t>(nullptr);
}

void log_write_message_printf(log_level_t level,
                              size_t num_tags, const char** tags_ptr,
                              const char* format_string, ...) {
    char message[LOG_MAX_MESSAGE_SIZE];
    va_list args;
    va_start(args, format_string);
    int msg_len = vsnprintf(message, LOG_MAX_MESSAGE_SIZE, format_string, args);
    va_end(args);
    if (msg_len < 0) {
        // There was an error formatting. Toss the message.
        return;
    }
    log_write_message_helper(level, num_tags, tags_ptr, message, msg_len);
}

void log_write_message(log_level_t level,
                       size_t num_tags, const char** tags_ptr,
                       const char* message) {
    size_t message_len = strlen(message);
    log_write_message_helper(level, num_tags, tags_ptr, message, message_len);
}
