/*
 * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
 * Copyright (c) 2014-2016 Valve Corporation. All rights reserved.
 * Copyright (C) 2014-2016 LunarG, Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Author: Jon Ashburn <jon@lunarg.com>
 * Author: Peter Lohrmann <peterl@valvesoftware.com>
 */

#include "vktrace_platform.h"

#include "vktrace_tracelog.h"
#include "vktrace_trace_packet_utils.h"

#include <assert.h>
#include <stdio.h>
#include <stdarg.h>

// filelike thing that is used for outputting trace messages
static FileLike* g_pFileOut = NULL;

VKTRACE_TRACER_ID g_tracelog_tracer_id = VKTRACE_TID_RESERVED;

void vktrace_trace_set_trace_file(FileLike* pFileLike)
{
    g_pFileOut = pFileLike;
}

// set initial value to 0 but once we read the trace file version
// we will update this and use for version checks
static uint32_t g_trace_version_num = 0;

void vktrace_set_trace_version(uint32_t version)
{
    g_trace_version_num = version;
}

BOOL vktrace_check_min_version(uint32_t version)
{
    return ((g_trace_version_num) >= (version) ? true : false);
}

FileLike* vktrace_trace_get_trace_file()
{
    return g_pFileOut;
}

void vktrace_tracelog_set_tracer_id(uint8_t tracerId)
{
    g_tracelog_tracer_id = (VKTRACE_TRACER_ID)tracerId;
}

VKTRACE_REPORT_CALLBACK_FUNCTION s_reportFunc;
VktraceLogLevel s_logLevel = VKTRACE_LOG_ERROR;

const char* vktrace_LogLevelToString(VktraceLogLevel level)
{
    switch(level)
    {
    case VKTRACE_LOG_NONE: return "Quiet";
    case VKTRACE_LOG_DEBUG: return "Debug";
    case VKTRACE_LOG_ERROR: return "Errors";
    case VKTRACE_LOG_WARNING: return "Warnings";
    case VKTRACE_LOG_VERBOSE: return "Info";
    default:
        return "Unknown";
    }
}

const char* vktrace_LogLevelToShortString(VktraceLogLevel level)
{
    switch(level)
    {
    case VKTRACE_LOG_NONE: return "Quiet";
    case VKTRACE_LOG_DEBUG: return "Debug";
    case VKTRACE_LOG_ERROR: return "Errors";
    case VKTRACE_LOG_WARNING: return "Warnings";
    case VKTRACE_LOG_VERBOSE: return "Info";
    default:
        return "Unknown";
    }
}


// For use by both tools and libraries.
void vktrace_LogSetCallback(VKTRACE_REPORT_CALLBACK_FUNCTION pCallback)
{
    s_reportFunc = pCallback;
}

void vktrace_LogSetLevel(VktraceLogLevel level)
{
    vktrace_LogDebug("Log Level = %u (%s)", level, vktrace_LogLevelToString(level));
    s_logLevel = level;
}

BOOL vktrace_LogIsLogging(VktraceLogLevel level)
{
    return (level <= s_logLevel) ? TRUE : FALSE;
}

void LogGuts(VktraceLogLevel level, const char* fmt, va_list args)
{
#if defined(WIN32)
        int requiredLength = _vscprintf(fmt, args) + 1;
#elif defined(PLATFORM_LINUX) || defined(PLATFORM_OSX)
        int requiredLength;
        va_list argcopy;
        va_copy(argcopy, args);
        requiredLength = vsnprintf(NULL, 0, fmt, argcopy) + 1;
        va_end(argcopy);
#endif
    static VKTRACE_THREAD_LOCAL BOOL logging = FALSE;

    // Don't recursively log problems found during logging
    if (logging)
    {
        return;
    }
    logging = TRUE;

    char* message = (char*)vktrace_malloc(requiredLength);
#if defined(WIN32)
    _vsnprintf_s(message, requiredLength, requiredLength - 1, fmt, args);
#elif defined(PLATFORM_LINUX) || defined(PLATFORM_OSX)
    vsnprintf(message, requiredLength, fmt, args);
#endif

    if (s_reportFunc != NULL)
    {
        s_reportFunc(level, message);
    }
    else
    {
#ifdef ANDROID
        #include <android/log.h>
        __android_log_print(ANDROID_LOG_INFO, "vktrace", "%s: %s\n", vktrace_LogLevelToString(level), message);
#else
        printf("%s: %s\n", vktrace_LogLevelToString(level), message);
#endif
    }

    vktrace_free(message);
    logging = FALSE;
}

void vktrace_LogAlways(const char* format, ...)
{
    va_list args;
    va_start(args, format);
    LogGuts(VKTRACE_LOG_VERBOSE, format, args);
    va_end(args);
}

void vktrace_LogDebug(const char* format, ...)
{
#if defined(_DEBUG)
	if (vktrace_LogIsLogging(VKTRACE_LOG_DEBUG))
	{
		va_list args;
	    va_start(args, format);
	    LogGuts(VKTRACE_LOG_DEBUG, format, args);
	    va_end(args);
    }
#endif
}

void vktrace_LogError(const char* format, ...)
{
    if (vktrace_LogIsLogging(VKTRACE_LOG_ERROR))
    {
        va_list args;
        va_start(args, format);
        LogGuts(VKTRACE_LOG_ERROR, format, args);
        va_end(args);
    }
}

void vktrace_LogWarning(const char* format, ...)
{
    if (vktrace_LogIsLogging(VKTRACE_LOG_WARNING))
    {
        va_list args;
        va_start(args, format);
        LogGuts(VKTRACE_LOG_WARNING, format, args);
        va_end(args);
    }
}

void vktrace_LogVerbose(const char* format, ...)
{
    if (vktrace_LogIsLogging(VKTRACE_LOG_VERBOSE))
    {
        va_list args;
        va_start(args, format);
        LogGuts(VKTRACE_LOG_VERBOSE, format, args);
        va_end(args);
    }
}
