#!/usr/bin/env python

from __future__ import print_function
from time import sleep

from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver
from smartcard.CardMonitoring import CardMonitor, CardObserver
from smartcard.util import toHexString
from evdev import UInput, ecodes
import uinput
import shutil
import random

codes_length=8

key_mappings = {
  uinput.KEY_0 : 0,
  uinput.KEY_1 : 1,
  uinput.KEY_2 : 2,
  uinput.KEY_3 : 3,
  uinput.KEY_4 : 4,
  uinput.KEY_5 : 5,
  uinput.KEY_6 : 6,
  uinput.KEY_7 : 7,
  uinput.KEY_8 : 8,
  uinput.KEY_9 : 9,
  uinput.KEY_A : 'A',
  uinput.KEY_B : 'B',
  uinput.KEY_C : 'C',
  uinput.KEY_D : 'D',
  uinput.KEY_E : 'E',
  uinput.KEY_F : 'F',
  uinput.KEY_G : 'G',
  uinput.KEY_H : 'H',
  uinput.KEY_I : 'I',
  uinput.KEY_J : 'J',
  uinput.KEY_K : 'K',
  uinput.KEY_L : 'L',
  uinput.KEY_M : 'M',
  uinput.KEY_N : 'N',
  uinput.KEY_O : 'O',
  uinput.KEY_P : 'P',
  uinput.KEY_Q : 'Q',
  uinput.KEY_R : 'R',
  uinput.KEY_S : 'S',
  uinput.KEY_T : 'T',
  uinput.KEY_U : 'U',
  uinput.KEY_V : 'V',
  uinput.KEY_W : 'W',
  uinput.KEY_X : 'X',
  uinput.KEY_Y : 'Y',
  uinput.KEY_Z : 'Z'
}

device = uinput.Device([uinput.KEY_0, uinput.KEY_1, uinput.KEY_2, uinput.KEY_3, uinput.KEY_4, uinput.KEY_5, uinput.KEY_6, uinput.KEY_7, uinput.KEY_8, uinput.KEY_9, uinput.KEY_A, uinput.KEY_B, uinput.KEY_C, uinput.KEY_D, uinput.KEY_E, uinput.KEY_F, uinput.KEY_G, uinput.KEY_H, uinput.KEY_I, uinput.KEY_J, uinput.KEY_K, uinput.KEY_L, uinput.KEY_M, uinput.KEY_N, uinput.KEY_O, uinput.KEY_P, uinput.KEY_Q, uinput.KEY_R, uinput.KEY_S, uinput.KEY_T, uinput.KEY_U, uinput.KEY_V, uinput.KEY_W, uinput.KEY_X, uinput.KEY_Y, uinput.KEY_Z, uinput.KEY_TAB])

def card_id_to_keyboards(card_id):
    id = card_id.replace(' ', '')

    return [getattr(uinput, 'KEY_'+x.upper()) for x in id]

class selectDFTELECOMObserver(CardObserver):
    def __init__(self):
        self.observer = ConsoleCardConnectionObserver()

    def update(self, observable, actions):
        try:
            (addedcards, removedcards) = actions
            for card in addedcards:
                #print("+Inserted: ", toHexString(card.atr))
                card.connection = card.createConnection()
                card.connection.connect()
                card.connection.addObserver(self.observer)
                apdu = [0xFF, 0xCA, 0x00, 0x00, 0x00]
                response, sw1, sw2 = card.connection.transmit(apdu)
                keys = card_id_to_keyboards(toHexString(response))
                print(keys)

                if len(keys) == codes_length:
                    read_keys = ""

                    for key in keys:
                        key_map = key_mappings[key]
                        read_keys = read_keys + str(key_map)

                    print("decoded keys - #" + read_keys + "#")

                    if len(read_keys) == codes_length:
                        rand = random.randint(1,1000)*5
                        write_file = "/opt/pos/common/tmp/_nfc_keys_"+str(rand)+".txt"
                        f = open(write_file, 'w')
                        f.write("nfc#" + read_keys + "\n")
                        f.close()
                        shutil.move(write_file, "/opt/pos/common/tmp/barcode.txt")
        except:
            pass

if __name__ == '__main__':
    cardmonitor = CardMonitor()
    selectobserver = selectDFTELECOMObserver()
    cardmonitor.addObserver(selectobserver)

    # loop forever
    while 1 > 0:
      sleep(2)
      pass

    # don't forget to remove observer, or the
    # monitor will poll forever...
    cardmonitor.deleteObserver(selectobserver)

    import sys
    if 'win32' == sys.platform:
        print('press Enter to continue')
        sys.stdin.read(1)


