"""interact with the Prologix GPIB and MCE IB test setup"""
import serial
import time


class PrologixGpibChat(object):
    """GPIB communication over prologix USB adapter"""
    def __init__(self, serial_dev):
        # track the current device address
        self.active_addr = None

        self.ser = serial.Serial(port=serial_dev,
                                 baudrate=115200,
                                 parity=serial.PARITY_NONE,
                                 stopbits=serial.STOPBITS_ONE,
                                 bytesize=serial.EIGHTBITS,
                                 timeout=10)

        self.initialize_prologix()

    def send_single(self, cmd_str, wait=0.1):
        """send a command and read the reply
        `wait` is important for long acq. commands
        (otherwise the output will be buffered on the next read)
        """
        self.ser.write(cmd_str + "\r\n")
        time.sleep(wait)
        self.ser.write("++read eoi\r\n")

        output = None
        time.sleep(0.1)

        if self.ser.inWaiting():
            output = self.ser.read(self.ser.inWaiting())[:-1]
            if output == "":
                output = "EMPTY"

            print "sent: %s, reply: %s" % (cmd_str, output)
        else:
            print "sent: %s" % cmd_str

        return output

    def initialize_prologix(self):
        """Issue a reset and put interface in control mode
        """
        print "Initializing Prologix USB-GPIB card"

        self.send_single("++rst")
        print "waiting 7 sec after Prologix reset"
        time.sleep(7)

        self.send_single("++ver")
        #self.send_single("++ifc")
        self.send_single("++mode 1")
        #self.send_single("++auto 1")

    def gpib_call(self, cmd_str, addr, wait=0.1):
        """send a command to a GPIB adddress and wait for reply
        """
        if addr != self.active_addr:
            self.send_single("++addr %s" % addr)
            self.active_addr = addr

        output = self.send_single(cmd_str, wait=wait)
        return output


class MceContinuity(object):
    """handle all communication with MCE continity card"""
    def __init__(self, serial_dev, ib_addr="10", meter_addr="1"):
        self.ib_addr = ib_addr
        self.meter_addr = meter_addr
        self.gpib_bus = PrologixGpibChat(serial_dev)
        self.slot_number = None

        self.test_connections()

    def test_connections(self):
        """test the connections to the multimeter and IB card"""
        self.gpib_bus.gpib_call("*idn?", addr=self.meter_addr, wait=0.5)
        #self.gpib_bus.gpib_call(":meas:volt:dc?",
        #                        addr=self.meter_addr, wait=0.5)

        self.gpib_bus.gpib_call("R", addr=self.ib_addr)
        self.slot_number = self.gpib_bus.gpib_call("S", addr=self.ib_addr)
        self.slot_number = int(self.slot_number.strip())

        print "determined slot number %s" % self.slot_number

    def run_template(self, filename_in):
        """Given a template file, run through all the requested checks
        These are text files with rows in the format:
        raw_name name mux1_command mux2_command read_command
        where mux1 sets the positive side of the continuity test
        mux2 is the negative side of the test and
        read_command is the measurement command to issue to the meter

        Note that F3R4N4Z1T1 was used in previous multimeter calls
        """
        file_in = open(filename_in, "r")
        filebase = filename_in.split(".")[:-1][0]

        if self.slot_number is None:
            print "slot was not determined"
            return

        filename_out = "%s_slot%d.dat" % (filebase, self.slot_number)
        print "writing to: ", filename_out
        file_out = open(filename_out, "w")

        for line in file_in.readlines():
            run_info = line.split()
            if int(run_info[0]) == self.slot_number:
                chan_name = run_info[2]
                mux1 = run_info[3]
                mux2 = run_info[4]
                meas = run_info[5]

                self.gpib_bus.gpib_call(mux1, addr=self.ib_addr, wait=0.1)
                self.gpib_bus.gpib_call(mux2, addr=self.ib_addr, wait=0.1)
                output = self.gpib_bus.gpib_call(meas, addr=self.meter_addr,
                                                 wait=2.)

                print chan_name, mux1, mux2, meas, output
                file_out.write("%s %s\n" % (chan_name, output))

        file_in.close()
        file_out.close()


if __name__ == "__main__":
    ib_test = MceContinuity("/dev/tty.usbserial-PXR3NWM6")
    ib_test.run_template("5MDM_ib_continuity_test_template.txt")