import os
import sys
import board
import time
import busio
import digitalio
import terminalio
import storage

# import display libraries
import displayio
import vectorio # for shapes
import adafruit_ili9341 # TFT (thin film transistor) display
from adafruit_display_text.bitmap_label import Label
from adafruit_display_text import label
from adafruit_display_shapes.rect import Rect
from adafruit_display_shapes.circle import Circle
#from adafruit_display_shapes.triangle import Triangle
from adafruit_display_shapes.line import Line
from adafruit_stmpe610 import Adafruit_STMPE610_SPI # touch screen reader

# set constants
SCREENSIZE_X = const(320)
SCREENSIZE_Y = const(240)
ON = const(0)  #indicator LED is active low.
OFF = const(1) #indicator LED is active low.

def main():
    #initialize pushbutton to toggle record/ pause states
    pushbutton = initialize_pushbutton()
    number_of_record_pause_states = 2
    #start in record_pause 0 == Recording
    record_pause_state = 0
    pushbutton_last_press_state = False

    # initialize touch screen and display screen
    spi_bus = initialize_spi()
    display = initialize_display( spi_bus )
    touch_screen = initialize_touch_screen( spi_bus )

    # initialize table display group
    display_group_table = initialize_display_group( display )
    text_group = create_table_screen( display, display_group_table )
    display.show( display_group_table )

    record_pause_press_state = 1 #startup in recording mode
    record_pause_last_press_state = 0
    show_record_pause_icon( display_group_table, record_pause_state, 0, 0)

    number_of_source_LED_states = 2
    source_LED_state = 0
    last_source_LED_state = 0
    source_LED_last_press_state = False
    last_record_pause = 2 #startup
    mode = 0
    last_mode = 0

    while True:
        if source_LED_state == 0:
            pass# print("led_sources_off")
        else:
            pass# print("led_sources_on")
        if record_pause_state == 0:
            print( "record_pause_state = 0, which means it's recording")
        else:
            # record_pause_state == 1, paused, so don't make measurements
            print( "record_pause_state = 1, which means it's paused")
            last_record_pause = 1

        if mode == 0:
            # if mode == 0 table mode
            if last_mode != 0:
                # mode = 0 = table, last mode not 0
                # to set up the table display, initialize display_group
                # display table background graphics
                display.show( display_group_table )
            # mode = 0, last mode = 0
            # display data text groups
            if display:
                pass
            if last_mode != 0:
                show_record_pause_icon( display_group_table, record_pause_state, mode, 1 )
            else:
                show_record_pause_icon( display_group_table, record_pause_state, mode,1)
            last_mode = 0
        if mode == 1:
            # if mode == 1 graph mode
            if last_mode != 1:
                # mode = 1 = graph, last mode not 1
                pass
            if last_mode != 1:
                show_record_pause_icon( display_group_graph, record_pause_state, mode, 1)
            else:
                show_record_pause_icon( display_group_graph, record_pause_state, mode, 1 )
            last_mode = 1

        exit_wait = 0
        remaining_wait_time = 2
        while remaining_wait_time > 0 and exit_wait == 0:
            # record_pause 0 is recording, record_pause 1 is paused
            # check pushbutton, if event, toggle record/ pause
            press = [0,0]
            press = screen_pressed( touch_screen )
            record_pause_press_state = press[0]
            #pushbutton_press_state = pushbutton_pressed( pushbutton )
            #if pushbutton_press_state != pushbutton_last_press_state and pushbutton_press_state == True:
            if record_pause_press_state != record_pause_last_press_state and record_pause_press_state == True:
                record_pause_state = (record_pause_state + 1) % number_of_record_pause_states
                #print ("record_pause_state = {}".format, (record_pause_state))
                #time.sleep(10)
                exit_wait = 1
            record_pause_last_press_state = record_pause_press_state


            if press[1] != source_LED_last_press_state and press[1] == True:
                source_LED_changed = True
                source_LED_state = (source_LED_state + 1) % number_of_source_LED_states
            source_LED_last_press_state = press[1]

            remaining_wait_time = 0
            time.sleep( 0.1 )
        # return to top of infinite loop

# function definitions below

