/* bug-buddy bug submitting program
 *
 * Copyright (C) Jacob Berkman
 *
 * Author:  Jacob Berkman  <jberkman@andrew.cmu.edu>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * 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 "config.h"
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include "bug-buddy.h"
#include "distribution.h"

typedef struct _Package      Package;
typedef struct _Phylum       Phylum;
typedef struct _Distribution Distribution;

typedef char *(*DistroVersionFunc) (Distribution *distro);

struct _Phylum {
	DistroVersionFunc version;
};


struct _Distribution {
	char *name;
	char *version_file;
	Phylum *phylum;
};

static char *get_lsb_version (Distribution *distro);
static char *get_redhat_version (Distribution *distro);
static char *get_turbolinux_version (Distribution *distro);
static char *get_debian_version (Distribution *distro);
static char *get_irix_version (Distribution *distro);

Phylum lsb_phy = {
	get_lsb_version
};

Phylum redhat_phy = {
	get_redhat_version
};

Phylum turbolinux_phy = {
	get_turbolinux_version
};

Phylum debian_phy = {
	get_debian_version
};

Phylum irix_phy = {
	get_irix_version
};

DistroVersionFunc lsb_ver =  get_lsb_version;
DistroVersionFunc redhat_ver = get_redhat_version;
DistroVersionFunc turbolinux_ver = get_turbolinux_version;
DistroVersionFunc debian_ver = get_debian_version;
DistroVersionFunc irix_ver =  get_irix_version;

static Distribution distros[] = {
	{ "Slackware",     "/etc/slackware-version",  &debian_phy },
	{ "Mandrake",      "/etc/mandrake-release",   &redhat_phy },
	{ "TurboLinux",    "/etc/turbolinux-release", &turbolinux_phy },
	{ "SuSE",          "/etc/SuSE-release",       &redhat_phy },
	{ "Red Hat",       "/etc/redhat-release",     &redhat_phy },
	{ "Frugalware",    "/etc/frugalware-release", &redhat_phy },
	{ "Fedora",        "/etc/fedora-release",     &redhat_phy },
	{ "Gentoo",        "/etc/gentoo-release",     &redhat_phy },
	{ "Solaris",       "/etc/release",  	      &redhat_phy },
	{ "PLD Linux",     "/etc/pld-release",        &redhat_phy },
	{ "LSB Linux",     "/etc/lsb-release",        &lsb_phy },
	{ "Debian",        "/etc/debian_version",     &debian_phy },
	{ "IRIX Freeware", "/bin/hinv",               &irix_phy },
	{ NULL }
};


static char**
get_lines_from_file (const char *filename)
{
	char *contents;
	gsize length;
	char **lines;
	GError *error = NULL;
	
	if (!g_file_get_contents (filename, &contents, &length, &error)) {
		g_error_free (error);
		return NULL;
	}

	lines = g_strsplit (contents, "\n", 0);
	g_free (contents);
	
	return lines;
}


static char *
get_lsb_version (Distribution *distro)
{
	char **lines;
	char *id = NULL;
	char *release = NULL;
	char *codename = NULL;
	char *name = NULL;
	int i = 0;

	g_return_val_if_fail (distro, NULL);
	g_return_val_if_fail (distro->version_file, NULL);

	lines = get_lines_from_file (distro->version_file);
	while (lines && lines[i]) {
		if (g_str_has_prefix (lines[i], "DISTRIB_ID=")) 
			id = lines[i] + 11;
		else if (g_str_has_prefix (lines[i], "DISTRIB_RELEASE=")) 
			release = lines[i] + 16;
		else if (g_str_has_prefix (lines[i], "DISTRIB_CODENAME=")) 
			codename = lines[i] + 17;
		i++;
	}
	if (id != NULL && release != NULL && codename != NULL)
		name = g_strdup_printf ("%s %s (%s)", id, release, codename);

	g_strfreev (lines);

	return name;
}



static char *
get_redhat_version (Distribution *distro)
{
	char **lines;
	char *name = NULL;

	g_return_val_if_fail (distro, NULL);
	g_return_val_if_fail (distro->version_file, NULL);

	lines = get_lines_from_file (distro->version_file);
	if (lines != NULL && lines[0] != NULL)
		name = g_strdup (lines[0]);

	g_strfreev (lines);

	return name;
}

static char *
get_turbolinux_version (Distribution *distro)
{
	char **lines;
	char *name = NULL;
	g_return_val_if_fail (distro, NULL);
	g_return_val_if_fail (distro->version_file, NULL);

	lines = get_lines_from_file (distro->version_file);
	if (lines != NULL && lines[0] != NULL)
                name = g_strdup_printf ("TurboLinux %s", lines[0]);

	g_strfreev (lines);

	return name;
}


static char *
get_debian_version (Distribution *distro)
{
	char **lines;
	char *name = NULL;

	g_return_val_if_fail (distro, NULL);
	g_return_val_if_fail (distro->version_file, NULL);
	g_return_val_if_fail (distro->name, NULL);

	lines = get_lines_from_file (distro->version_file);
	if (lines != NULL && lines[0] != NULL)
                name = g_strdup_printf ("%s %s", distro->name, lines[0]);

	g_strfreev (lines);

	return name;
}


static char *
get_irix_version (Distribution *distro)
{
	g_return_val_if_fail (distro, NULL);
	g_return_val_if_fail (distro->version_file, NULL);
	return "Irix";
/*
	return get_line_from_command ("/usr/bin/echo -n SGI `/sbin/uname -Rs | /bin/cut -d' ' -f1,3-`; "
				      "versions -b fw_common | awk 'NR >= 4 { print \", Freeware\",$3 }'");*/
}

static char *
get_distro_name_from_file (void)
{
	int i;
        for (i = 0; distros[i].name; i++) {
		if (!g_file_test (distros[i].version_file, G_FILE_TEST_EXISTS))
			continue;
		return distros[i].phylum->version (&distros[i]);
	}
	return NULL;
}

char *
get_distro_name (void)
{
	char *name;

	name = get_distro_name_from_file ();
	if (!name) {
		return g_strdup ("Unknown");
	}

	return name;
}

