#!/usr/bin/python

import sys
import os
import string
import StringIO

def cvtip(ipaddr):
    (one, two, three, four) = split(".", ipaddr)
    ipnum = (int(one) << 24) + (int(two) << 16) + (int(three) << 8) + (int(four))
    return ipnum

class NetGroup:
    def __init__(self, file=None):
        self.defaults = {
            "network": "UNSET",
            "netmask": "UNSET",
            "broadcast": "UNSET",
            "gateway": "UNSET",
            "nameserver": "UNSET"
            "domain": "UNSET"
            }
        self.db = []

        if file is not None:
            line = file.readline()
            done = 0
            indb = 0
            while not done:
                if not line:
                    break
                if line[-1] == "\n":
                    line = line[:-1]

                if len(line) < 1:
                    if indb:
                        done = 1
                    else:
                        indb = 1
                        line = file.readline()
                    continue

                fields = string.split(line)
                if indb:
                    self.db.append(fields)
                else:
                    self.defaults[fields[0]] = fields[1]

                line = file.readline()

    def setdefaults(self, network="UNSET", netmask="UNSET", broadcast="UNSET",
                    gateway="UNSET", nameserver="UNSET", domain="UNSET"):
        if network == "UNSET":
            raise NameError, "network not specified"
        if netmask == "UNSET":
            raise NameError, "netmask not specified"

        self.network = network
        self.netmask = netmask

        if broadcast == "UNSET":
            bcastnum = cvtip(self.network) | (~cvtip(self.netmask) & 0xffffffff)
            self.broadcast = "%d.%d.%d.%d" % (bcastnum >> 24,
                                              (bcastnum >> 16) & 0xff,
                                              (bcastnum >> 8) & 0xff,
                                              bcastnum & 0xff)
        else:
            self.broadcast = broadcast

        if gateway != "UNSET":
            self.gateway = gateway
        if nameserver != "UNSET":
            self.nameserver = nameserver
        if domain != "UNSET":
            self.domain = domain

    def add(self, macaddr, ipaddr):
        self.db.append([macaddr, ipaddr])

    def remove(self, macaddr="UNSET", ipaddr="UNSET"):
        if macaddr == "UNSET" and ipaddr == "UNSET":
            raise NameError, "must specify a MAC addr or IP addr to remove"

        for dbentry in self.db:
            if macaddr in ("UNSET", dbentry[0]) and ipaddr in ("UNSET", dbentry[1]):
                self.db.remove(dbentry)
                break

    def isempty(self):
        return (len(self.db) == 0)

    def str(self):
        buf = StringIO.StringIO()

        for defkey in self.defaults.keys():
            if self.defaults[defkey] != "UNSET":
                buf.write("%s %s\n" % (defkey, self.defaults[defkey]))

        buf.write("\n")

        for dbentry in self.db:
            buf.write("%s %s\n" % (dbentry[0], dbentry[1]))

        buf.write("\n")

        selfstr = buf.getvalue()
        buf.close()

        return selfstr

    def fwrite(self, file):
        file.write(self.str())

class NetDb:
    def __init__(self, file=None):
        self.dblist = []

        if file is not None:
            newdb = NetGroup(file)
            while not newdb.isempty():
                self.dblist.append(newdb)
                newdb = NetGroup(file)

    def fwrite(self, file):
        for dbentry in self.dblist:
            dbentry.fwrite(file)

    def add(self, dbentry):
        self.dblist.append(dbentry)

    def remove(self, dbentry):
        self.dblist.remove(dbentry)

    def groups(self):
        return self.dblist

class PkgList:
    def __init__(self, file=None):
        self.pkglist = []

        pipe = 0
        if file is None:
            file = os.popen("dpkg --get-selections")
            pipe = 1

        line = file.readline()
        while line:
            if line[-1] == "\n":
                line = line[:-1]
            fields = string.split(line)
            self.pkglist.append(fields)
            line = file.readline()

        if pipe:
            file.close()

    def fwrite(self, file):
        for pkg in self.pkglist:
            file.write("%s\t%s\n" % (pkg[0], pkg[1]))

    def getpkgs(self):
        l = []
        for pkg in self.pkglist:
            l.append(pkg[0])
        return l

    def getstatus(self, pkg):
        for listpkg in self.pkglist:
            if listpkg[0] == pkg:
                return listpkg[1]
        raise ValueError, "package not in package list"

    def setstatus(self, pkg, status):
        for listpkg in self.pkglist:
            if listpkg[0] == pkg:
                listpkg[1] = status
                return
        raise ValueError, "package not in package list"

# Code for testing the above classes.

def test():
    print "Testing NetDb..."
    f = open("../conf/network.cfg", "r")
    netdb = NetDb(f)
    f.close()
    for netgroup in netdb.groups():
        print "Network group:"
        for defaultkey in netgroup.defaults.keys():
            print " %s: %s" % (defaultkey, netgroup.defaults[defaultkey])
        print "Items:"
        for netitem in netgroup.db:
            print " %s -> %s" % (netitem[0], netitem[1])

    print "Writing save file to stdout."
    netdb.fwrite(sys.stdout)
    print "Save file done."

    print "Testing PkgList..."
    f = open("../conf/select.cfg", "r")
    for pkglist in (PkgList(f), PkgList()):
        print "Setting libc6's status..."
        pkglist.setstatus("libc6", "foo")
        print "Listing packages..."
        for pkg in pkglist.getpkgs():
            print "package: %s, status %s" % \
                  (pkg, pkglist.getstatus(pkg))
        print "Writing save file to stdout."
        pkglist.fwrite(sys.stdout)
        print "Save file done."
    f.close()

test()
