#!/usr/bin/python -u

import sys
import subprocess
#from gi.repository import GObject
import gobject
import dbus
import dbus.service
import dbus.mainloop.glib
import os
import Openbmc

## Abstract class, must subclass
class SensorValue(Openbmc.DbusProperties):
	IFACE_NAME = 'org.openbmc.SensorValue'
	def __init__(self,bus,name):
		#Openbmc.DbusProperties.__init__(self)
		self.Set(SensorValue.IFACE_NAME,'units',"")
		self.Set(SensorValue.IFACE_NAME,'error',False)
		
	@dbus.service.method(IFACE_NAME,
		in_signature='v', out_signature='')
	def setValue(self,value):
		self.Set(SensorValue.IFACE_NAME,'value',value)

	@dbus.service.method(IFACE_NAME,
		in_signature='', out_signature='v')
	def getValue(self):
		return self.Get(SensorValue.IFACE_NAME,'value')

class SensorThresholds(Openbmc.DbusProperties):
	IFACE_NAME = 'org.openbmc.SensorThresholds'
	def __init__(self,bus,name):
		self.Set(SensorThresholds.IFACE_NAME,'thresholds_enabled',False)
		self.Set(SensorThresholds.IFACE_NAME,'emergency_enabled',False)
		self.Set(SensorThresholds.IFACE_NAME,'warning_upper',0)
		self.Set(SensorThresholds.IFACE_NAME,'warning_lower',0)
		self.Set(SensorThresholds.IFACE_NAME,'critical_upper',0)
		self.Set(SensorThresholds.IFACE_NAME,'critical_lower',0)
		self.Set(SensorThresholds.IFACE_NAME,'critical_lower',0)
		self.Set(SensorThresholds.IFACE_NAME,'threshold_state',"NORMAL")
		self.Set(SensorThresholds.IFACE_NAME,'worst_threshold_state',"NORMAL")
	
	@dbus.service.method(IFACE_NAME,
		in_signature='', out_signature='')
	def resetThresholdState(self):
		self.Set(SensorThresholds.IFACE_NAME,'worst_threshold_state',"NORMAL")

	def check_thresholds(self,value):
		iface = SensorThresholds.IFACE_NAME
		if (self.Get(iface,'thresholds_enabled') == False):
			return False
		rtn = False
		current_state = "NORMAL"
		if (value >= self.properties[iface]['critical_upper']):
			current_state = "CRITICAL"
			rtn = True
		elif (value <= self.properties[iface]['critical_lower']):
			current_state = "CRITICAL"
			rtn = True
		elif (value >= self.properties[iface]['warning_upper']):
			current_state = "WARNING"
			rtn = True
		elif (value <= self.properties[iface]['warning_lower']):
			current_state = "WARNING"
			rtn = True

		if (self.Get(iface,'threshold_state') != current_state and
		 		current_state == "CRITICAL" and
				self.Get(iface,'emergency_enabled') == True):
			self.Emergency()

		self.Set(iface,'threshold_state',current_state)
		worst = self.properties[iface]['worst_threshold_state']
		if (current_state == "CRITICAL" or 
		   (current_state == "WARNING" and worst != "CRITICAL")):
			self.Set(iface,'worst_threshold_state',current_state)

		return rtn

	@dbus.service.signal(IFACE_NAME,signature='')
	def Emergency(self):
		pass


class VirtualSensor(SensorValue):
	def __init__(self,bus,name):
		Openbmc.DbusProperties.__init__(self)
		SensorValue.__init__(self,bus,name)
		dbus.service.Object.__init__(self,bus,name)

