/*
 * Copyright (c) 2004-2006 Jean-François Wauthy (pollux@xfce.org)
 *
 * 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 2 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 Library General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <gmodule.h>

#ifdef HAVE_STRING_H
#include <string.h>
#endif

#include <libxfcegui4/libxfcegui4.h>
#include <libxfce4util/libxfce4util.h>

#include <libxfprint/libxfprint.h>

/* globals */
G_MODULE_EXPORT const gchar name[] = "BSD-LPR";
G_MODULE_EXPORT const gchar description[] = N_("BSD-LPR printing system support for Xfprint");
G_MODULE_EXPORT const gchar version[] = VERSION;
G_MODULE_EXPORT const gchar author[] = "Jean-François Wauthy";
G_MODULE_EXPORT const gchar homepage[] = "http://www.xfce.org";

static gint
compare_printer_name (Printer * a, Printer * b)
{
  return (g_ascii_strcasecmp (a->name, b->name));
}

G_MODULE_EXPORT GList *
get_printers ()
{
  GList *list = NULL;
  FILE *printcap;
  gchar buf[1024];

  /* load printer list from printcap file */
  printcap = fopen (PRINTCAP_PATH, "r-");

  if (!printcap) {
    g_warning ("unable to open printcap file : %s", PRINTCAP_PATH);
    return list;
  }

  while (fgets (buf, sizeof (buf), printcap)) {
    int i = 0;
    int token_start = 0;

    if (buf[0] == '#')
      continue;

    while (i < strlen (buf)) {
      
      if (buf[i] == '|' || buf[i] == ':' || buf[i] == '\n' || buf[i] == '\r') {
	gchar *printer_name = NULL;

	printer_name = g_strndup (&buf[token_start], i - token_start);
	g_strstrip (printer_name);

	if (strlen (printer_name) != 0) {
	  Printer *printer;

	  printer = g_new0 (Printer, 1);

	  printer->name = g_strdup (printer_name);
	  printer->alias = g_strdup (printer_name);

	  if (g_list_find_custom (list, printer, (GCompareFunc) compare_printer_name) == NULL)
	    list = g_list_append (list, printer);
	  else
	    printer_free (printer);
	}

	g_free (printer_name);
	
	if (buf[i] == '|')
	  token_start = i + 1;
	else
	  break;
      }

      i++;
    }
  }

  fclose (printcap);

  return list;
}

G_MODULE_EXPORT Printer *
get_default_printer ()
{
  const gchar *default_printer = NULL;
  Printer *printer = NULL;

  default_printer = g_getenv ("PRINTER");

  if (default_printer) {
    GList *printers = get_printers ();
    printer = printer_lookup_byname (printers, default_printer);
    printers_free (printers);
  }

  return printer;
}

G_MODULE_EXPORT gint
get_printer_state (const gchar * printer)
{
  return PRINTER_STATE_UNKNOWN;
}

G_MODULE_EXPORT gint
get_printer_jobs_count (const gchar * printer)
{
  return -1;
}

/*-----------------------------*/
/* printer list customizations */
/*-----------------------------*/
G_MODULE_EXPORT void
customize_printer_list_window (PrinterListWindow * win)
{
  printer_list_window_hide_column (win, PRINTER_LIST_WINDOW_STATE_COLUMN);
}

/*-----------------------------*/
/* printer queue customization */
/*-----------------------------*/
G_MODULE_EXPORT void
customize_printer_queue_window (PrinterQueueWindow * win)
{
  printer_queue_window_hide_column (win, PRINTER_QUEUE_WINDOW_PRIORITY_COLUMN);
  printer_queue_window_hide_column (win, PRINTER_QUEUE_WINDOW_CREATION_TIME_COLUMN);
  printer_queue_window_hide_column (win, PRINTER_QUEUE_WINDOW_PROCESSING_TIME_COLUMN);
}

G_MODULE_EXPORT GList *
get_jobs (const gchar * printer)
{
  GList *list = NULL;
  gchar *output;
  gint exit_status;
  gchar *cmd;
  gchar **argv;

  cmd = g_strdup_printf ("lpq -P%s", printer);

  if (!g_shell_parse_argv (cmd, NULL, &argv, NULL)) {
    g_free (cmd);
    g_strfreev (argv);
    return NULL;
  }

  /* TODO add LC_ALL=C in envp */
  if (g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &output, NULL, &exit_status, NULL)) {
    gchar **lines;
    int n;
    int i;
    gboolean format_ok = FALSE;
    gint start_line = 65535;

    lines = g_strsplit (output, "\n", 0);

    /* get the number of lines */
    for (n = 0; lines[n] != NULL; n++)
      if (g_str_has_prefix (lines[n], "Rank")) {
        format_ok = TRUE;
        start_line = n + 1;
      }
    n--;

    if (!format_ok) {
      DBG ("job list is empty");
      g_free (cmd);
      g_free (output);
      g_strfreev (lines);
      g_strfreev (argv);
      return NULL;
    }

    /* parse the output and create the job list */
    for (i = start_line; i < n; i++) {
      gchar rank[25];
      gchar owner[25];
      guint job_id;
      gchar file[50];
      guint size;
      Job *job;

      if (strlen (lines[i]) == 0)
        continue;

      if (sscanf (lines[i], "%s%s%d%s%d", rank, owner, &job_id, file, &size) != 5)
        continue;

      job = g_new0 (Job, 1);

      job->name = g_strdup (file);
      job->id = job_id;
      job->state = g_ascii_strcasecmp (rank, "active") == 0 ? JOB_STATE_PRINTING : JOB_STATE_PENDING;
      job->user = g_strdup (owner);
      job->size = size / 1024;

      list = g_list_append (list, job);
    }

    g_free (output);
    g_strfreev (lines);
  }

  g_free (cmd);
  g_strfreev (argv);
  return list;
}

G_MODULE_EXPORT gboolean
remove_job (const gchar * printer, gint id)
{
  gchar *cmd = NULL;
  gboolean ret = FALSE;

  cmd = g_strdup_printf ("lprm -P%s %d", printer, id);
  DBG ("executing '%s'", cmd);
  ret = xfce_exec (cmd, FALSE, FALSE, NULL);
  g_free (cmd);

  return ret;
}

G_MODULE_EXPORT gboolean
print_file (const gchar * printer, const gchar * original_name, const gchar * file, gboolean remove_file)
{
  gchar *cmd = NULL;
  gchar *base_name = NULL;
  gboolean ret = FALSE;

  base_name = g_path_get_basename (original_name);

  cmd = g_strdup_printf ("lpr -P%s -T %s %s", printer, base_name, file);
  ret = xfce_exec_sync (cmd, FALSE, FALSE, NULL);

  if (remove_file)
    unlink (file);

  g_free (cmd);
  g_free (base_name);

  return ret;
}
