import ugfx, badge, utime, random
import hashlib, binascii
try:
    from umqtt.simple import MQTTClient
    import wifi, machine
except Exception as e:
    print("[JuNePager] Emulator I suppose? ;)")
# import gc

''' JuNe Pager

Use case: I want to be able to 'ping' someone in my friends list and have a message pop up on their badge.

Messages are sent through MQTT with the persistent flag.
The pager starts a service when enabled that polls every X minutes for new messages.

This app should have:
- show ID
- add id to favorite recipients
- send message (select recipient, select message)
  - favorite recipient list + custom entry at top
- enable/disable service

'''

class Pager:
    def load(self):
        try:
            badge.nvs_get_u8('junepager', 'service', 1)
        except Exception as e:
            print("[JuNePager] Emulator sux0rs.")
            self.isEmulator = 1
            self.serviceID = "1234"
            self.serviceEnabled = 1
            self.serviceTime = 300
            self.serviceFont = 'Roboto_Regular12'
            return
        self.isEmulator = 0
        self.serviceEnabled = badge.nvs_get_u8('junepager', 'service', 1)
        self.serviceTime = badge.nvs_get_u16('junepager', 'time', 300)
        self.serviceFont = badge.nvs_get_str('junepager', 'font', 'Roboto_Regular12')
        self.serviceID = binascii.hexlify(hashlib.sha256(machine.unique_id()).digest())[0:4].decode()

    def save(self):
        if self.isEmulator:
            print("[JuNePager] Emulator sux0rs.")
            return
        badge.nvs_set_u8('junepager', 'service', self.serviceEnabled)
        badge.nvs_set_u16('junepager', 'time', self.serviceTime)
        badge.nvs_set_str('junepager', 'font', self.serviceFont)

    def send_message(self):
        print("[JuNePager] Send message.")
        ugfx.clear(ugfx.BLACK)
        ugfx.string_box(0,0,300,20,"Send Message","Roboto_Regular12",ugfx.WHITE,ugfx.justifyCenter)
        ugfx.string_box(0,20,280,20,"Bla bla","Roboto_Regular12",ugfx.WHITE,ugfx.justifyCenter)
        ugfx.string_box(0,30,280,45,"Je moeder","Roboto_Regular12",ugfx.WHITE,ugfx.justifyCenter)
        ugfx.string_box(0,65,280,50,"START sends, SELECT aborts.","Roboto_Regular12",ugfx.WHITE,ugfx.justifyCenter)
        ugfx.flush()
    
    def __init__(self):
        print("[JuNePager] JuNe Rules!")
        ugfx.init()
        badge.init()
        ugfx.input_init()
        try:
            wifi.init()
        except Exception as e:
           print("[JuNePager] Still emulator.... (no wifi)")
        self.button_pressed = None
    
    def draw_menu(self):
        ugfx.clear(ugfx.WHITE)
        ugfx.string_box(0,0,280,20,"JuNe Pager","Roboto_Regular12",ugfx.BLACK,ugfx.justifyCenter)
        ugfx.string_box(0,0,280,20, self.serviceID ,"Roboto_Regular12",ugfx.BLACK,ugfx.justifyRight)
        ugfx.string_box(0,20,280,20,"A: Message","Roboto_Regular12",ugfx.BLACK,ugfx.justifyLeft)
        ugfx.string_box(0,40,280,20,"B: Bookmark someone","Roboto_Regular12",ugfx.BLACK,ugfx.justifyLeft)
        ugfx.string_box(0,60,280,20,"UP: Enable/Disable pager (" + ("enabled" if self.serviceEnabled else "disabled") + ")","Roboto_Regular12",ugfx.BLACK,ugfx.justifyLeft)
        serviceMessage = badge.nvs_get_str('junepager', 'lastmessage', None)
        if serviceMessage is not None and len(serviceMessage) > 0:
            ugfx.string_box(0,80,280,20,"LEFT: Clear pager message","Roboto_Regular12",ugfx.BLACK,ugfx.justifyLeft)
        ugfx.flush()

    def button(self, pressed, b):
        if pressed:
            print("[JuNePager] Button pressed: " + str(b))
            self.button_pressed = b

    def program_main_menu(self):
        print("[JuNePager] Pager menu.")
        self.button_pressed = None

        ugfx.input_attach(ugfx.BTN_SELECT, lambda pressed: self.button(pressed, "SELECT"))
        ugfx.input_attach(ugfx.BTN_START, lambda pressed: self.button(pressed, "START"))
        ugfx.input_attach(ugfx.BTN_B, lambda pressed: self.button(pressed, "B"))
        ugfx.input_attach(ugfx.BTN_A, lambda pressed: self.button(pressed, "A"))
        ugfx.input_attach(ugfx.JOY_UP, lambda pressed: self.button(pressed, "UP"))
        ugfx.input_attach(ugfx.JOY_DOWN, lambda pressed: self.button(pressed, "DOWN"))
        ugfx.input_attach(ugfx.JOY_LEFT, lambda pressed: self.button(pressed, "LEFT"))
        ugfx.input_attach(ugfx.JOY_RIGHT, lambda pressed: self.button(pressed, "RIGHT"))

        self.draw_menu()
        while True:
            if self.button_pressed == None:
                utime.sleep_ms(10)
                pass
            elif self.button_pressed == "SELECT":
                print("[JuNePager] Quit request. Bye")
                if self.wifi:
                    self.mqtt.disconnect()
                import appglue
                appglue.home()
                return
            elif self.button_pressed == "LEFT":
                print("[JuNePager] Clear message.")
                badge.nvs_set_str('junepager', 'lastmessage', '')
                self.button_pressed = None
                self.draw_menu()
            elif self.button_pressed == "UP":
                self.serviceEnabled = (0 if self.serviceEnabled else 1)
                print("[JuNePager] Service is now {}".format("enabled" if self.serviceEnabled else "disabled"))
                self.save()
                self.button_pressed = None
                self.draw_menu()
            elif self.button_pressed == "DOWN":
                self.button_pressed = None
                self.draw_menu()
            elif self.button_pressed == "START":
                self.button_pressed = None
                # self.instructions()
                self.draw_menu()
            else:
                print("[JuNePager] Unhandled key.")
                self.button_pressed = None

    def sendMessage(self, receiver, msg):
        if not self.wifi and not wifi.sta_if.isconnected():
            print("[JuNePager] No wifi - can't send to topic {} msg {}".format(topic, msg))
            return
        self.wifi = 1
        topic = "june/rules/pager/" + str(receiver) + "/" + str(self.serviceID)
        print("[JuNePager] Sending to topic {} msg {}".format(topic, msg))
        if msg is None:
            msg = ''
        self.mqtt.publish(topic, msg, retain=True, qos=1)

    def init(self):
        self.wifi = 0
        self.load()
        ugfx.clear(ugfx.WHITE)
        ugfx.string_box(0,0,280,20,"JuNe Pager","Roboto_Regular12",ugfx.BLACK,ugfx.justifyCenter)
        ugfx.string_box(0,0,280,20, self.serviceID ,"Roboto_Regular12",ugfx.BLACK,ugfx.justifyRight)
        ugfx.string_box(0,30,280,20,"Connecting...","Roboto_Regular12",ugfx.BLACK,ugfx.justifyCenter)
        ugfx.flush()

        # Wait for WiFi connection
        print("[JuNePager] Get wifi up.")
        try:
            wifi.sta_if.isconnected()
        except Exception as e:
            print("[JuNePager] Wifi needs init first..")
            wifi.init()
        try:
            count = 0
            while not wifi.sta_if.isconnected():
                count = count + 1
                utime.sleep_ms(50)
                if (count % 20) == 0:
                    print("[JuNePager] Still trying to get wifi up.")
                if count > 100:
                    print("[JuNePager] Fuck this. Fix your wifi.")
                    self.wifi = 0
                    return
            print("[JuNePager] Wifi up.")
        except Exception as e:
            print("[JuNePager] Wifi error: " + str(e))
            self.wifi = 0

        print("[JuNePager] Create MQTT object.")
        self.mqtt = MQTTClient("JuNePager" + self.serviceID, "mqtt.sha2017.org")
        print("[JuNePager] MQTT connect.")
        try:
            self.mqtt.connect(clean_session=True)
        except Exception as e:
             print("[JuNePager] Error connecting MQTT -- expect that stuff to be broken. Le sigh. Error: {}".format(str(e)))

    def run(self):
        self.init()
        self.program_main_menu()

# Start pager app
Pager().run()
