import machine
import pycom
import utime

from exceptions import Exceptions

class Sleep:

    @property
    def wakeReason(self):
        return machine.wake_reason()[0]
    @property
    def wakePins(self):
        return machine.wake_reason()[1]
    @property
    def powerOnWake(self):
        return self.wakeReason == machine.PWRON_WAKE
    @property
    def pinWake(self):
        return self.wakeReason == machine.PIN_WAKE
    @property
    def RTCWake(self):
        return self.wakeReason == machine.RTC_WAKE
    @property
    def ULPWake(self):
        return self.wakeReason == machine.ULP_WAKE
    @property
    def isSleepWake(self):
        return self.pinWake or self.RTCWake or self.ULPWake

    @property
    def activeTime(self):
        return self.__activeTime + utime.ticks_diff(utime.ticks_ms(), self.__activityStart)
    @property
    def inactiveTime(self):
        return self.__inactiveTime

    ACTIVE_TIME_KEY = 'activeTime'
    INACTIVE_TIME_KEY = 'inactiveTime'
    SLEEP_TIME_KEY = 'sleepTime'

    def __init__(self):
        self.__activityStart = utime.ticks_ms()

        self.__initPersistentVariable(Sleep.ACTIVE_TIME_KEY)
        self.__initPersistentVariable(Sleep.INACTIVE_TIME_KEY)

        if not self.powerOnWake:
            sleptTime = pycom.nvs_get(Sleep.SLEEP_TIME_KEY) - machine.remaining_sleep_time()
            pycom.nvs_set(Sleep.INACTIVE_TIME_KEY, pycom.nvs_get(Sleep.INACTIVE_TIME_KEY) + sleptTime)

        self.__activeTime = pycom.nvs_get(Sleep.ACTIVE_TIME_KEY)
        self.__inactiveTime = pycom.nvs_get(Sleep.INACTIVE_TIME_KEY)
        self.__wakeUpPins = []


    def __initPersistentVariable(self, key, value=0):
        if (pycom.nvs_get(key) == None):
            pycom.nvs_set(key, value)


    def addWakeUpPin(self, pin):
        # P2, P3, P4, P6, P8 to P10 and P13 to P23
        if isinstance(pin, list):
            self.__wakeUpPins.extend(pin)
        else:
            self.__wakeUpPins.append(pin)

        try:
            machine.pin_sleep_wakeup(self.__wakeUpPins, mode=machine.WAKEUP_ANY_HIGH, enable_pull=True)
        except Exception as e:
            Exceptions.error(Exception('Sleep not available: ' + str(e)))

    def resetTimers(self):
        pycom.nvs_set(Sleep.ACTIVE_TIME_KEY, 0)
        pycom.nvs_set(Sleep.INACTIVE_TIME_KEY, 0)

    def sleep(self, milliseconds=0):
        if milliseconds == 0:
            milliseconds = 604800000 # 1 week

        pycom.nvs_set(Sleep.SLEEP_TIME_KEY, milliseconds)
        pycom.nvs_set(Sleep.ACTIVE_TIME_KEY, self.activeTime + utime.ticks_diff(utime.ticks_ms(), self.__activityStart))

        try:
            machine.deepsleep(milliseconds)
        except Exception as e:
            Exceptions.error(Exception('Deepsleep not available: ' + str(e)))

    def delay(self, milliseconds):
        utime.sleep_ms(milliseconds)

[((1124, 1140), 'utime.ticks_ms', 'utime.ticks_ms', ([], {}), '()\n', (1138, 1140), False, 'import utime\n'), ((1534, 1570), 'pycom.nvs_get', 'pycom.nvs_get', (['Sleep.ACTIVE_TIME_KEY'], {}), '(Sleep.ACTIVE_TIME_KEY)\n', (1547, 1570), False, 'import pycom\n'), ((1602, 1640), 'pycom.nvs_get', 'pycom.nvs_get', (['Sleep.INACTIVE_TIME_KEY'], {}), '(Sleep.INACTIVE_TIME_KEY)\n', (1615, 1640), False, 'import pycom\n'), ((2306, 2345), 'pycom.nvs_set', 'pycom.nvs_set', (['Sleep.ACTIVE_TIME_KEY', '(0)'], {}), '(Sleep.ACTIVE_TIME_KEY, 0)\n', (2319, 2345), False, 'import pycom\n'), ((2355, 2396), 'pycom.nvs_set', 'pycom.nvs_set', (['Sleep.INACTIVE_TIME_KEY', '(0)'], {}), '(Sleep.INACTIVE_TIME_KEY, 0)\n', (2368, 2396), False, 'import pycom\n'), ((2526, 2575), 'pycom.nvs_set', 'pycom.nvs_set', (['Sleep.SLEEP_TIME_KEY', 'milliseconds'], {}), '(Sleep.SLEEP_TIME_KEY, milliseconds)\n', (2539, 2575), False, 'import pycom\n'), ((2917, 2945), 'utime.sleep_ms', 'utime.sleep_ms', (['milliseconds'], {}), '(milliseconds)\n', (2931, 2945), False, 'import utime\n'), ((156, 177), 'machine.wake_reason', 'machine.wake_reason', ([], {}), '()\n', (175, 177), False, 'import machine\n'), ((237, 258), 'machine.wake_reason', 'machine.wake_reason', ([], {}), '()\n', (256, 258), False, 'import machine\n'), ((1745, 1763), 'pycom.nvs_get', 'pycom.nvs_get', (['key'], {}), '(key)\n', (1758, 1763), False, 'import pycom\n'), ((1787, 1812), 'pycom.nvs_set', 'pycom.nvs_set', (['key', 'value'], {}), '(key, value)\n', (1800, 1812), False, 'import pycom\n'), ((2068, 2163), 'machine.pin_sleep_wakeup', 'machine.pin_sleep_wakeup', (['self.__wakeUpPins'], {'mode': 'machine.WAKEUP_ANY_HIGH', 'enable_pull': '(True)'}), '(self.__wakeUpPins, mode=machine.WAKEUP_ANY_HIGH,\n    enable_pull=True)\n', (2092, 2163), False, 'import machine\n'), ((2727, 2758), 'machine.deepsleep', 'machine.deepsleep', (['milliseconds'], {}), '(milliseconds)\n', (2744, 2758), False, 'import machine\n'), ((833, 849), 'utime.ticks_ms', 'utime.ticks_ms', ([], {}), '()\n', (847, 849), False, 'import utime\n'), ((1330, 1365), 'pycom.nvs_get', 'pycom.nvs_get', (['Sleep.SLEEP_TIME_KEY'], {}), '(Sleep.SLEEP_TIME_KEY)\n', (1343, 1365), False, 'import pycom\n'), ((1368, 1398), 'machine.remaining_sleep_time', 'machine.remaining_sleep_time', ([], {}), '()\n', (1396, 1398), False, 'import machine\n'), ((1451, 1489), 'pycom.nvs_get', 'pycom.nvs_get', (['Sleep.INACTIVE_TIME_KEY'], {}), '(Sleep.INACTIVE_TIME_KEY)\n', (1464, 1489), False, 'import pycom\n'), ((2657, 2673), 'utime.ticks_ms', 'utime.ticks_ms', ([], {}), '()\n', (2671, 2673), False, 'import utime\n')]