# Contributors Listed Below - COPYRIGHT 2016
# [+] International Business Machines Corp.
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied. See the License for the specific language governing
# permissions and limitations under the License.

import os
import subprocess
import dbus
import dbus.service
from obmc.dbuslib.bindings import DbusProperties


# Abstract class, must subclass
class SensorValue(DbusProperties):
    IFACE_NAME = 'org.openbmc.SensorValue'

    def __init__(self, bus, name):
        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 VirtualSensor(SensorValue):
    def __init__(self, bus, name):
        DbusProperties.__init__(self)
        SensorValue.__init__(self, bus, name)
        dbus.service.Object.__init__(self, bus, name)


CONTROL_IFACE = 'org.openbmc.Control'


class BootCountSensor(VirtualSensor):
    def __init__(self, bus, name):
        VirtualSensor.__init__(self, bus, name)
        # Default boot count is 2.  Add 1 onto this to allow for an
        # SBE side switch boot attempt
        self.setValue(3)

    # override setValue method for debug purposes
    @dbus.service.method(
        SensorValue.IFACE_NAME, in_signature='v', out_signature='')
    def setValue(self, value):
        print("Setting boot count to " + str(value))
        SensorValue.setValue(self, value)


class PowerSupplyRedundancySensor(VirtualSensor):
    def __init__(self, bus, name):
        VirtualSensor.__init__(self, bus, name)
        self.bus = bus
        self.bus_name = 'xyz.openbmc_project.Settings'
        self.obj_path = '/xyz/openbmc_project/control/power_supply_redundancy'
        self.iface = 'xyz.openbmc_project.Control.PowerSupplyRedundancy'
        self.prop_iface = 'org.freedesktop.DBus.Properties'
        self.property_name = 'PowerSupplyRedundancyEnabled'
        super(PowerSupplyRedundancySensor, self).setValue(self.getValue())

    # Override setValue method
    @dbus.service.method(
        SensorValue.IFACE_NAME, in_signature='v', out_signature='')
    def setValue(self, value):
        if (value == "Enabled"):
            intf = self.getPowerSupplyInterface()
            intf.Set(self.iface, self.property_name, True)
        elif (value == "Disabled"):
            intf = self.getPowerSupplyInterface()
            intf.Set(self.iface, self.property_name, False)
        else:
            print("Invalid Power Supply Redundancy value")
            return
        super(PowerSupplyRedundancySensor, self).setValue(value)

    # Override getValue method
    @dbus.service.method(
        SensorValue.IFACE_NAME, in_signature='', out_signature='v')
    def getValue(self):
        intf = self.getPowerSupplyInterface()
        value = intf.Get(self.iface, self.property_name)
        if (value == 1):
            return "Enabled"
        elif (value == 0):
            return "Disabled"
        else:
            print("Unable to determine Power Supply Redundancy value")
            return ""

    def getPowerSupplyInterface(self):
        obj = self.bus.get_object(self.bus_name, self.obj_path,
                                  introspect=True)
        return dbus.Interface(obj, self.prop_iface)


class PowerSupplyDeratingSensor(VirtualSensor):
    def __init__(self, bus, name):
        VirtualSensor.__init__(self, bus, name)
        super(PowerSupplyDeratingSensor, self).setValue(90)

    # override setValue method
    @dbus.service.method(
        SensorValue.IFACE_NAME, in_signature='v', out_signature='')
    def setValue(self, value):
        print("Setting Power Supply Derating is not allowed")


class TurboAllowedSensor(VirtualSensor):
    def __init__(self, bus, name):
        VirtualSensor.__init__(self, bus, name)
        self.setValue(0)

    # override setValue method
    @dbus.service.method(
        SensorValue.IFACE_NAME, in_signature='b', out_signature='')
    def setValue(self, value):
        super(TurboAllowedSensor, self).setValue(value)
