import sys       # command line parsing
import os        # sistema operativo
import os.path   # sistema operativo (gerarchia file)
import time      # gestione dei timer
import datetime  # data e ora
import Image     # gestione delle immagini
import re        # regular expression
import cStringIO # ram file
import cPickle   # oggetti Python

#------------------------------------------------------------------------------------------------------------------------------

__fontname = 'Courier'                                    # 'Terminal' | 'System' | 'Courier' | 'ABlack'
__mode     = 'poll'                                       # 'filter' | 'alone' | 'poll'
__format   = 'png'                                        # formato di output
__filename = '/w1/FIAT/disegni'                         # file di input (ignorato in modalita' 'filter')
__border   = '0'                                          # 0 caratteri blank di bordo
__timeout  = 2                                            # 2 secondi di timeout
__outdir   = '/w1/dos/ARCHIVIOX/Export/COMMERCIALE/DISEGNI' # outputdir

#------------------------------------------------------------------------------------------------------------------------------

__font = {}

char_bitmap_cache = {}

def get_char_bitmap( ascii ):
    # restituisce la bitmap del carattere 'ascii' recuperandola dal font 'font'
    #   i caratteri non supportati verranno sostituiti dal carattere 255
    #
    if ( __font['name'], ascii ) in char_bitmap_cache:
        return char_bitmap_cache[ ( __font['name'], ascii ) ]

    if ascii < __font['first'] or ascii > 255:
        ascii = 255
    
    relative_ascii = ascii - __font['first']

    char_x = relative_ascii % __font['cols']
    char_y = relative_ascii / __font['cols']

    x_start = __font['cell']['x'] * char_x + __font['offset']['x']
    x_stop  = x_start + __font['char']['x']
    
    y_start = __font['cell']['y'] * char_y + __font['offset']['y']
    y_stop  = y_start + __font['char']['y']

    bitmap = __font['font'].crop( ( x_start, y_start, x_stop, y_stop ) )

    char_bitmap_cache[ ( __font['name'], ascii ) ] = ( bitmap, __font['char']['x'], __font['char']['y'] )
    
    return ( bitmap, __font['char']['x'], __font['char']['y'] )

#------------------------------------------------------------------------------------------------------------------------------


def print_array( array, imgfilename, cols, rows ):
    # Stampa su file il contenuto di un array di stringhe
    # 
    if rows == 0 or cols == 0: # NON stampa le pagine vuote
        return
    
    char = __font['char']

    offsetx = 0
    offsety = 0

    xstart, ystart = offsetx, offsety    
    xstop,  ystop  = offsetx, offsety
    width, height  = (char['x'], char['y'])

    if __border == '1':
        offsetx = width
        offsety = height

    imgsize = ( width * cols + (offsetx * 2), height * rows + (offsety * 2) )
    
    img = Image.new( "RGB", imgsize, (255,255,255) )
    
    for line in array:
        for char in line:
            if ord(char) != 32:
                bitmap, w, h = get_char_bitmap( ord( char ) )

            xstop = xstart+width
            ystop = ystart+height
        
            if ord(char) != 32:
                img.paste( bitmap, ( int(xstart), int(ystart), int(xstop), int(ystop) ) )

            xstart = xstop
        ystart += height
        xstart = offsetx

    # save as PNG
    if __format == 'png':
        img.save( "%s//%s.png"  % (__outdir,imgfilename) )

    # save as GIF    
    if __format == 'gif':
        img.save( "%s//%s.gif"  % (__outdir,imgfilename) )

    # save as TXT
    if __format == 'txt':
        out = open( "%s//%s.txt" % (__outdir,imgfilename), 'w' )
        for line in array:
            for char in line:
                if ord(char) > 32:
                    out.write( char )
                else:
                    out.write( ' ' )
            out.write( '\n' )
        out.close()
    
#------------------------------------------------------------------------------------------------------------------------------

def text_to_img( rawfile ):
    # converte un file di testo in un file grafico
    #
    stringhe = []
    stringa = []
    filename = "txt2img"
    
    size_x, size_y, x = 0, 0, 0

    p1    = re.compile('Articolo      :  ([A-Z0-9]+)')
    p1bis = re.compile('ARTICOLO  ([A-Z0-9]+)  ')
    p2    = re.compile('    Mod\.([A-Z0-9 a-z]+)\Z')
    
    escape = 0   
    
    for ch in rawfile.read():
        
        # print char to standard output
        if __mode == 'filter':
            sys.stdout.write( ch )
            
        chord = ord(ch)
        
        if chord == 0x0A or chord == 0x0C: # newline / formfeed
            str = "".join(stringa)
            
            # modifica (se necessario) il nome del file (articolo)
            m1 = p1.search( str )
            if m1 != None:
                filename = m1.group(1)
                
            m1bis = p1bis.search( str )
            if m1bis != None:
                filename = m1bis.group(1) + '-Note'
                
            # modifica (se necessario) il nome del file (modello)
            m2 = p2.search( str )
            if m2 != None:
                filename += "-" + m2.group(1)

            # se riconosce l'inizio di una pagina, stampa la pagina precedente
            if str.find('DISTINTA  ') == str.find('ASSEMBLAGGIO') - 10  or str.find('    DISTINTA DI PRODUZIONE') != -1:
                print_array( stringhe, filename, size_x, size_y )
                stringhe = []
                filename = "default"
                size_y = 0

            # aggiunge comunque la stringa alla pagina in memoria
            stringhe.append( str )
            size_y += 1
            
            if len(stringa) > size_x:
                size_x = len(stringa)
                
            stringa = []
            
        elif chord == 0x0D: # carriage return (e termine sequenza di escape)
            x = 0
            escape = 0
            
        elif chord > 32: # caratteri stampabili
            if escape:
                pass
            elif len(stringa) > x:
                stringa[x] = ch
            else:
                stringa.append( ch )
            x += 1

        elif chord == 32: # spazio (permetti sovrastampa)
            if escape:
                pass
            elif len(stringa) > x:
                pass # non sovrascrive il carattere
            else:
                stringa.append( ch )
            x += 1
        elif chord == 27: # sequenza di escape (inizio)
            escape = 1
        else: # altri caratteri di controllo
            pass
            
    print_array( stringhe, filename, size_x, size_y )

