import os
import sys
import inspect
import numpy as np
import string
import calibr_box
import find_usb_tty
import ptsexcept


DEBUG       = False
INFO        = True
WARRNING    = True
CRITICAL    = True

FIRMWARE_PATH           ='gateware/syn/spec/spec_top_fmc_masterfip.bin'
TOPDIRNAME              ="fmcmasterfip"

test03_outputpath       ='/tmp/'

test05_output_file     = "/tmp/eeprom"
test05_fru_gen_path    = "/software/fmc-bus/tools/fru-generator"
test05_gensdbfs_path   = "/software/fpga-config-space/sdbfs/userspace/gensdbfs"
test05_sdbfs_path      = "/python/sdbfs/"

test06_thd = 2000;
test06_thdratio = 1.8

mintemp                 = 0
maxtemp                 = 80

fmcmasterfip_commonpath="/python/common"
fmcmasterfip_regspath="/python/regs"
speclib_path = '/software/spec-sw/tools/libspec.so';
faldacq_path = "/software/fmc-adc-100m14b4cha-sw/libtools/fald-acq"


BOX_USB_VENDOR_ID = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device

def lineno(steps = 1):
    """Returns the current line number in our program."""
    ptr = inspect.currentframe().f_back
    for i in xrange(steps) :
        ptr = ptr.f_back
    ptr = ptr.f_lineno;
    return ptr
#     return inspect.currentframe().f_back.f_back.f_lineno

def linefile(steps = 1):
    """Returns the current line number in our program."""
    ptr = inspect.currentframe().f_back
    for i in xrange(steps) :
        ptr = ptr.f_back
    ptr = ptr.f_code;
    return ptr
#     return inspect.currentframe().f_back.f_back.f_code

# find absolute path of directory of name stored in topdirname
def find_prj_topdir(topdirname):
    [ tmppath, dirname ] = os.path.split( os.getcwd() );
    while( tmppath != '/' ):
        if dirname == topdirname:
            return os.path.join( tmppath, dirname)+"/"
        [ tmppath, dirname ] = os.path.split(tmppath);
    
    crit_msg("Top directory path not found\nPlease make sure that top directory of PtsFmcMastrefip is called \"fmcmasterfip\"")
    return "";


def user_msg( msg ):
    print >> sys.__stdout__, ( "%s" % msg );


def dbg_msg( msg, steps = 1 ):
    msg = string.replace(msg, "\n", "\n\t\t\t\t")
    if DEBUG == True :
        print ( "\t\t\tDEBUG: %s %s %s"  % ( msg, linefile(steps), lineno(steps) ) );

def info_msg( msg ):
    msg = string.replace(msg, "\n", "\n\t")
    if INFO == True :
        print ( "\t%s" % msg);
        
def warr_msg( string ):
    string = string.replace(string, "\n", "\n\t\t")
    if WARRNING == True :
        print ( "\tWARRNING: %s" % string);

def err_msg( msg ):
#     msg = string.replace(msg, "\n", "\n")
    print ( "ERROR: %s" % msg);

def header_msg( testname, undertest ):
    print ( "_______________________________________________________________");
    print ( "                        %s " % testname );
    print ( "_______________________________________________________________");
    print ( "Testing:" );
    for t in undertest:
        print ("\t%s" % t )
    print ( "_______________________________________________________________");
    print("")
     
       
def info_err_msg( msg, err ):
    if err:
        err_msg(msg)
    else :
        info_msg(msg)
        
def section_msg( msg ):
#     msg = string.replace(msg, "\n", "\n\t")
    print ( "\n_________________ %s _________________" % msg);
        
def crit_msg( msg ):
    print ( "CRITICAL: %s" % msg);
    raise Exception("Critical: %s" % msg )

def ask_user( question ):
    user_msg(question+" (Y/n)");
    ret = raw_input("")
    
    info_msg("User was asked:")
    info_msg(question)
    
    if ret == 'n':
        info_msg("User replied: No")
        return False
    else:
        info_msg("User replied: Yes")
        return True

def u2int8(val):
    if val & 0x8000:
        val = np.int8( np.uint8( val ) ^ np.uint8( 0xfffff ) + 1 )
    return val
    
def u2int16(val):
    if val & 0x8000:
        val = np.int16( np.uint16( val ) ^ np.uint16( 0xfffff ) + 1 )
    return val

def u2int32(val):
    if val & 0x80000000:
        val = np.int32( np.uint32( val ) ^ np.uint32( 0xffffffffff ) + 1 )
    return val

def u2int16arr(arr):
    for i in xrange( len( arr ) ):
        arr[i]=u2int16(arr[i])
    return arr

def summarise_test_results( test_name, test_results ):
    print "\n\n\n"
    section_msg("Summary of %s" % test_name)
    errors = 0 
    for k, v in test_results.iteritems():
        if v == 0:
            errors += 1;
            info_msg("Subtest FAILED: %s!" % k )
        else:
            info_msg("Subtest SUCCESSFULL: %s!" % k )
    
    if errors:
        section_msg("%s failed with %d errors" % ( test_name,  errors) )
        raise ptsexcept.PtsError("%s failed with %d errors" % ( test_name,  errors) )
    else:
        section_msg("%s finished successful" % test_name )
    
    
def bitvector( word, low, high ):
    word = word & ( pow(2,high+1)-1 )
    word = word >> low
    return word

def merge_dictionaries(dict0, dict1):
    return dict( dict0.items() + dict1.items() )

def merge_dictionaries_prefix(dict0, dict1, prefix0, prefix1):
    tmp ={}
    
    for k, v in dict0.iteritems():
        tmp[prefix0+k]=v
    
    for k, v in dict1.iteritems():
        tmp[prefix1+k]=v
        
    return tmp    
    
    
def calibration_box_init():
        section_msg("Initialization of calibration box")
        
        info_msg("Looking for calibration box")
        box_tty = find_usb_tty.CttyUSB().find_usb_tty(BOX_USB_VENDOR_ID, BOX_USB_DEVICE_ID)

        
        if len( box_tty ) < 1:
            err_msg("Can't find calibration box. Make sure that it is connected, and that CP210x driver was correctly mounted")
            raise ptsexcept.PtsCritical( "Can't find calibration box. Make sure that it is connected, and that CP210x driver was correctly mounted");
        for box in box_tty:
            info_msg("Found device: %s" % box)
            
        box = calibr_box.CCalibr_box(box_tty[0])
        
        return box
