#! /usr/bin/env python

import sys, os, os.path
import time
import subprocess

import numpy as np

import dice.testbench.motor as dtm
import dice.testbench.utils.grid as dtug
import dice.testbench.multimeter.keithley6514 as multi
import dice.testbench.temperature.digisense as dttd


import dice.control.led.sndice_refurbished_specs as specs


# ---------------------------------------------------------
#
# Commands on DICE head control PC

def dice_led_on_off(led, current, on):
    on_str = "OFF"
    if on:
        on_str = "ON"

    command = ( "dice-led-on-off --force --current %f  %d  %s" % 
                (current, led, on_str) )
    proc = subprocess.Popen(command, shell=True,
                            stdout = subprocess.PIPE,
                            stderr = subprocess.PIPE)
    (out, err) = proc.communicate()
    # print err


def dice_sample(channel, tries = 2):
    command = ( "dice-sample %d" % channel )
    #
    for t in xrange(tries):
        proc = subprocess.Popen(command, shell=True,
                                stdout = subprocess.PIPE,
                                stderr = subprocess.PIPE)
        (out, err) = proc.communicate()
        parts = out.strip().split()
        print parts
        if len(parts)==5:
            break
    #
    if len(parts)!=5:
        raise IOError("Failed to run dice-sample")
    #
    #
    # 1332329172.153316     63    4681    -26.865627    4047.965067
    t = float(parts[0])
    c = int(parts[1])
    n = int(parts[2])
    mean = float(parts[3])
    variance = float(parts[4])
    #
    return t, c, n, mean, variance



def clap_sample(channel, tries = 2):
    host = "dicehead"
    command = ( "clap-sample %d" % channel )
    remote_command = "ssh %s %s" % (host, command)
    #
    for t in xrange(tries):
        proc = subprocess.Popen(remote_command, shell=True,
                                stdout = subprocess.PIPE,
                                stderr = subprocess.PIPE)
        (out, err) = proc.communicate()
        parts = out.strip().split()
        print parts
        if len(parts)==5:
            break
    #
    if len(parts)!=5:
        raise IOError("Failed to remotely run clap-sample")
    #
    # 1332329172.153316     63    4681    -26.865627    4047.965067
    t = float(parts[0])
    c = int(parts[1])
    n = int(parts[2])
    mean = float(parts[3])
    variance = float(parts[4])
    #
    return t, c, n, mean, variance

def backend_samples(f):
    # Sample before turning on (dark current)
        
    sample_led    = dice_sample(led)
    sample_phd    = dice_sample(led + 33)
    sample_temp24 = dice_sample(58)
    sample_tempBE = dice_sample(59)
    sample_temp9  = dice_sample(60)
    sample_vref   = dice_sample(61)

    print >>f, "# DARK current"
    print >>f, "# ILED   " + "   ".join([str(i) for i in sample_led])
    print >>f, "# IPHD   " + "   ".join([str(i) for i in sample_phd])
    print >>f, "# TEMP24 " + "   ".join([str(i) for i in sample_temp24])
    print >>f, "# TEMPBE " + "   ".join([str(i) for i in sample_tempBE])
    print >>f, "# TEMP9  " + "   ".join([str(i) for i in sample_temp9])
    print >>f, "# VREF   " + "   ".join([str(i) for i in sample_vref])
    f.flush()

def clap_samples(f):
    # Sample before turning on (dark current)
        
    sample_g1      = clap_sample(1)
    sample_g32     = clap_sample(2)
    sample_tclap0  = clap_sample(3)
    sample_tclap1  = clap_sample(4)
    sample_tbe     = clap_sample(5)
    sample_lemo    = clap_sample(6)
    sample_biasout = clap_sample(7)
    sample_gndfe   = clap_sample(8)

    print >>f, "# G1      " + "   ".join([str(i) for i in sample_g1])
    print >>f, "# G32     " + "   ".join([str(i) for i in sample_g32])
    print >>f, "# TCLAP0  " + "   ".join([str(i) for i in sample_tclap0])
    print >>f, "# TCLAP1  " + "   ".join([str(i) for i in sample_tclap1])
    print >>f, "# TBE     " + "   ".join([str(i) for i in sample_tbe])
    print >>f, "# LEMO    " + "   ".join([str(i) for i in sample_lemo])
    print >>f, "# BIASOUT " + "   ".join([str(i) for i in sample_biasout])
    print >>f, "# GNDFE   " + "   ".join([str(i) for i in sample_gndfe])
    f.flush()



# --------- Parse command line arguments ------------------

def usage():
    print >>sys.stderr, \
        'usage: beam-map led=<led> current=<current> z=<z>'
    print >>sys.stderr, \
        "                    [xmin=<xmin> xmax=<xmax> ymin=<ymin> ymax=<ymax>]"
    print >>sys.stderr, \
        "                    [dx=<dx> dy=<dy>]"
    

# print sys.argv

if len(sys.argv) < 1:
    usage()
    sys.exit(1)


phd = "NIST"
phd_port = "/dev/ttyS3"
led = 19
current = 10000. # ADU
z = -1590. # mm

