import NFC_PN532 as nfc
import neopixel
import time
import sys
import select
from machine import Pin, SPI

#neopixel
ws_pin = 0
led_num = 8
BRIGHTNESS = 0.2  # Adjust the brightness (0.0 - 1.0)

led_strip = neopixel.NeoPixel(Pin(ws_pin), led_num)

def set_neopixel_brightness(color):
    r, g, b = color
    r = int(r * BRIGHTNESS)
    g = int(g * BRIGHTNESS)
    b = int(b * BRIGHTNESS)
    return (r, g, b)

def set_neopixel_color(r,g,b):
    color = (r,g,b)
    color = set_neopixel_brightness(color)
    led_strip.fill(color)
    led_strip.write()

set_neopixel_color(0,0,0)

# SPI
spi_dev = SPI(0, baudrate=1000000)
cs = Pin(17, Pin.OUT)
cs.on()

# SENSOR INIT
pn532 = nfc.PN532(spi_dev,cs)
ic, ver, rev, support = pn532.get_firmware_version()
#print('Found PN532 with firmware version: {0}.{1}'.format(ver, rev))

# Configure PN532 to communicate with MiFare cards
pn532.SAM_configuration()

# FUNCTION TO READ NFC
def read_nfc(dev, tmot):
    """Accepts a device and a timeout in millisecs """
    print('Reading...')
    uid = dev.read_passive_target(timeout=tmot)
    if uid is None:
        print('CARD NOT FOUND')
    else:
        numbers = [i for i in uid]
        string_ID = '{}-{}-{}-{}'.format(*numbers)
        print('Found card with UID:', [hex(i) for i in uid])
        print('Number_id: {}'.format(string_ID))

def loop_neopixel():
    # Display red
    color = (255, 0, 0)  # Red color
    color = set_neopixel_brightness(color)
    led_strip.fill(color)
    led_strip.write()
    time.sleep(1)

    # Display green
    color = (0, 255, 0)  # Green color
    color = set_neopixel_brightness(color)
    led_strip.fill(color)
    led_strip.write()
    time.sleep(1)

    # Display blue
    color = (0, 0, 255)  # Blue color
    color = set_neopixel_brightness(color)
    led_strip.fill(color)
    led_strip.write()
    time.sleep(1)

def read_nfc_loop():
    sys.stdout.write('Waiting for RFID/NFC card to read!\r')
    set_neopixel_color(255,0,0)
    while True:
        # Check if a card is available to read
        uid = pn532.read_passive_target(timeout=0.5)
        # Try again if no card is available.
        if uid is not None:
            break

    set_neopixel_color(255,255,0)

    ntag_string = 'Data: '
    sys.stdout.write('Reading ntag                      \r')

    leds_on = 0
    for page in range(20,40):
        try:
            ntag2xx_page = pn532.ntag2xx_read_block(page)
            if (page % 2) == 0:
                if page == 0:
                    pass
                elif page == 2:
                    pass
                else:
                    led_strip[leds_on] = (0,0,255)
                    leds_on += 1
                    if leds_on > 7:
                        leds_on = 7
                    led_strip.write()

            if ntag2xx_page is not None:
                for char in ntag2xx_page:
                    ntag_string += chr(char)
            else:
                sys.stdout.write('Error reading card\r')
                return 1
        except:
            sys.stdout.write('Error reading card\r')
            return 1

    set_neopixel_color(0,255,0)
    sys.stdout.write(ntag_string + '\r')
    time.sleep(3)

    return 0
            #print('PAGE ',page,': ',[chr(x) for x in ntag2xx_page])

def write_nfc_loop(data):
    content = data.encode('utf-8')
    length = len(content)
    pages = int(length / 4)
    if (length % 4) != 0:
        pages += 1

    sys.stdout.write("Waiting for RFID/NFC card to write to!\r")
    set_neopixel_color(255,0,0)
    while True:
        # Check if a card is available to read
        uid = pn532.read_passive_target(timeout=0.5)
        # Try again if no card is available.
        if uid is not None:
            break

    set_neopixel_color(255,255,0)

    sys.stdout.write('Erasing card\r')
    for page in range(20,41):
        content_erase = b'\x00\x00\x00\x00'
        pn532.ntag2xx_write_block(page, content_erase)

    sys.stdout.write('Writing card\r')
    for page in range(20,20 + pages):
        content_slice = bytearray(4)
        for i in range(0,4):
            try:
                content_slice[i] = (content[i + 4 * (page - 20)])
            except:
                content_slice[i] = 0
            #content_slice.append(content[i + 4 * (page - 20)])
        print(content_slice)
        pn532.ntag2xx_write_block(page, content_slice)

    sys.stdout.write('Write done\r')
    set_neopixel_color(0,255,0)

def loop():
    poll_results = poll_obj.poll(1)
    if poll_results:
        rw = sys.stdin.readline().strip()
        sys.stdout.write("received data: " + rw + "\r")
        rw = rw.lower()
        if rw == 'w':
            while True:
                sys.stdout.write('ID: \r')
                poll_results = poll_obj.poll(1)
                data = sys.stdin.readline().strip()
                write_nfc_loop(data)
        elif rw == 'r':
            while True:
                ret = read_nfc_loop()
                if ret == 255:
                    set_neopixel_color(0,0,255)
                    rw = None
                    return 1
        elif rw == '':
            while True:
                ret = read_nfc_loop()
                if ret == 255:
                    set_neopixel_color(0,0,255)
                    rw = None
                    return 1
        else:
            sys.stdout.write('Invalid option\r')

poll_obj = select.poll()
poll_obj.register(sys.stdin, select.POLLIN)

set_neopixel_color(0,0,255)


while True:
    poll_results = poll_obj.poll(1)
    if poll_results:
        while True:
            try:
                ret = loop()
                if ret == 1:
                    poll_results = None
                    break
            except:
               set_neopixel_color(0,0,255)
               break
    else:
        continue
#except:
#    set_neopixel_color(0,0,0)