import ugfx, network, badge, time
import random
from . import ch_ssid

# By default, this gets updated by the "main" part at bottom of scripta
target_ssid = "SHA2017-insecure"

rssis = []

best = -127
worst = 127
total = 0
total_samples = 0

# Some layout dimensions
LINE_Y=127-12
LINE_X=24

def init_display():
    ugfx.init()
    ugfx.clear(ugfx.BLACK)  # cycle all pixels to try and cut ghosting
    ugfx.flush()
    ugfx.clear(ugfx.WHITE)
    ugfx.flush()
    ugfx.line(0,LINE_Y,298,LINE_Y,ugfx.BLACK)
    ugfx.line(LINE_X, 0, LINE_X, LINE_Y, ugfx.BLACK)
    ugfx.string(0, LINE_Y, "SSID: %s" % target_ssid, "", ugfx.BLACK)
    for y in range(10, LINE_Y, 10):
        if y % 20 == 0:
            from_x = LINE_X-4
            to_x = LINE_X
            ugfx.string(0, y - 6, "-%d" % y, "", ugfx.BLACK)
        else:
            from_x = LINE_X - 3
            to_x = LINE_X - 1
        ugfx.line(from_x, y, LINE_X, y, 127)
    ugfx.flush()

def rssi_sample(sta_if):
    scanResults = sta_if.scan()
    print("@ %d, %d access points" % (time.time(), len(scanResults)))
    for result in [ s for s in scanResults if s[0].decode() == target_ssid ]:
        rssi = result[3]
        print("Measured RSSI %s" % rssi)
        show_sample(rssi)
        break

random_value = -60

def test_random_sample():
    # version of rssi_sample that doesn't require waiting for a WiFi scan
    global random_value
    random_value = random_value + random.randint(-5, 5)
    random_value = min(random_value, 0)
    random_value = max(-192, random_value)
    rssi = random_value
    if rssi < -127:
        rssi = None
    show_sample(rssi)

def show_sample(rssi):
    global total_samples, total, best, worst, avg

    show_rssi_on_leds(rssi)

    rssis.append(rssi)

    if rssi is not None:
        # write the status line
        total_samples += 1
        total += rssi
        best = max(best, rssi)
        worst = min(worst, rssi)
        avg = total // total_samples
        status_line = "Best: %d, Worst: %d, Mean: %d" % (best, worst, avg)

        ugfx.area(129, LINE_Y + 1, 256, 128, ugfx.WHITE)
        ugfx.string(130, LINE_Y, status_line, "", ugfx.BLACK)

    # every 100 samples, perform a full refresh of the graph area to avoid ghosting
    if total_samples > 0 and total_samples % 100 == 0:
        ugfx.area(LINE_X+1, 0, 298, LINE_Y, ugfx.BLACK)
        ugfx.flush()
        ugfx.area(LINE_X+1, 0, 298, LINE_Y, ugfx.WHITE)
        ugfx.flush()

    # draw the graph
    draw_rssi_graph(rssis, ugfx.BLACK)

    # put the raw RSSI reading in the top right
    ugfx.area(240, 2, 298, 24, ugfx.BLACK)
    if rssi is None:
        msg = "???"
    else:
        msg = "%d" % rssi
    ugfx.string(242, 2, msg, "Roboto_Black22", ugfx.WHITE)
    ugfx.flush()

    # clear the old parts of the graph, in preparation for the next time we flush to draw it
    draw_rssi_graph(rssis, ugfx.WHITE)

def draw_rssi_graph(rssis, colour):
    while len(rssis) > 298 - LINE_X - 1:
        rssis.pop(0)
    for i in range(len(rssis)):
        rssi = rssis[i]
        if rssi is not None:  # leave a blank gap in the graph if the rssi is "none"
            pos_y = 0 - rssis[i] # assume negative for now?
            pos_y = min(pos_y, LINE_Y)  # don't overwrite the bottom part of the graph
            ugfx.pixel(i + LINE_X + 1, pos_y, colour)
            # make the graph thicker vertically so it's easier to see
            if pos_y < LINE_Y - 1:
                ugfx.pixel(i + LINE_X + 1, pos_y + 1, colour)
            if pos_y > 0:
                ugfx.pixel(i + LINE_X + 1, pos_y - 1, colour)

class LED(object):
    def __init__(self, r,g,b):
        self.r =r
        self.g = g
        self.b = b

    def to_list(self):
        return [self.g, self.r, self.b, 0]

def map(value, from_low, from_high, to_low, to_high):
      result = (value - from_low) * (to_high - to_low) // (from_high - from_low) + to_low;
      return max(to_low, min(result, to_high))

def show_rssi_on_leds(rssi):
    off = LED(0,0,0)
    if rssi is None:  # turn all LEDs off if there's no SSID
        color = off
        rssi = -127
    elif rssi < -90:   # dim red
        color = LED(10, 0 , 0)
    elif rssi < -80:  # bright red
        color = LED(80, 0, 0)
    elif rssi < -70:  # orange
        color = LED(10, 8, 0)
    elif rssi < -50:  # dim green
        color = LED(0, 10, 0)
    else:  # bright green
        color = LED(0, 40, 0)
    led_values = []
    # LEDs go right to left, but we want left to right
    num_leds = map(rssi, -80, -50, 1, 6)
    for i in range(num_leds, 6):
        led_values += off.to_list()
    for i in range(num_leds):
        led_values += color.to_list()
    print(led_values)
    badge.leds_send_data(bytes(led_values))

def run_monitor(ssid, sta_if):
    global target_ssid
    target_ssid = ssid
    print("Monitoring %s..." % ssid)

    # this doesn't work, because right now run_monitor never exits
    ugfx.input_attach(ugfx.BTN_START, exit_app)

    sta_if = network.WLAN(network.STA_IF)
    sta_if.active(True)

    badge.leds_init()
    init_display()

    while True:
        #test_random_sample()
        rssi_sample(sta_if)

def exit_app(pushed):
    if pushed:
        ugfx.clear(ugfx.WHITE)
        ugfx.string(100,50,'Restarting!','Roboto_Regular18',ugfx.BLACK)
        ugfx.flush()
        badge.eink_busy_wait()
        deepsleep.start_sleeping(1)

print("Starting...")
ch_ssid.chooseSSID("Select SSID to track", run_monitor)


