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)

[((43, 31, 43, 47), 'utime.ticks_ms', 'utime.ticks_ms', ({}, {}), '()', False, 'import utime\n'), ((52, 28, 52, 64), 'pycom.nvs_get', 'pycom.nvs_get', ({(52, 42, 52, 63): 'Sleep.ACTIVE_TIME_KEY'}, {}), '(Sleep.ACTIVE_TIME_KEY)', False, 'import pycom\n'), ((53, 30, 53, 68), 'pycom.nvs_get', 'pycom.nvs_get', ({(53, 44, 53, 67): 'Sleep.INACTIVE_TIME_KEY'}, {}), '(Sleep.INACTIVE_TIME_KEY)', False, 'import pycom\n'), ((75, 8, 75, 47), 'pycom.nvs_set', 'pycom.nvs_set', ({(75, 22, 75, 43): 'Sleep.ACTIVE_TIME_KEY', (75, 45, 75, 46): '(0)'}, {}), '(Sleep.ACTIVE_TIME_KEY, 0)', False, 'import pycom\n'), ((76, 8, 76, 49), 'pycom.nvs_set', 'pycom.nvs_set', ({(76, 22, 76, 45): 'Sleep.INACTIVE_TIME_KEY', (76, 47, 76, 48): '(0)'}, {}), '(Sleep.INACTIVE_TIME_KEY, 0)', False, 'import pycom\n'), ((82, 8, 82, 57), 'pycom.nvs_set', 'pycom.nvs_set', ({(82, 22, 82, 42): 'Sleep.SLEEP_TIME_KEY', (82, 44, 82, 56): 'milliseconds'}, {}), '(Sleep.SLEEP_TIME_KEY, milliseconds)', False, 'import pycom\n'), ((91, 8, 91, 36), 'utime.sleep_ms', 'utime.sleep_ms', ({(91, 23, 91, 35): 'milliseconds'}, {}), '(milliseconds)', False, 'import utime\n'), ((11, 15, 11, 36), 'machine.wake_reason', 'machine.wake_reason', ({}, {}), '()', False, 'import machine\n'), ((14, 15, 14, 36), 'machine.wake_reason', 'machine.wake_reason', ({}, {}), '()', False, 'import machine\n'), ((58, 12, 58, 30), 'pycom.nvs_get', 'pycom.nvs_get', ({(58, 26, 58, 29): 'key'}, {}), '(key)', False, 'import pycom\n'), ((59, 12, 59, 37), 'pycom.nvs_set', 'pycom.nvs_set', ({(59, 26, 59, 29): 'key', (59, 31, 59, 36): 'value'}, {}), '(key, value)', False, 'import pycom\n'), ((70, 12, 70, 103), 'machine.pin_sleep_wakeup', 'machine.pin_sleep_wakeup', (), '', False, 'import machine\n'), ((86, 12, 86, 43), 'machine.deepsleep', 'machine.deepsleep', ({(86, 30, 86, 42): 'milliseconds'}, {}), '(milliseconds)', False, 'import machine\n'), ((33, 52, 33, 68), 'utime.ticks_ms', 'utime.ticks_ms', ({}, {}), '()', False, 'import utime\n'), ((49, 24, 49, 59), 'pycom.nvs_get', 'pycom.nvs_get', ({(49, 38, 49, 58): 'Sleep.SLEEP_TIME_KEY'}, {}), '(Sleep.SLEEP_TIME_KEY)', False, 'import pycom\n'), ((49, 62, 49, 92), 'machine.remaining_sleep_time', 'machine.remaining_sleep_time', ({}, {}), '()', False, 'import machine\n'), ((50, 51, 50, 89), 'pycom.nvs_get', 'pycom.nvs_get', ({(50, 65, 50, 88): 'Sleep.INACTIVE_TIME_KEY'}, {}), '(Sleep.INACTIVE_TIME_KEY)', False, 'import pycom\n'), ((83, 80, 83, 96), 'utime.ticks_ms', 'utime.ticks_ms', ({}, {}), '()', False, 'import utime\n')]