/* -------------------------------
 * vim:tabstop=4:shiftwidth=4
 * debug.c
 * Mon, 01 May 2006 01:44:42 +0700
 * -------------------------------
 * Debugging code/utilities
 * -------------------------------*/

#include "debug.h"
#include "xutils.h"

#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>

#ifdef DBG_PRINT_PID
#include <sys/types.h>
#include <unistd.h>
#endif

int debug_output_disabled = 0;

/* Disables all output from debugging macros */
void debug_disable_output()
{
  debug_output_disabled = 1;
}

/* Print the message to STDERR (varadic macros is not used in the sake of
 * portability) */
void print_message_to_stderr(const char *fmt, ...)
{
  static char msg[PATH_MAX];
  va_list va;
  va_start(va, fmt);
  vsnprintf(msg, PATH_MAX, fmt, va);
  va_end(va);
  fprintf(stderr, "%s", msg);
}

int trace_mode = False;

void print_trace_header(const char *funcname, const char *fname, const int line)
{
  static pid_t pid = 0;
#ifdef TRACE_TIMESTAMP
  {
    static char timestr[PATH_MAX + 1];
    time_t curtime = time(NULL);
    struct tm *loctime = localtime(&curtime);
    strftime(timestr, PATH_MAX, "%b %e %H:%M:%S", loctime);
    fprintf(stderr, "%s ", timestr);
  }
#endif
#ifdef TRACE_WM_NAME
  fprintf(stderr, "%s ", settings.wnd_name);
#endif
#ifdef TRACE_PID
  if (!pid) pid = getpid();
  fprintf(stderr, "(%d) ", pid);
#endif
#ifdef TRACE_DPY
  if (tray_data.dpy != NULL)
    fprintf(stderr, "(%s) ", DisplayString(tray_data.dpy));
  else
    fprintf(stderr, "(dpy) ");
#endif
#ifdef TRACE_VERBOSE_LOCATION
  fprintf(stderr, "(%s:%4d) ", fname, line);
#endif
  fprintf(stderr, "%s(): ", funcname);

  (void)pid; /* unused */
  (void)fname; /* unused */
  (void)line; /* unused */
}

/* Print the summary of icon data */
int print_icon_data(struct TrayIcon *ti)
{
#ifdef DEBUG
  XWindowAttributes xwa;
#endif
  LOG_INFO(("wid = 0x%lx\n", ti->wid));
  LOG_TRACE(("  self = %p\n", (void *)ti));
  LOG_TRACE(("  prev = %p\n", (void *)ti->prev));
  LOG_TRACE(("  next = %p\n", (void *)ti->next));
  LOG_TRACE(("  invalid = %d\n", ti->is_invalid));
  LOG_TRACE(("  layed_out = %d\n", ti->is_layed_out));
  LOG_TRACE(("  update_pos = %d\n", ti->is_updated));
  LOG_INFO(("  name = %s\n",
      x11_get_window_name(tray_data.dpy, ti->wid, "<unknown>")));
  LOG_INFO(("  visible = %d\n", ti->is_visible));
  LOG_INFO(("  position (grid) = %dx%d+%d+%d\n", ti->l.grd_rect.w,
      ti->l.grd_rect.h, ti->l.grd_rect.x, ti->l.grd_rect.y));
  LOG_INFO(("  position (pixels) = %dx%d+%d+%d\n", ti->l.icn_rect.w,
      ti->l.icn_rect.h, ti->l.icn_rect.x, ti->l.icn_rect.y));
  LOG_INFO(("  wnd_sz = %dx%d\n", ti->l.wnd_sz.x, ti->l.wnd_sz.y));
  LOG_TRACE(("  cmode = %d\n", ti->cmode));
  LOG_INFO(("  xembed = %d\n", ti->is_xembed_supported));
  if (ti->is_xembed_supported) {
    LOG_TRACE(("  xembed_accepts_focus = %d\n", ti->is_xembed_accepts_focus));
    LOG_TRACE(("  xembed_last_timestamp = %ld\n", ti->xembed_last_timestamp));
    LOG_TRACE(("  xembed_last_msgid = %ld\n", ti->xembed_last_msgid));
  }
  LOG_INFO(("  embedded = %d\n", ti->is_embedded));
#ifdef DEBUG
  if (ti->is_embedded) {
    LOG_TRACE(("  mid-parent = 0x%lx\n", ti->mid_parent));
    if (!XGetWindowAttributes(tray_data.dpy, ti->mid_parent, &xwa)) {
      LOG_TRACE(("  ERR: XGetWindowAttributes() on mid-parent window faied\n"));
    } else {
      LOG_TRACE(("  mid-parent wid = 0x%lx\n", ti->mid_parent));
      LOG_TRACE(("  mid-parent state = %s\n",
          xwa.map_state == IsUnmapped
              ? "Unmapped"
              : (xwa.map_state == IsUnviewable ? "Unviewable" : "Viewable")));
      LOG_TRACE(("  mid-parent geometry = %dx%d+%d+%d\n", xwa.width, xwa.height,
          xwa.x, xwa.y));
    }
  }
  if (settings.log_level > LOG_LEVEL_INFO) {
    Window real_parent, root, *children = NULL;
    unsigned int nchildren = 0;
    int rc;
    rc = XQueryTree(
        tray_data.dpy, ti->wid, &root, &real_parent, &children, &nchildren);
    if (rc && children != NULL && nchildren > 0) XFree(children);
    if (!rc) {
      LOG_TRACE(("  ERR: XQueryTree() failed\n"));
    } else {
      LOG_TRACE(("  parent wid from XQueryTree() = 0x%lx\n", real_parent));
    }
  }
  if (!XGetWindowAttributes(tray_data.dpy, ti->wid, &xwa)) {
    LOG_TRACE(("  ERR: XGetWindowAttributes() on icon window failed\n"));
  } else {
    LOG_TRACE(("  geometry from XGetWindowAttributes() = %dx%d+%d+%d\n",
        xwa.width, xwa.height, xwa.x, xwa.y));
    LOG_TRACE(("  mapstate from XGetWindowAttributes() = %s\n",
        xwa.map_state == IsUnmapped
            ? "Unmapped"
            : (xwa.map_state == IsUnviewable ? "Unviewable" : "Viewable")));
  }
#endif
  /* This resets x11 error state (which might have left from X11 calls above)
   */
  x11_ok();
  return NO_MATCH;
}

void dump_icon_list()
{
  icon_list_forall(&print_icon_data);
}
