import serial
import sys
import socket
import time

from PySide.QtGui import *
from PySide.QtCore import *


class Send_nmea_to_gui(QMainWindow):
    """ Vypisuje na seriovu port/ Etherbet nmea vety podle casu """

    def __init__(self, parent=None):
        super(Send_nmea_to_gui, self).__init__(parent)
        self.init_Ui(self)
        self.signals()

    def init_Ui(self, parent):
        self.serial_thread = Serial_connectivity()  # thread serial
        self.ethernet_thread = Ethernet_connectivity()  # thread serial

        self.setFixedSize(250, 125)
        self.setWindowTitle('Data to GUI')
        self.setWindowIcon(QIcon("transmitter_icon.ico"))

        self.pushButton_serial = QPushButton('SERIAL', self)
        self.pushButton_serial.resize(self.pushButton_serial.sizeHint())
        self.pushButton_serial.move(45, 50)

        self.pushButton_ethernet = QPushButton('  ETHERNET  ', self)
        self.pushButton_ethernet.resize(self.pushButton_ethernet.sizeHint())
        self.pushButton_ethernet.move(135, 50)

    def signals(self):

        self.pushButton_serial.clicked.connect(self.serial_connectivity)
        self.pushButton_ethernet.clicked.connect(self.ethernet_connectivity)

        self.connect(self.serial_thread, SIGNAL("serial_stop()"), self.ethernet_connectivity)
        self.connect(self.ethernet_thread, SIGNAL("ethernet_stop()"), self.serial_connectivity)



    def serial_connectivity(self):
        time.sleep(0.5)
        if self.ethernet_thread.isRunning():
            self.ethernet_thread.exiting = True
        elif not self.pushButton_ethernet.isEnabled():
            self.ethernet_stop()
            self.pushButton_serial.setText("SERIAL")
            self.pushButton_serial.resize(self.pushButton_ethernet.sizeHint())
        else:
            self.file_name()
            self.pushButton_serial.setText("SERIAL RUN")
            self.pushButton_serial.resize(self.pushButton_ethernet.sizeHint())
            self.pushButton_serial.setEnabled(False)
            self.pushButton_ethernet.setText("STOP")
            self.pushButton_ethernet.resize(self.pushButton_ethernet.sizeHint())
            self.serial_thread.exiting = False
            self.serial_thread.start()

    def serial_stop(self):
        self.serial_thread.exiting = True
        self.pushButton_serial.setText("SERIAL")
        self.pushButton_serial.resize(self.pushButton_ethernet.sizeHint())
        self.pushButton_serial.setEnabled(True)

    def ethernet_connectivity(self):
        time.sleep(0.5)
        if self.serial_thread.isRunning():
            self.serial_thread.exiting = True
        elif not self.pushButton_serial.isEnabled():
            self.serial_stop()
            self.pushButton_ethernet.setText("ETHERNET")
            self.pushButton_ethernet.resize(self.pushButton_ethernet.sizeHint())
        else:
            self.file_name()
            self.pushButton_ethernet.setText("ETHERNET RUN")
            self.pushButton_ethernet.resize(self.pushButton_ethernet.sizeHint())
            self.pushButton_ethernet.setEnabled(False)
            self.pushButton_serial.setText("STOP")
            self.pushButton_serial.resize(self.pushButton_ethernet.sizeHint())
            self.ethernet_thread.exiting = False
            self.ethernet_thread.start()

    def ethernet_stop(self):
        self.ethernet_thread.exiting = True
        self.pushButton_ethernet.setText("ETHERNET")
        self.pushButton_ethernet.resize(self.pushButton_ethernet.sizeHint())
        self.pushButton_ethernet.setEnabled(True)

    def file_name(self):
        file_name = QFileDialog.getOpenFileName(self, "Read file", "", "Text file (*.txt);;All file (*.*)")
        self.serial_thread.path = (str(file_name[0]))
        self.ethernet_thread.path = (str(file_name[0]))

    def closeEvent(self, event):
        self.ethernet_stop()
        self.serial_stop()
        while self.serial_thread.isRunning():
            pass
        while self.ethernet_thread.isRunning():
            pass