# xmin =     0. # mm
# xmax =   300. # mm
# ymin =     0. # mm
# ymax =   300. # mm
# zmin = -1593. # mm
# zmax =     0. # mm

xmin = 135. # mm
xmax = 165. # mm
ymin = 133. # mm
ymax = 163. # mm

# dx = 10. # mm
# dy = 10. # mm
dx = 1. # mm
dy = 1. # mm

for arg in sys.argv[1:]:
    if '=' not in arg:
        print >>sys.stderr, "error: invalid argument [%s]" % arg
        usage()
        sys.exit(2)
    eqparts = arg.split('=')
    if len(eqparts) != 2:
        print >>sys.stderr, "error: invalid argument format [%s]" % arg
        usage()
        sys.exit(3)
    
    param = eqparts[0].lower()
    if param not in ['led', 'z', 'current',
                     'xmin', 'xmax', 'ymin', 'ymax',
                     'dx', 'dy'
                     ]:
        print >>sys.stderr, "error: invalid parameter [%s]" % arg
        usage()
        sys.exit(4)

    exec(arg)
    # print arg, param, eval(param)

# --------- Init testbench motors -------------------------

B = dtm.Bench()
B.open()
B.setup()

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

# --------- Init multimeter Keithley 6514 -----------------

K = multi.Multimeter(port = phd_port)

K.open()
K.reset()
# K.write("CURR:RANG 2e-7")
K.write("CURR:RANG 2e-10")
K.write("FUNC 'CURR:DC'")
K.write("SYST:ZCH OFF")

# ---------------------------------------------------------
#
# LEDHEAD : moving LED head to put each LED in front
# of the monochromator entrance slit

def ledhead_position(led):
    # x_ref = 77. #mm
    x_ref = 71. #mm
    y_ref = 87. #mm
    # DO NOT CHANGE THIS !
    x = x_ref + specs.LEDS[led]['x']
    y = y_ref + specs.LEDS[led]['y']
    return x, y

# --------- Init DIGISENSE temperature --------------------

DG = dttd.Temperature(port = "/dev/ttyS0")
DG.open()


def temperature_measurements(f):
    # Measure DigiSense temperature 

    dg_temperature = DG.measure()
    print >>f, "# TEMP_DIGISENSE   %s  %s" % (str(time.time()),
                                              str(dg_temperature))
    f.flush()


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

# xy_mm = 12800.0 # steps / mm
# z_mm  =  2560.0 # steps / mm

B.sensor_move_absolute('Z', z, unit = "mm")

filename = ("PENCIL-BEAM-%02d-on-map-I=%06dADU-z=%06dmm-dxdy=%fmm%fmm-%s-CLAP-%f.data" %
            ( led, current, z, dx, dy, phd, time.time() ) )
f = open(filename, "w")
print >>f, "# time   x(mm)   y(mm)    I(A)"

# ipos = 0
xref = xmin + (xmax-xmin)/2
yref = ymin + (ymax-ymin)/2

xlast,ylast = None, None
for (x,y) in dtug.Grid(xmin, xmax, dx,
                       ymin, ymax, dy,
                       order = "faster",
                       reference = {'x':xref,'y':yref, 'period':20} ):
    print "LED map: GOTO to ", x, y
    if x != xlast: B.sensor_move_absolute('X', x, unit = "mm")
    if y != ylast: B.sensor_move_absolute('Y', y, unit = "mm")
    xlast = x
    ylast = y

    # extra delay for capacity discharge ?
    # time.sleep(3)

    T = time.time()
    # K.write("READ?")
    # data_str = K.read()
    # print "Received [%s]" % data_str
    # parts = data_str.split(',')
    # if (len(parts) != 3):
    #     print >>sys.stderr, "No data. stop."
    #     break

    # flux = float(parts[0])
    # print T, x, y, flux
    # print >>f, T, x, y, flux
    # f.flush()

    # read clap samples

    sample_g1      = clap_sample(1)
    sample_g32     = clap_sample(2)

    # print >>f, "# G1      " + "   ".join([str(i) for i in sample_g1])
    # print >>f, "# G32     " + "   ".join([str(i) for i in sample_g32])

    print >>f, T, x, y, "   ".join([str(i) for i in sample_g1]), " # G1"
    print >>f, T, x, y, "   ".join([str(i) for i in sample_g32]), " # G32"

    # ipos+=1

    # if (ipos==20):
    #     print "LED map: GOTO to ref position", xref, yref
    #     B.sensor_move_absolute('X', xref, unit = "mm")
    #     B.sensor_move_absolute('Y', yref, unit = "mm")
    #     xlast = xref
    #     ylast = yref
    #     time.sleep(10)
    #     T = time.time()
    #     K.write("READ?")
    #     data_str = K.read()
    #     print "Received [%s]" % data_str
    #     parts = data_str.split(',')
    #     if (len(parts) != 3):
    #         print >>sys.stderr, "No data. stop."
    #         break
    #     flux = float(parts[0])
    #     print T, xref, yref, flux
    #     print >>f, T, xref, yref, flux
    #     f.flush()
    #     ipos=0

f.close()

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

K.close()
B.close()

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

