/*
 * GkDebconf -- Help to configure packages with debconf
 * Copyleft (C) 2003 Agney Lopes Roth Ferraz <agney@users.sourceforge.net>
 *
 * 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 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.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <dirent.h>
#include <errno.h>

#include <gtk/gtk.h>

#include "../config.h"

#include "defines.h"
#include "debconf.h"
#include "interface.h"
#include "files.h"

#define INFODIR "/var/lib/dpkg/info"
#define CONFIGEXT ".config"

extern gint errno;
extern GtkWidget *main_window;



/**
 * sort_configs:
 *
 * @a: gconstpointer that contains string a.
 * @b: gconstpointer that contains string b.
 *
 *  Compares strings.
 * Returns 0 if string a match string b. A number lass than zero if a is less than b, otherwise if a is greater than b.
 */

int
sort_configs (gconstpointer a, gconstpointer b)
{
  gchar *as = (gchar*)a;
  gchar *bs = (gchar*)b;
  return strcmp(as,bs);
}


/**
 * get_options:
 * This lists the *.config files in /var/lib/dpkg/info  and list them in Glist as packages wich
 * can be configured
 *
 * Returns a Glist with packages that can be configured.
 */

GList *get_options ()
{
  DIR *dir;
  struct dirent *dent;
  gchar *point;
  gint i;
  GList *cflist = NULL;

  if ((dir = opendir (INFODIR)) == NULL)
    {
      perror(_("Opening "INFODIR));
      return NULL;
    }

  for (i = 3 ; (dent = readdir (dir)) ; i++)
    {
      if ((point = strrchr (dent->d_name, '.')) == NULL)
        continue;

      if (!strcmp (point, CONFIGEXT))
        {
          bzero (point, strlen(point));
          cflist = g_list_insert_sorted (cflist,
                                         g_strdup (dent->d_name),
                                         sort_configs);
        }
    }

  closedir(dir);

  return cflist;
}

/**
 * pkg_info:
 *
 * @all_pkgs: Glist that contains packages names.
 *  Gets all sections of installed packages
 *
 * Returns package section and description on packages on all_pkgs.
 */

GList **pkg_info(GList *all_pkgs)
{
  GList **pkg_info;
  GList *pkg_descriptions = NULL;
  GList *pkg_sections = NULL;
  GList *all_pkgs_copy;

  FILE *fd;

  gchar *p = NULL;
  gchar str[100], s[20];
  GString *desc, *cmd;
  pkg_info = malloc (sizeof (GList*) * 2);
  pkg_info[0] = NULL;
  pkg_info[1] = NULL;
  all_pkgs_copy = all_pkgs;


  cmd = g_string_new("/usr/bin/dpkg -s");

  while (all_pkgs_copy)
    {
      p = all_pkgs_copy->data;
      all_pkgs_copy = all_pkgs_copy->next;

      g_string_append(cmd, " ");
      g_string_append(cmd, p);
    }

  if ((fd = popen(cmd->str, "r")) == NULL)
    {
      fprintf(stderr, "Can't open pipe for dpkg\n");
      return NULL;
    }

  while (! feof(fd))
    {
      char *res = NULL;

      res = fgets(str, 100, fd);
      if (res && strstr(str, "Section: "))
        {
          strcpy(s, str + 9);
          if (s[strlen(s)-1] == '\n')
            s[strlen(s)-1] = '\0';

          p = strdup(s);

          pkg_sections = g_list_append(pkg_sections, p);
        }


      if (res && strstr(str, "Description: "))
        {
          desc = g_string_new( str + 12);
          res = fgets(str, 100, fd);

          do
            {
              if (*str)
                {
                  int str_len = strlen(str);
                  if (!strcmp(str+(str_len-3)," .\n"))
                    str[str_len-2] = ' ';
                  g_string_append(desc, str);
                }
              res = fgets(str, 100, fd);
            }
          while (res && !feof(fd) && !strstr(str,"Package: "));

          p = desc->str;

          pkg_descriptions = g_list_append(pkg_descriptions, p);
          g_string_free(desc,0);	/* free wrapper but keep string */
        }
    }

  fclose(fd);

  g_string_free(cmd,1);

  pkg_info[0] = pkg_sections;
  pkg_info[1] = pkg_descriptions;

  return pkg_info;

}

/**
 * pkg_sections:
 *
 * @pkg_sections: Glist that contains packages sections.
 *
 * Extracts sections for the list from all package sections
 * Returns a Glist of sections.
 */

GList *sections(GList *pkg_sections)
{
  GList *sections = NULL;
  GList *pkg_sections_copy;
  gchar *data;

  pkg_sections_copy = g_list_copy(pkg_sections);

  while (pkg_sections_copy)
    {
      data = pkg_sections_copy->data;

      pkg_sections_copy = pkg_sections_copy->next;

      if (strlen(data) != 0)
        {

          if (g_list_find_custom(sections, data, sort_configs) == NULL)
            {
              sections = g_list_insert_sorted(sections, data, sort_configs);
            }
        }

    }
  /* Add virtual section. labeled "*" for displaying all packages */
  sections = g_list_insert_sorted(sections, "*", sort_configs);

  return sections;
}