class HwmonSensor(SensorValue,SensorThresholds):
	IFACE_NAME = 'org.openbmc.HwmonSensor'
	def __init__(self,bus,name):
		Openbmc.DbusProperties.__init__(self)
		SensorValue.__init__(self,bus,name)
		SensorThresholds.__init__(self,bus,name)
		self.Set(HwmonSensor.IFACE_NAME,'scale',1)
		self.Set(HwmonSensor.IFACE_NAME,'offset',0)
		self.Set(HwmonSensor.IFACE_NAME,'filename','')
		self.value_dirty = False

		# need to cache value to know if changed
		self.value = None
		dbus.service.Object.__init__(self,bus,name)

	@dbus.service.method(SensorValue.IFACE_NAME,
		in_signature='v', out_signature='')
	def setValue(self,value):
		self.value_dirty = True
		SensorValue.setValue(self,value)

	## Called by sensor process to update value from polling
	## if returns not None, then sensor process will update hwmon value
	@dbus.service.method(IFACE_NAME,
		in_signature='v', out_signature='(bv)')
	def setByPoll(self,value):
		scale = self.properties[HwmonSensor.IFACE_NAME]['scale']
		offset = self.properties[HwmonSensor.IFACE_NAME]['offset']
		if (self.value_dirty == True):
			## new value externally set, so just return to hwmon
			## process to write value
			self.value_dirty = False
			val = (self.properties[SensorValue.IFACE_NAME]['value']-offset) * scale
			return [True,val]
		else:
			# Keep the val as integer. scale may be floating point
			val = int(value/scale + offset)
			if (val != self.value):
				SensorValue.setValue(self,val)
				self.check_thresholds(val)
				self.value = val

			return [False,0]
		
CONTROL_IFACE = 'org.openbmc.Control'
class PowerCap(VirtualSensor):
	def __init__(self, bus, name):
		VirtualSensor.__init__(self, bus, name)
		SensorValue.setValue(self, 0)
		self.sysfs_attr = "/sys/class/hwmon/hwmon3/user_powercap"
	##override setValue method
	@dbus.service.method(SensorValue.IFACE_NAME,
		in_signature='v', out_signature='')
	def setValue(self, value):
		try:
			cmd_str = "echo "+str(value)+" > "+self.sysfs_attr
			ret = subprocess.check_output(cmd_str, shell=True)
		except subprocess.CalledProcessError as powerexc:
			print "Set PowerCap Error", powerexc.returncode,
			powerexc.output
			return
		print "Set PowerCap: ", value
		SensorValue.setValue(self, value)
		
class BootProgressSensor(VirtualSensor):
	def __init__(self,bus,name):
		VirtualSensor.__init__(self,bus,name)
		self.setValue("Off")
		bus.add_signal_receiver(self.SystemStateHandler,signal_name = "GotoSystemState")

	def SystemStateHandler(self,state):
		if (state == "HOST_POWERED_OFF"):
			self.setValue("Off")


	##override setValue method
	@dbus.service.method(SensorValue.IFACE_NAME,
		in_signature='v', out_signature='')
	def setValue(self,value):
		SensorValue.setValue(self,value)
		if (value == "FW Progress, Starting OS"):
			self.GotoSystemState("HOST_BOOTED")
			
	@dbus.service.signal(CONTROL_IFACE,signature='s')
	def GotoSystemState(self,state):
		pass
		
class OccStatusSensor(VirtualSensor):
	def __init__(self,bus,name, sysfs = None):
		## default path. can be override
		if sysfs is None:
			self.sysfs_attr = "/sys/class/i2c-adapter/i2c-3/3-0050/online"
		else:
			self.sysfs_attr = sysfs
		VirtualSensor.__init__(self,bus,name)
		self.setValue("Disabled")
		bus.add_signal_receiver(self.SystemStateHandler,signal_name = "GotoSystemState")

	def SystemStateHandler(self,state):
		if (state == "HOST_POWERED_OFF"):
			self.setValue("Disabled")

	##override setValue method
	@dbus.service.method(SensorValue.IFACE_NAME,
		in_signature='v', out_signature='')
	def setValue(self,value):
		if (value == "Enabled"):
			print "Installing OCC device"
			os.system("echo 1 > " +  self.sysfs_attr)
		else:
			print "Deleting OCC device"
			os.system("echo 0 > " +  self.sysfs_attr)
		SensorValue.setValue(self,value)
			
	@dbus.service.signal(CONTROL_IFACE,signature='s')
	def GotoSystemState(self,state):
		pass
	
class BootCountSensor(VirtualSensor):
	def __init__(self,bus,name):
		VirtualSensor.__init__(self,bus,name)
		self.setValue(2)

class OperatingSystemStatusSensor(VirtualSensor):
	def __init__(self,bus,name):
		VirtualSensor.__init__(self,bus,name)
		self.setValue("Off")
		bus.add_signal_receiver(self.SystemStateHandler,signal_name = "GotoSystemState")

	def SystemStateHandler(self,state):
		if (state == "HOST_POWERED_OFF"):
			self.setValue("Off")
