# encoding:utf-8
from http.server import HTTPServer,SimpleHTTPRequestHandler
from PySmartCard.CpuCard import PcscReader
import time

def getbits(intger):
      tmp = intger
      b = 0
      while(tmp):
            tmp >>= 1
            b += 1
      return b - 1

class cardReaderHelper:
      cardReader = None
      cardReaderName = ""
      def __init__(self):
            self.cardReader = PcscReader()
      def open(self):
            names = self.cardReader.get_pcsc_readerlist()
            if len(names) > 0:
                  self.cardReaderName = names.split(";")[0]
            if len(self.cardReaderName) > 0:
                  print("Found Card Reader:", self.cardReaderName)
                  return True
            else:
                  print("Can't Found Any Card Reader")
                  return False
      def connect(self):
            return self.cardReader.connect_device(self.cardReaderName)
      
      def disconnect(self):
            self.cardReader.disconnect_device()
      
      def search(self, timeout):
            i = timeout
            ATR = ""
            while(i > 0):
                  i -= 1
                  ATR = self.connect()
                  if len(ATR) > 0:
                        break
                  else:
                        self.disconnect()
                        time.sleep(1)
            return ATR

      def poweron(self):
            if self.cardReader.power_on(1) == 0:
                  return True
            else:
                  self.disconnect()
                  return False

      def __sendAPDU(self, send, readertype=None):
            recv = {"data":"","sw":"","sw1":"","sw2":"","empty":True}
            print("Send",send)
            result = self.cardReader.send_apdu(send, readertype)
            if len(result) > 0:
                  recv["empty"] = False
                  recv["data"] = result[:-4]
                  recv["sw"] = result[-4:]
                  recv["sw1"] = result[-4:-2]
                  recv["sw2"] = result[-2:]
            print("Recv",recv["data"], recv["sw1"], recv["sw2"], recv["sw"], recv["empty"])
            return recv

      def transfer(self, send, readertype=None):
            recv = self.__sendAPDU(send, readertype)
            if not recv["empty"]:
                  if recv["sw1"] == "61":
                        apdu = "00C00000" + recv["sw2"]
                        recv = self.__sendAPDU(apdu, readertype)
                  elif recv["sw1"] == "6C":
                        apdu = send[0:8] + recv["sw2"]
                        recv = self.__sendAPDU(apdu, readertype)
            return recv

      def prase(self, recv):
            cardCode=""
            if not recv["empty"]:
                  if "9000" == recv["sw"]:
                        raw = recv["data"]
                        cur = 0
                        while(cur >= 0):
                              old_cur = cur
                              cur = raw.find("80", old_cur)
                              if cur >= 0:
                                    if "03838D" == raw[cur+4:cur+10] or "0301DD" == raw[cur+4:cur+10]:
                                          r_len = int(raw[cur+2:cur+4], 16)
                                          code = int(raw[cur+10:cur+r_len*2+4], 16)
                                          code &= ~(1<<getbits(code))
                                          code >>= 4
                                          cardCode = str(code)
                                          print("Prase Card Code ", cardCode)
                                          break
                                    else:
                                          print("Prase Card Code Failed")
                              if cur == old_cur:
                                    cur += 1
                  else:
                        print("Receive Error "+ recv["sw"])
            return cardCode

class My_RequestHandler(SimpleHTTPRequestHandler):
      def do_GET(self):
            readResult = {"message":"读卡失败，请再次尝试", "result":""}
            reader = cardReaderHelper()
            if reader.open():
                  if len(reader.search(10)) > 0:
                        if reader.poweron():
                              recv = reader.transfer("FF70076B07A005BE0380010400", 1)
                              reader.disconnect()
                              if not recv["empty"]:
                                    code = reader.prase(recv)
                                    if(len(code) > 0):
                                          readResult["message"] = "读卡成功"
                                          readResult["result"] = code
                                    else:
                                          readResult["message"]="读卡失败: " + recv["sw"]
                              else:
                                    readResult["message"]="读卡失败"
                        else:
                              readResult["message"]="卡上电失败"
                  else:
                        readResult["message"]="没有搜索到卡片"

            result = "{\"code\":\"200\",\"message\":\"" + readResult["message"] + "\",\"result\":\""+ readResult["result"] +"\"}"
            print(result)
            self.send_response(200)
            self.send_header('Content-type','text/plain; charset=utf-8')
            self.send_header('Access-Control-Allow-Origin', self.headers['Origin'])
            self.send_header('Access-Control-Allow-Credentials', 'true')
            self.send_header("Access-Control-Allow-Headers", "authorization")
            self.end_headers()
            self.wfile.write(bytes(result, "utf8"))

      def do_OPTIONS(self):
            self.send_response(200, "ok")
            self.send_header('Access-Control-Allow-Origin', self.headers['Origin'])
            self.send_header('Access-Control-Allow-Credentials', 'true')
            self.send_header("Access-Control-Allow-Headers", "authorization")
            self.end_headers()

def run(server_class=HTTPServer, handler_class=My_RequestHandler):
      server_address = ('', 8000)
      httpd = server_class(server_address, handler_class)
      print("Start Service!")
      httpd.serve_forever()


if __name__ == "__main__":
      run()
