#!/usr/bin/env python

import os
import gobject
import glob
import dbus
import dbus.service
import dbus.mainloop.glib
import re
from obmc.dbuslib.bindings import get_dbus

from obmc.sensors import SensorValue as SensorValue
from obmc.sensors import HwmonSensor as HwmonSensor
from obmc.sensors import SensorThresholds as SensorThresholds

try:
    import obmc_system_config as System
    have_system = True
except ImportError:
    have_system = False

SENSOR_BUS = 'org.openbmc.Sensors'
SENSOR_PATH = '/org/openbmc/sensors'
DIR_POLL_INTERVAL = 30000
HWMON_PATH = '/sys/class/hwmon'

## static define which interface each property is under
## need a better way that is not slow
IFACE_LOOKUP = {
    'units': SensorValue.IFACE_NAME,
    'adjust': HwmonSensor.IFACE_NAME,
    'scale': HwmonSensor.IFACE_NAME,
    'offset': HwmonSensor.IFACE_NAME,
    'critical_upper': SensorThresholds.IFACE_NAME,
    'warning_upper': SensorThresholds.IFACE_NAME,
    'critical_lower': SensorThresholds.IFACE_NAME,
    'warning_lower': SensorThresholds.IFACE_NAME,
    'emergency_enabled': SensorThresholds.IFACE_NAME,
}


class Hwmons():
    def __init__(self, bus):
        self.sensors = {}
        self.hwmon_root = {}

        if have_system:
            self.scanDirectory()
            gobject.timeout_add(DIR_POLL_INTERVAL, self.scanDirectory)

    def readAttribute(self, filename):
        val = "-1"
        try:
            with open(filename, 'r') as f:
                for line in f:
                    val = line.rstrip('\n')
        except (OSError, IOError):
            print "Cannot read attributes:", filename
        return val

    def writeAttribute(self, filename, value):
        with open(filename, 'w') as f:
            f.write(str(value)+'\n')

    def poll(self, objpath, attribute):
        try:
            raw_value = int(self.readAttribute(attribute))
            obj = bus.get_object(SENSOR_BUS, objpath, introspect=False)
            intf = dbus.Interface(obj, HwmonSensor.IFACE_NAME)
            rtn = intf.setByPoll(raw_value)
            if rtn[0]:
                self.writeAttribute(attribute, rtn[1])
        except:
            print "HWMON: Attibute no longer exists: "+attribute
            self.sensors.pop(objpath, None)
            return False

        return True

    def addObject(self, dpath, hwmon_path, hwmon):
        objsuf = hwmon['object_path']
        objpath = SENSOR_PATH+'/'+objsuf

        if objpath not in self.sensors:
            print "HWMON add: "+objpath+" : "+hwmon_path

            ## register object with sensor manager
            obj = bus.get_object(SENSOR_BUS, SENSOR_PATH, introspect=False)
            intf = dbus.Interface(obj, SENSOR_BUS)
            intf.register("HwmonSensor", objpath)

            ## set some properties in dbus object
            obj = bus.get_object(SENSOR_BUS, objpath, introspect=False)
            intf = dbus.Interface(obj, dbus.PROPERTIES_IFACE)
            intf.Set(HwmonSensor.IFACE_NAME, 'filename', hwmon_path)

            ## check if one of thresholds is defined to know
            ## whether to enable thresholds or not
            if 'critical_upper' in hwmon:
                intf.Set(
                    SensorThresholds.IFACE_NAME, 'thresholds_enabled', True)

            for prop in hwmon.keys():
                if prop in IFACE_LOOKUP:
                    intf.Set(IFACE_LOOKUP[prop], prop, hwmon[prop])
                    print "Setting: "+prop+" = "+str(hwmon[prop])

            self.sensors[objpath] = True
            self.hwmon_root[dpath].append(objpath)
            gobject.timeout_add(
                hwmon['poll_interval'], self.poll, objpath, hwmon_path)

    def scanDirectory(self):
        devices = os.listdir(HWMON_PATH)
        found_hwmon = {}
        regx = re.compile('([a-z]+)\d+\_')
        for d in devices:
            dpath = HWMON_PATH+'/'+d+'/'
            found_hwmon[dpath] = True
            if dpath not in self.hwmon_root:
                self.hwmon_root[dpath] = []
            ## the instance name is a soft link
            instance_name = os.path.realpath(dpath+'device').split('/').pop()

            if instance_name in System.HWMON_CONFIG:
                hwmon = System.HWMON_CONFIG[instance_name]

                if 'labels' in hwmon:
                    label_files = glob.glob(dpath+'/*_label')
                    for f in label_files:
                        label_key = self.readAttribute(f)
                        if label_key in hwmon['labels']:
                            namef = f.replace('_label', '_input')
                            self.addObject(
                                dpath, namef, hwmon['labels'][label_key])
                        else:
                            pass

                if 'names' in hwmon:
                    for attribute in hwmon['names'].keys():
                        self.addObject(
                            dpath, dpath+attribute, hwmon['names'][attribute])

            else:
                print "WARNING - hwmon: Unhandled hwmon: "+dpath

        for k in self.hwmon_root.keys():
            if k not in found_hwmon:
                ## need to remove all objects associated with this path
                print "Removing: "+k
                for objpath in self.hwmon_root[k]:
                    if objpath in self.sensors:
                        print "HWMON remove: "+objpath
                        self.sensors.pop(objpath, None)
                        obj = bus.get_object(
                            SENSOR_BUS, SENSOR_PATH, introspect=False)
                        intf = dbus.Interface(obj, SENSOR_BUS)
                        intf.delete(objpath)

                self.hwmon_root.pop(k, None)

        return True


if __name__ == '__main__':
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
    bus = get_dbus()
    root_sensor = Hwmons(bus)
    mainloop = gobject.MainLoop()

    print "Starting HWMON sensors"
    mainloop.run()

# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
