#!/usr/bin/python -u

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

DBUS_NAME = 'org.openbmc.control.Chassis'
OBJ_NAME = '/org/openbmc/control/'+sys.argv[1]
CONTROL_INTF = 'org.openbmc.Control'

POWER_OFF = 0
POWER_ON = 1

BOOTED = 100

def getWatchdog():
    obj =  bus.get_object('org.openbmc.watchdog.Host',
            '/org/openbmc/watchdog/HostWatchdog_0')
    intf = dbus.Interface(obj, 'org.openbmc.Watchdog' )
    return intf

class ChassisControlObject(Openbmc.DbusProperties):
	def __init__(self,bus,name):
		self.dbus_objects = { }
		Openbmc.DbusProperties.__init__(self)
		dbus.service.Object.__init__(self,bus,name)
		## load utilized objects
		self.dbus_objects = {
			'power_control' : { 
				'bus_name' : 'org.openbmc.control.Power',
				'object_name' : '/org/openbmc/control/power0',
				'interface_name' : 'org.openbmc.control.Power'
			},
			'identify_led' : {
				'bus_name' : 'org.openbmc.control.led',
				'object_name' : '/org/openbmc/led/IDENTIFY',
				'interface_name' : 'org.openbmc.Led'
			}
		}

		#uuid
		self.Set(DBUS_NAME,"uuid",str(uuid.uuid1()))
		self.Set(DBUS_NAME,"reboot",0)
		self.Set(DBUS_NAME,"power_policy",0)	
		self.Set(DBUS_NAME,"last_system_state","")	

		bus.add_signal_receiver(self.power_button_signal_handler, 
					dbus_interface = "org.openbmc.Button", signal_name = "ButtonPressed", 
					path="/org/openbmc/buttons/PowerButton_0" )
    		bus.add_signal_receiver(self.host_watchdog_signal_handler, 
					dbus_interface = "org.openbmc.Watchdog", signal_name = "WatchdogError")
		bus.add_signal_receiver(self.SystemStateHandler,signal_name = "GotoSystemState")


	def getInterface(self,name):
		o = self.dbus_objects[name]
		obj = bus.get_object(o['bus_name'],o['object_name'])
		return dbus.Interface(obj,o['interface_name'])


	@dbus.service.method(DBUS_NAME,
		in_signature='', out_signature='')
	def setIdentify(self):
		print "Turn on identify"
		intf = self.getInterface('identify_led')
		intf.setOn()	
		return None

	@dbus.service.method(DBUS_NAME,
		in_signature='', out_signature='')
	def clearIdentify(self):
		print "Turn on identify"
		intf = self.getInterface('identify_led')
		intf.setOff()
		return None

	@dbus.service.method(DBUS_NAME,
		in_signature='', out_signature='')
	def powerOn(self):
		print "Turn on power and boot"
		self.Set(DBUS_NAME,"reboot",0)
		if (self.getPowerState()==0):
			intf = self.getInterface('power_control')
			intf.setPowerState(POWER_ON)
			intfwatchdog = getWatchdog()
			#Start watchdog with 30s timeout per the OpenPower Host IPMI Spec
			#Once the host starts booting, it'll reset and refresh the timer
			intfwatchdog.set(30000)
			intfwatchdog.start()
		return None

	@dbus.service.method(DBUS_NAME,
		in_signature='', out_signature='')
	def powerOff(self):
		print "Turn off power"
		intf = self.getInterface('power_control')
		intf.setPowerState(POWER_OFF)
		return None

	@dbus.service.method(DBUS_NAME,
		in_signature='', out_signature='')
	def softPowerOff(self):
		print "Soft off power"
		## TODO: Somehow tell host to shutdown via ipmi
		## for now hard power off
		self.powerOff()	
		return None

	@dbus.service.method(DBUS_NAME,
		in_signature='', out_signature='')
	def reboot(self):
		print "Rebooting"
		self.Set(DBUS_NAME,"reboot",1)
		intf.softPowerOff()
		return None

	@dbus.service.method(DBUS_NAME,
		in_signature='', out_signature='i')
	def getPowerState(self):
		intf = self.getInterface('power_control')
		return intf.getPowerState()

	@dbus.service.method(DBUS_NAME,
		in_signature='', out_signature='')
	def setDebugMode(self):
		return None

	@dbus.service.method(DBUS_NAME,
		in_signature='i', out_signature='')
	def setPowerPolicy(self,policy):
		self.Set(DBUS_NAME,"power_policy",policy)	
		return None


	## Signal handler

	def SystemStateHandler(self,state_name):
		self.Set(DBUS_NAME,"last_system_state",state_name)	
		if (state_name == "HOST_POWERED_OFF" and self.Get(DBUS_NAME,"reboot")==1):
			self.powerOn()
				

	def power_button_signal_handler(self):
		# toggle power
		state = self.getPowerState()
		if state == POWER_OFF:
			self.powerOn()
		elif state == POWER_ON:
			self.powerOff();
		
		# TODO: handle long press and reset

	def host_watchdog_signal_handler(self):
		print "Watchdog Error, Hard Rebooting"
		self.Set(DBUS_NAME,"reboot",1)
		self.powerOff()
		

if __name__ == '__main__':
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

    bus = Openbmc.getDBus()
    name = dbus.service.BusName(DBUS_NAME, bus)
    obj = ChassisControlObject(bus, OBJ_NAME)
    mainloop = gobject.MainLoop()
    
    print "Running ChassisControlService"
    mainloop.run()