def initialize_pushbutton():
    pushbutton = digitalio.DigitalInOut( board.D12 )
    pushbutton.direction = digitalio.Direction.INPUT
    pushbutton.pull = digitalio.Pull.UP
    return pushbutton

def pushbutton_pressed( pushbutton ):
    pushbutton_press_state = not pushbutton.value   #active low, so True is notpushed and False is pushed
    return pushbutton_press_state                   #pushbutton_press_state is True if button is being pushed

def initialize_spi():
    try:
        # spi has already been initialized by displayio/adafruit_ili9341, but reinitialize it here anyway
        spi_bus = board.SPI()
        # initialized spi bus
        return spi_bus
    except ValueError as err:
        print( "Error: spi bus fail: {:}".format(err) )
        return False

def initialize_touch_screen( spi_bus ):
    touch_screen_chip_select = digitalio.DigitalInOut(board.D6)
    try:
        touch_screen = Adafruit_STMPE610_SPI(spi_bus, touch_screen_chip_select)
        return touch_screen
    except ValueError as err:
        print("Error: touch screen fail {:}".format(err))
        return False

def screen_pressed( touch_screen ):
    record_pause_press_state = 0
    table_graph_press_state = 0
    source_LED_press_state = 0
    while not touch_screen.buffer_empty:
        touch_data = touch_screen.read_data()
        touch_x = touch_data[ 1 ]
        touch_y = touch_data[ 0 ]
        touch_pressure = touch_data[ 2 ]
        print( "X: %d, Y: %d, press: %d" % ( touch_x, touch_y, touch_pressure ) )
        if ( touch_x < 2200 ) and ( touch_y > 1500) and ( touch_y < 3700 ) and ( touch_y > 2400 ): #1750, 2950
            #print ("record_pause_press_state = 1")
            record_pause_press_state = 1
        if ( touch_x < 1000 ) and ( touch_y > 1000 ) and ( touch_y < 3000 ):
            table_graph_press_state = 1
        if ( touch_x > 2700 ) and ( touch_y > 1000 ) and ( touch_y < 3000 ):
            source_LED_press_state = 1
    return (record_pause_press_state, source_LED_press_state)

def initialize_display( spi_bus ):
    if spi_bus == False:
        return False
    try:
        # displayio/dafruit_ili9341 library owns the pins until display release
        displayio.release_displays()
        tft_display_cs = board.D9
        tft_display_dc = board.D10
        display_bus = displayio.FourWire( spi_bus, command=tft_display_dc, chip_select=tft_display_cs )
        display = adafruit_ili9341.ILI9341( display_bus, width=SCREENSIZE_X, height=SCREENSIZE_Y, rotation=180 )
        # initialized display
        return display
    except ValueError as err:
        print("Error: display fail {:}".format(err))
        return False

def initialize_display_group( display ):
    if display == False:
        print("no display")
        return False
    display_group = displayio.Group()
    return display_group

def create_table_screen( display, display_group ):
    RED = 0xFF0022
    full_spectrum_frame( display_group, RED )
    text_group = full_spectrum_text_groups( display_group )
    return text_group

def full_spectrum_frame( table_group, border_color ):
    # begin full spectrum frame
    if table_group == False:
        return
    palette = displayio.Palette(1)
    palette[0] = border_color
    background_rectangle = vectorio.Rectangle(pixel_shader=palette, width=SCREENSIZE_X, height=SCREENSIZE_Y, x=0, y=0)
    table_group.append( background_rectangle )
    palette = displayio.Palette(1)
    palette[0] = 0xFFFFFF
    border_width = 7
    foreground_rectangle = vectorio.Rectangle(pixel_shader=palette, width=SCREENSIZE_X - 2*border_width, height=SCREENSIZE_Y - 2*border_width, x=border_width, y=border_width)
    table_group.append( foreground_rectangle )

    #Draw screen switch button:
    palette = displayio.Palette(1)
    palette[0] = 0xC1C1C1
    screen_button_triangle = vectorio.Polygon( pixel_shader=palette, points = [(250, 60), (250, 160), (310, 110)], x=0, y=0)
    table_group.append(screen_button_triangle)

    #Draw the record_pause_circle:
    record_pause_circle = vectorio.Circle( pixel_shader=palette, radius=45, x=170, y=70 )
    table_group.append( record_pause_circle )

    #Draw source trapezoid
    source_trapezoid = vectorio.Polygon( pixel_shader=palette, points = [(150, 170), (190, 170), (210, 230), (130, 230)], x=0, y=0)
    table_group.append(source_trapezoid)