#------------------------------------------------------------------------------------------------------------------------------

def printSyntax():
    print """
    txt2gif:
        Convertitore da testo a immagine
    
    Utilizzo:
        txt2gif [--mode (filter|alone|poll)] [--format (gif|png)] [--font {pyfontname}]
                [--border (0|1)] [--timeout {seconds}] [--outdir {directory}] [txtfile]
    
        --mode    = modalita' di conversione
                    'filter' si comporta come une filtro LPD accettando testo da stdin e riproponendolo inalterato su stdout
                    mentre crea i file grafici equivalenti
                    'alone' accetta un file di testo in input e generea gli equivalenti file grafici
                    'poll' verifica ogni 'timeout' secondi il contenuto del file di input, e lo converte nei file grafici equivalenti

        --format  = formato dei file grafici generati, txt = file di testo ascii 8 bit

        --font    = font da utilizzare per la conversione, i piu' comuni sono Terminal, System e Courier

        --border  = bordo bianco, se settato a 1, lascia un bordo bianco di 1 carattere attorno all'immagine

        --timeout = tempo di attesa nella modalita' 'poll' prima di procedere alla conversione il file di input deve mantenere la
                    medesima dimensione per almeno timeout secondi prima che il processo di conversione venga effettuato

        --outdir  = directory in cui riporre i file grafici generati
        
        txtfile   = file da convertire (in modalita' 'alone') o da controllare e convertire (in modalita' 'poll')
    """
    sys.exit(0)              
    
#------------------------------------------------------------------------------------------------------------------------------

args = sys.argv[1:]

idx = 0
while idx < len(args):
    arg = args[ idx ]
    if arg == '--mode':
        __mode = args[ idx + 1 ]
        if __mode != 'filter' and __mode != 'alone' and __mode != 'poll':
            print '\n INVALID MODE \n'
            printSyntax()
    elif arg == '--format':
        __format = args[ idx + 1 ]
        if __format != 'gif' and __format != 'png' and __format != 'txt':
            print '\n INVALID FORMAT \n'
            printSyntax()
    elif arg == '--font':
        __fontname = args[ idx + 1 ]
        if not os.path.isfile('.//%s.pyfont' % __fontname):
            print '\n INVALID FONT \n'
            printSyntax()
    elif arg == '--border':
        __border = args[ idx + 1 ]
        if __border != '0' and __border != '1':
            print '\n INVALID BORDER \n'
            printSyntax()
    elif arg == '--timeout':
        __timeout = args[ idx + 1 ]
        try:
            __timeout = int( __timeout )
        except:
            print '\n INVALID TIMEOUT (must be an integer} \n'
            printSyntax()
        if __timeout < 1 or __timeout > 120 :
            print '\n INVALID TIMEOUT (must be between 1 and 120 secs} \n'
            printSyntax()
    elif arg == '--outdir':
        __outdir = args[ idx + 1 ]
    elif arg[0] != '-':
        __filename = arg
        idx -= 1
    else:
        printSyntax()
        
    idx += 2

# -----------------------------------------------------------------------------------------------------------------------------------

f = open('.//%s.pyfont' % __fontname, 'rb')
buffer = f.read()
f.close

__font = cPickle.loads( buffer )

if __mode == 'alone':
    rawfile = open( __filename, 'rb' )
    text_to_img( rawfile )
    rawfile.close()
    
elif __mode == 'filter':
    text_to_img( sys.stdin )
    
elif __mode == 'poll':
    size = 0
    mtime = 0
    while 1:
        try:
            stat = os.stat( __filename )
            mysize,mymtime = stat[6],stat[8]

            if mysize == size and mymtime == mtime:
                print datetime.datetime.now().strftime("%a %d/%m/%Y  %H:%M:%S"),
                start = time.time()
                # convert!!!
                rawfile = open( __filename, 'rb' )
                text_to_img( rawfile )
                rawfile.close()
                stop = time.time()
                print 'Done! (%f sec)' % (stop-start)
                
                # remove from filesystem
                os.remove( __filename )
            else:
                # waiting...
                size = mysize
                mtime = mymtime
        except:
            # missing
            pass
        time.sleep( __timeout )
    
else:
    print 'working mode unsupported'

# -----------------------------------------------------------------------------------------------------------------------------------
    