class Serial_connectivity(QThread):
    def __init__(self, parent=None):
        super(Serial_connectivity, self).__init__(parent)
        self.exiting = False
        self.path = ""

    def run(self):
        # ---------------------------------------open and read file-------------------------------------------------
        try:
            infile = open(str(self.path), 'r')
            lines_infile = infile.readlines()
            infile.close()
        except:
            print("Fail to read file.")
            self.exiting = True

        # --------------------------------------------port setup----------------------------------------------------
        ser = serial.Serial()
        ser.port = "COM1"
        ser.baudrate = 115200
        ser.bytesize = serial.EIGHTBITS  # number of bits per bytes
        ser.parity = serial.PARITY_NONE  # set parity check: no parity
        ser.stopbits = serial.STOPBITS_ONE  # number of stop bits
        # ser.timeout = None                # block read
        ser.timeout = 1  # non-block read
        # ser.timeout = 2                   # timeout block read
        ser.xonxoff = False  # disable software flow control
        ser.rtscts = False  # disable hardware (RTS/CTS) flow control
        ser.dsrdtr = False  # disable hardware (DSR/DTR) flow control
        ser.writeTimeout = 2  # timeout for write
        # ser.open()
        try:
            ser.open()
        except Exception, e:
            print "error open serial port: " + str(e)
            # ---------------------------------------port write-----------------------------------------------------
        i = 0  # prochazeni radku
        a = 1  # number of send line
        stamp_old = 0  # compute delay
        delay_s = 0  # delay between sentence
        while not self.exiting:
            while ser.inWaiting() == 0:  # waiting on data true
                if i == len(lines_infile) - 1:  # line out of range data
                    i = 0
                    a = 0
                    stamp_old = 0  # compute delay
                    delay_s = 0  # delay between sentence
                    print ("Restart device (end file)")
                    continue
                line = lines_infile[i]  # read sentence from file
                i += 1
                if line == "":
                    continue
                msg = line.rstrip()  # cut white symbol and separate
                smsg_ = msg.split(",")

                if smsg_[0][:3] == "$PH":  # compute delay
                    stamp_new = float(smsg_[3])
                    delay_s = (stamp_new - stamp_old) / 1000
                    stamp_old = stamp_new  #

                if a % 100 == 0:  # info (every 100th) number of sentence send
                    print ("Sent {} NMEA sentencs.".format(a))
                a += 1

                ser.write(msg + "\n")  # write on port

                if self.exiting:  # exiting
                    ser.close()
                    break

                time.sleep(delay_s)  # delay between

            if self.exiting:  # exiting
                break
                # --------------------------------------------reset from gui----------------------------------------
            rmsg = ser.readline()  # read one line
            if rmsg == "":
                pass
            if rmsg == "reset device":  # read one line
                i = 0
                a = 0  # for info number
                stamp_old = 0  # for compute delay
                delay_s = 0  # for delay between sentence
                print(rmsg)
                # --------------------------------------------exit--------------------------------------------------
        ser.close()
        print "Break connectivity."
        self.emit(SIGNAL("serial_stop()"))
        QThread.quit(self)


class Ethernet_connectivity(QThread):
    def __init__(self, parent=None):
        super(Ethernet_connectivity, self).__init__(parent)
        self.exiting = False
        self.path = ""

    def run(self):
        """
        Ethernet server
        """
        # ---------------------------------------open and read file-------------------------------------------------
        try:
            infile = open(str(self.path), 'r')
            lines_infile = infile.readlines()
            infile.close()
        except:
            print("Fail to read file.")
            self.exiting = True
        # ---------------------------------------ethernet setup---------------------------------------------------------
        host = '0.0.0.0'
        port = 50007
        # create dgram udp socket
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        except socket.error:
            print 'Failed to create socket'
        try:
            s.bind((host, port))
        except socket.error, msg:
            print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
            s.close()

        print("Wait on host...")
        while not self.exiting:
            try:
                s.settimeout(1)
                d = s.recvfrom(1024)
                rdata = d[0]
                addr = d[1]
                print("Data from client {} :{}".format(addr, rdata))
                break
            except socket.error:
                pass

        i = 0
        a = 1
        stamp_old = 0  # compute delay
        delay_s = 0  # delay between sentence
        while not self.exiting:
            if i == len(lines_infile) - 1:  # line out of range data
                i = 0
                a = 0
                stamp_old = 0  # compute delay
                delay_s = 0  # delay between sentence
                print ("Restart device (end file)")
                continue
            if self.exiting:
                break
            msg = lines_infile[i].rstrip()
            smsg_ = msg.split(",")
            if smsg_[0][:3] == "$PH":
                stamp_new = float(smsg_[3])
                delay_s = (stamp_new - stamp_old) / 1000
                stamp_old = stamp_new
            i += 1
            if msg == "":
                continue
            if a % 100 == 0:
                print ("Sent {} NMEA sentencs.".format(a))
            a += 1
            try:
                # Set data to join client
                s.sendto(msg, addr)
                # print 'Server sent data: ' + msg + " to " + str(addr)
            except socket.error, msg:
                print 'Error Code : ' + str(msg)
                # receive data from client (data, addr)
                # -----------------------------------------------------reset from gui-----------------------------------
            try:
                s.settimeout(delay_s)  # set delay between sentences
                #s.settimeout(0.1)  # set delay between sentences
                d = s.recvfrom(1024)
                rdata = d[0]
                addr = d[1]
                print("Data from client {} :{}".format(addr, rdata))
                if rdata == "reset device":
                    i = 0
                    a = 1
                    stamp_old = 0  # compute delay
                    delay_s = 0  # delay between sentences
            except:
                pass
        # --------------------------------------------exit--------------------------------------------------------------
        s.close()
        print "Break connectivity."
        self.emit(SIGNAL("ethernet_stop()"))
        QThread.quit(self)

# -----------------------------------------------main loop--------------------------------------------------------------

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = Send_nmea_to_gui()
    main.show()
    app.exec_()

# ----------------------------------------------------------------------------------------------------------------------