def full_spectrum_text_groups( table_group ):
    if table_group == False:
        return False
    # Fixed width font
    fontPixelWidth, fontPixelHeight = terminalio.FONT.get_bounding_box()
    text_color = 0x000000 # black text for readability
    text_group = displayio.Group( scale = 2, x = 15, y = 20 ) #scale sets the text scale in pixels per pixel
    table_group.append( text_group )
    #print("TG max_size {:}".format(len(text_group))) # to figure max_size of group
    return text_group

def show_record_pause_icon( display_group, record_pause, mode, create_update ):
    if display_group == False:
        print("No display")
        return
    #print ( len ( display_group ))
    WHITE = 0xFFFFFF
    GREY = 0xC1C1C1
    RED = 0xFF0022
    BLACK = 0x000000
    if mode == 0:
        x_center = 170
        y_center = 70
    else:
        x_center = 170
        y_center = 14
    radius = 8
    x_corner = x_center - radius
    y_corner = y_center - radius
    off_screen_y = 300
    width = 18
    split_width = int( width/3 )
    height = 18
    if create_update == 0:
        blank_icon = Rect( x_corner, y_corner, width, height, fill = GREY)
        recording_icon = Circle( x_center, y_center, radius, fill = RED)
        pause_square_icon = Rect( x_corner, y_corner, width, height, fill = BLACK)
        pause_split_icon = Rect( x_corner + split_width, y_corner, split_width, height, fill = GREY)
        display_group.append( blank_icon )
        display_group.append( recording_icon )
        display_group.append( pause_square_icon )
        display_group.append( pause_split_icon )
    else:
        len_group = ( len ( display_group ))
        if record_pause == 0:
            display_group[ len_group - 4 ].y = y_corner
            display_group[ len_group - 3 ].y = y_corner
            display_group[ len_group - 2 ].y = off_screen_y
            display_group[ len_group - 1 ].y = off_screen_y
        elif record_pause == 1:
            display_group[ len_group - 4 ].y = off_screen_y
            display_group[ len_group - 3 ].y = off_screen_y
            display_group[ len_group - 2 ].y = y_corner
            display_group[ len_group - 1 ].y = y_corner

def remove_record_pause_icon ( display_group ):
    len_group = ( len ( display_group ))
    display_group[ len_group - 2 ].y = 250
    display_group[ len_group - 1 ].y = 250


def led_sources_on(VIS_sensor, NIR_sensor):
    if VIS_sensor != None:
        VIS_sensor.driver_led_current = 12.5 # mA, options 12.5, 25, 50, 100 mA
        VIS_sensor.driver_led = True

    if NIR_sensor != None:
        s = "ATLEDC=48\n"   #0, 16, 32, 48 set the driver to 12.5, 25, 50, 100 mA
        b = bytearray()
        b.extend(s)
        NIR_sensor.write(b)
        #print( "Bytearray sent: %s" % b )
        data = NIR_sensor.readline()
        #print( "Data received: %s" % data)
        s = "ATLED1=100\n" #100 is on, 0 is off
        b = bytearray()
        b.extend(s)
        NIR_sensor.write(b)
        #print( "Bytearray sent: %s" % b )
        data = NIR_sensor.readline()
        #print( "Data received: %s" % data)

def led_sources_off(VIS_sensor, NIR_sensor):
    if VIS_sensor != None:
        VIS_sensor.driver_led = False
    if NIR_sensor != None:
        s = "ATLED1=0\n" #100 is on, 0 is off
        b = bytearray()
        b.extend(s)
        NIR_sensor.write(b)
        #print( "Bytearray sent: %s" % b )
        data = NIR_sensor.readline()
        #print( "Data received: %s" % data)

main()

