#!/bin/env python
import dbus, sys, os
sys.path.append("/usr/share/system-config-printer")
import cups, cupshelpers, foomatic

class HalPrinter:
    def __init__(self):
        self.get_properties()
        try:
            self.cups_connection = cups.Connection()
        except RuntimeError:
            self.cups_connection = None

    def get_properties(self):
        self.properties = {}
        for key, value in os.environ.iteritems():
            if key.startswith("HAL_PROP_"):
                name = key[9:].lower().replace("_", '.')
                self.properties[name] = value
        self.uid = os.getenv("UDI", "")
        self.read()

    def read(self):
        p = self.properties
        self.make = (p.get("printer.vendor", "") or
                     p.get("usb.vendor", "Unknown"))
        self.model = (p.get("printer.product", "") or
                      p.get("usb.product", "Unknown"))
        self.description = p.get("printer.description", "")
        self.name = self.get_name()

    def get_name(self):
        # XXX check for unallowed chars
        if self.properties.has_key("usb.port_number"):
            name = "%s-%s" % (self.model,
                              self.properties["usb.port_number"])
        else:
            name = self.model
        name = name.replace(" ", "_")
        name = name.replace("/", "_")
        return name.replace("#", "_")

    def get_cups_uris(self):
        return ["hal://%s" % self.uid,
                ]

    def get_cups_uri(self):
        return "hal://%s" % self.uid

    def match(self, printer):
        if printer.is_class: return False
        if (printer.name.lower() == self.name.lower() or
            printer.device_uri == self.properties.get("linux.device.file", False)):
            return True

    def add(self):
        printers = cupshelpers.getPrinters(self.cups_connection)
        found = False

        for name, printer in printers.iteritems():
            if printer.is_class: continue
            if (name == self.name or
                printer.device_uri == self.properties.get("linux.device.file", False)):
                if not printer.enabled:
                    printer.setEnabled(True)
                found = True
            pass
        if found:
            return

        # really new printer - try autodetection
        
        f = foomatic.Foomatic()
        ppd = f.getPPD(self.make, self.model, self.description)
        if ppd:
            self.cups_connection.addPrinter(
                self.name, device=self.get_cups_uri(),
                ppd=ppd, info="Added by HAL")
            self.cups_connection.enablePrinter(self.name)
            self.cups_connection.acceptJobs(self.name)

            # XXX log
        else:
            # ask eggcups
            try:
                bus = dbus.SystemBus()
                obj = bus.get_object("com.redhat.PrintDriverSelection",
                                     "/com/redhat/PrintDriverSelection")
                interface = dbus.Interface(obj, "com.redhat.PrintDriverSelection")
                interface.PromptPrintDriver(self.make, self.model,
                                            self.uid, self.name)
            except:
                # XXX Error handling
                pass
        
    def remove(self):
        printers = cupshelpers.getPrinters(self.cups_connection)

        for name, printer in printers.iteritems():
            if printer.is_class: continue
            if (name == self.name or
                printer.device_uri == self.properties.get("linux.device.file", False)):
                if printer.enabled:
                    printer.setEnabled(False)
        # XXX log, error handling

    def configure(self):
        make, model = sys.stdin.readlines()
        if make[-1]=="\n": make = make[:-1]
        if model[-1]=="\n": model = model[:-1]

        # get PPD
        f = foomatic.Foomatic()
        printer = f.getMakeModel(make, model)

        if not printer: return
        
        ppd = printer.getPPD()
        
        if ppd:
            # add printer
            self.cups_connection.addPrinter(
                self.name, device=self.get_cups_uri(),
                ppd=ppd, info="Added by HAL")
            self.cups_connection.enablePrinter(self.name)
            self.cups_connection.acceptJobs(self.name)

class HalLpAdmin:

    def __init__(self):
        if len(sys.argv)!=2:
            return self.usage()

        if sys.argv[1]=="--add":
            self.addPrinter()
        elif sys.argv[1]=="--remove":
            self.removePrinter()
        elif sys.argv[1]=="--configure":
            self.configurePrinter()
        else:
            return usage()

    def usage(self):
        print "Usage: hal_lpadmin (--add|--remove|--configure)"

    def addPrinter(self):
        printer = HalPrinter()
        printer.add()
        
    def removePrinter(self):
        printer = HalPrinter()
        printer.remove()

    def configurePrinter(self):
        printer = HalPrinter()
        printer.configure()

def main():
    try:
        h = HalLpAdmin()
    except Exception, e:
        pass # XXX error handling
main()
