#include "ka_log.h"

#include <stdio.h>
#include "timer1.h"

static int LogStarted = 0;
static int UseFile = 1;

static const char* log_categorystr[] =
{
  ""
, ""
, "Error       "
, "Warning     "
, "Note        "
, "            "
, ""
};

static const char* log_subcategorystr[] =
{
  "          "
, "buffer    "
, "video     "
, "audio     "
, "subtitles "
, "demux     "
, "draw      "
, "seek      "
, "replay    "
, "nav       "
};

#include <stdarg.h>

void ka_logReset(void)
{
  LogStarted = 0;
}

void ka_allowStdOut(void)
{
  UseFile = 0;
}

/**
 * Writes standard logging information for a given loggin category.
 *
 * @param  cat  Logging category and subcategory.
 */
static void LogCategory(int cat)
{
  int category = cat & 0xff00;
  const char* sepline = "----------------------------------------------------------------------------------------------------\n";

  if (category == ka_log_simple)
  {
    if ((LogStarted & 2) == 0)
    {
      fprintf(stderr, sepline);
      fprintf(stderr, "       rtc  category  action\n");
      fprintf(stderr, sepline);
      LogStarted |= 2;
    }
  }
  else if (category <= ka_log_info)
  {
    if ((LogStarted & 2) == 0)
    {
      fprintf(stderr, sepline);
      fprintf(stderr, "       rtc  category  action\n");
      fprintf(stderr, sepline);
      LogStarted |= 2;
    }

    if (category == ka_log_rtc)
    {
      uint32_t t = timer_getrtc();
      if (t)
        fprintf(stderr, "%10u  ", t);
      else
        fprintf(stderr, "%10u) ", timer_gettime());
    }
    else
      fprintf(stderr, "%s", log_categorystr[category >> 8]);

    fprintf(stderr, "%s", log_subcategorystr[cat & 0xff]);
  }
  else
  {
    if ((LogStarted & 1) == 0)
    {
      fprintf(stderr, sepline);
      LogStarted |= 1;
    }

    fprintf(stderr, "%s", log_categorystr[category >> 8]);
  }
}

/**
 * Logs some information and moves to the start of the next line.
 * Information is prefixed by category related standard logging information.
 *
 * @param  cat      Logging category and subcategory.
 * @param  pformat  Information formatting printf like.
 * @param  ...      Variable list of parameters.
 */
void ka_log(int cat, const char* pformat, ...)
{
  va_list arg;

  if (UseFile)
  {
    // stderr assigned?
    if (fseek(stderr, 0, SEEK_END))
      return;

    LogCategory(cat);
  }

  va_start(arg, pformat);
  vfprintf(stderr, pformat, arg);
  va_end(arg);
  fprintf(stderr, "\n");
}

/**
 * Starts logging some information but expect more information to follow
 * on the same line.
 * Information is prefixed by category related standard logging information.
 *
 * @param  cat      Logging category and subcategory.
 * @param  pformat  Information formatting printf like.
 * @param  ...      Variable list of parameters.
 */
void ka_logs(int cat, const char* pformat, ...)
{
  va_list arg;

  if (UseFile)
  {
    // stderr assigned?
    if (fseek(stderr, 0, SEEK_END))
      return;

    LogCategory(cat);
  }

  va_start(arg, pformat);
  vfprintf(stderr, pformat, arg);
  va_end(arg);
}

/**
 * Continues logging infomation on an already started line.
 *
 * @param  pformat  Information formatting printf like.
 * @param  ...      Variable list of parameters.
 */
void ka_logn(const char* pformat, ...)
{
  va_list arg;

  if (UseFile)
  {
    // stderr assigned?
    if (fseek(stderr, 0, SEEK_END))
      return;
  }

  va_start(arg, pformat);
  vfprintf(stderr, pformat, arg);
  va_end(arg);
  fflush(stderr);
}

void ka_logv(const char* pformat, va_list arg)
{
  if (UseFile)
  {
    // stderr assigned?
    if (fseek(stderr, 0, SEEK_END))
      return;
  }

  vfprintf(stderr, pformat, arg);
  fflush(stderr);
}

void ka_log_dump(const uint8_t* pdata, uint32_t size)
{
  fprintf(stderr, "Dump of %p\n", pdata);
  fwrite(pdata, size, 1, stderr);
  fprintf(stderr, "End of Dump\n");
}
