import time
from .psw_gw_instek import GWInstekPSW
#from .tpg262_gnome232 import TPG262GNOME232


def write_value2file(fname, value):
    with open(fname, 'w') as f:
        f.write(str(value))
        
def add_string2file(fname, string):
    with open(fname, 'a+') as f:
        f.write(string)        


def guess_initial_voltage(calibration_table, target_pressure):
    import numpy as np          # import only if this function is called
    from numpy.polynomial import Polynomial
    # calibration table is expected to be of the form
    # voltage pressure
    voltages, pressures = np.loadtxt(calibration_table, unpack=True)
    # least squares fit of a polynomial of given degree
    poly = Polynomial.fit(pressures, voltages, deg=2)
    voltage_guess = poly(target_pressure)
    add_string2file('/dev/shm/golem/ActualSession/SessionLogBook/GlobalLogbook','Initial guess for valve PS: % 2.2f V (target: % 2.1f mPa)\n' % (voltage_guess,target_pressure))
    add_string2file('/dev/shm/golem/ActualSession/SessionLogBook/PressureLog','Initial guess for valve PS: % 2.2f V (target: % 2.1f mPa)\n' %(voltage_guess,target_pressure))
    return voltage_guess


def fill_chamber(target_pressure, eps=0.1, start_v=20,
                 interval=1.5, proportional_const=1e-1, derivative_const=1e-1,
                 max_time=60, fail_pressure=200,
                 psw_address='192.168.2.75', gauge_address='192.168.2.246',
                 calibration_table="/dev/shm/golem/ActualSession/SessionLogBook/WG_calibration_table",  # should be a string if available
                 verbose=False):
    psw = GWInstekPSW(psw_address)
    #gauge = TPG262GNOME232(gauge_address)
    add_string2file('/dev/shm/golem/ActualSession/SessionLogBook/PressureLog','fill_chamber START\n')

    if calibration_table is not None:
        v = guess_initial_voltage(calibration_table, target_pressure)
    else:
        v = start_v
    psw.set_voltage(v)
    write_value2file('/dev/shm/golem/ActualSession/SessionLogBook/ActualVoltageAtGasValve', v) # 250520: pridano VoSv
    psw.set_output(True)
    last_p = p = 0
    start_t = time.time()
    #while True:
    for x in range(10):   
        last_p = p
        ff=open("/dev/shm/golem/ActualSession/SessionLogBook/ActualChamberPressuremPa", "r") #omlouvam se
        p=float(ff.read())  # to mPa 
        #p = gauge.get_pressure(1) * 1e3  # to mPa
        #write_value2file('/dev/shm/pressure_chamber_mPa', p) # 250520: zbytecne VoSv
        if p > fail_pressure:
            #psv.set_output(False) 0420 Hlasilo problem NameError: name 'psv' is not defined
            psw.set_output(False)
            raise RuntimeError('pressure {} over limit {}'.format(p, fail_pressure))
        elapsed = time.time() - start_t
        if elapsed > max_time:
            raise RuntimeError('did not converge, maintaining pressure {}'.format(p))
        err = target_pressure - p
        change = p - last_p
        if abs(err) < eps and abs(change)/interval < eps:
            if verbose:
                print('reached pressure {} with error {} and change {} in {} seconds '.format(p, err, change, elapsed))
            break
        v += proportional_const * err - derivative_const * change / interval
        psw.set_voltage(v)
        write_value2file('/dev/shm/golem/ActualSession/SessionLogBook/ActualVoltageAtGasValve', v) # 250520: pridano VoSv
        if verbose:
            print('pressure {}, setting voltage {}'.format(p, v))
        time.sleep(interval)
    add_string2file('/dev/shm/golem/ActualSession/SessionLogBook/PressureLog','fill_chamber END\n')


def close_valve(psw_address='192.168.2.75'):
    psw = GWInstekPSW(psw_address)
    psw.set_output(False)
    write_value2file('/dev/shm/golem/ActualSession/SessionLogBook/ActualVoltageAtGasValve', "0")

