#!/usr/bin

# output_files.py
#       --copyright--                   Copyright 2007 (C) Tranzoa, Co. All rights reserved.    Warranty: You're free and on your own here. This code is not necessarily up-to-date or of public quality.
#       --url--                         http://www.tranzoa.net/tzpython/
#       --email--                       pycode is the name to send to. tranzoa.com is the place to send to.
#       --bodstamps--
#       January 18, 2008        bar
#       January 20, 2008        bar     comment
#       March 12, 2008          bar     proper spaces in html header
#       May 17, 2008            bar     email adr
#       September 23, 2010      bar     sh pl pm and hash files
#       September 28, 2010      bar     put a 1; at the end of Perl
#       October 1, 2010         bar     json is C
#                                       don't put pound defines in c-like languages
#       October 28, 2010        bar     a way to add encoding directive to the top of the hash languages
#       December 26, 2010       bar     take the trailing ***/ off the header for the generic (e.g. .txt) file
#       January 27, 2011        bar     safely write file names that are unicode
#                                       imports tzlib now for that. keep an eye out for projects that don't want this and replace_file does not import tzlib, purposely, if I recall.
#       March 3, 2011           bar     egad! fix c and c-like files. if statement typo
#       --eodstamps--
##      \file
#
#
#       Create a class whose objects are output files in various formats with appropriate headers and trailers for auto-generated files.
#
#

import  os
import  time
import  traceback

import  replace_file
import  tzlib


class   a_filer(object) :
    def __init__(me, file_name, fo) :
        me.fo           = fo
        me.file_name    = file_name

        me.bfile_name   = os.path.split(file_name)[1]
        me.pfile_name   = os.path.split(traceback.extract_stack()[0][0])[1]             # the highest level module name. os.path.split(traceback.extract_stack()[-1][0])[1] is this file's name


    def get_write_mode(me) :
        return("")                  # or "b"


    def hdr_str(me) :
        return(me.bfile_name.encode('utf8') + " " + time.asctime() + " Produced by " + me.pfile_name.encode('utf8'))

    def write_header(me) :
        if  me.fo :
            print >> me.fo, ";   " + me.hdr_str()
            print >> me.fo
        pass


    def write_trailer(me) :
        if  me.fo :
            print >> me.fo
            print >> me.fo, ";"
            print >> me.fo, ";"
            print >> me.fo, ";"
            print >> me.fo, "; eof"
        pass


    pass    # a_filer



class   a_c_filer(a_filer) :
    def write_header(me) :
        if  me.fo :
            print >> me.fo, "/***  "    + me.hdr_str() + " ***/"
            print >> me.fo

            n   = tzlib.best_ascii(me.bfile_name.replace(".", "_")).upper()
            print >> me.fo, "#ifndef _" + n
            print >> me.fo, "#define _" + n + " 1"
            print >> me.fo
            print >> me.fo
        pass


    def write_trailer(me) :
        if  me.fo :
            print >> me.fo
            print >> me.fo
            print >> me.fo, "#endif"
            print >> me.fo
            print >> me.fo
            print >> me.fo
            print >> me.fo, "/* eof */"
        pass


    pass    # a_c_filer



class   a_c_like_filer(a_filer) :
    def write_header(me) :
        if  me.fo :
            print >> me.fo, "/***  "    + me.hdr_str() + " ***/"
            print >> me.fo
        pass


    def write_trailer(me) :
        if  me.fo :
            print >> me.fo
            print >> me.fo
            print >> me.fo
            print >> me.fo, "/* eof */"
        pass


    pass    # a_c_like_filer



class   an_htm_filer(a_filer) :
    def write_header(me) :
        if  me.fo :
            print >> me.fo, "<HTML>"
            print >> me.fo, "<!-- " + me.hdr_str() + " -->"
            print >> me.fo
        pass


    def write_trailer(me) :
        if  me.fo :
            print >> me.fo
            print >> me.fo, "</HTML>"
        pass


    pass    # an_htm_filer





class   a_hash_filer(a_filer) :
    def __init__(me, *args, **kwargs) :
        me.shebang  = kwargs.get('shebang', None)
        del(kwargs['shebang'])
        super(a_hash_filer, me).__init__(*args, **kwargs)


    def write_header(me) :
        if  me.fo :
            if  me.shebang :
                print >> me.fo, me.shebang
                print >> me.fo
            print >> me.fo, "#   " + me.hdr_str()
            print >> me.fo, "#"
            print >> me.fo, "#"
            print >> me.fo
            print >> me.fo
        pass


    def write_trailer(me) :
        if  me.fo :
            print >> me.fo
            print >> me.fo
            print >> me.fo, "#"
            print >> me.fo, "#"
            print >> me.fo, "#"
            print >> me.fo, "# eof"
        pass


    pass    # a_hash_filer



class   a_py_filer(a_hash_filer) :
    def __init__(me, *args, **kwargs) :
        kwargs['shebang']   = kwargs.get('shebang', "#!/usr/bin/python")
        super(a_py_filer, me).__init__(*args, **kwargs)
    pass    # a_py_filer



class   a_pl_filer(a_hash_filer) :
    def __init__(me, *args, **kwargs) :
        kwargs['shebang']   = kwargs.get('shebang', "#!/usr/bin/perl")
        super(a_pl_filer, me).__init__(*args, **kwargs)
    def write_trailer(me) :
        if  me.fo :
            print >> me.fo
            print >> me.fo
            print >> me.fo, "1;"
            print >> me.fo
        super(a_pl_filer, me).write_trailer()
    pass    # a_pl_filer



class   a_sh_filer(a_hash_filer) :
    def __init__(me, *args, **kwargs) :
        kwargs['shebang']   = kwargs.get('shebang', "#!/bin/bash")
        super(a_sh_filer, me).__init__(*args, **kwargs)
    pass    # a_sh_filer



class   a_file(file) :
    def __init__(me, file_name, ext = None, mode = None, **kwargs) :

        drc         = os.path.split(file_name)[0]
        if  drc and (not os.path.isdir(drc)) :
            os.makedirs(drc)


        if  ext :
            if ext[0] != '.' :
               ext  = "." + ext
        else :
            ext     = os.path.splitext(file_name)[1]

        if  ext in  {
                        ".c"    : 1,
                        ".h"    : 1,
                        ".cpp"  : 1,
                        ".hpp"  : 1,
                        ".hmd"  : 1,
                    } :
            fl      = a_c_filer(    file_name, me)
        elif ext in  {
                        ".java" : 1,
                        ".js"   : 1,
                        ".json" : 1,
                        ".cs"   : 1,
                    } :
            fl      = a_c_like_filer(file_name, me)
        elif ext in {
                        ".htm"  : 1,
                        ".html" : 1,
                    } :
            fl      = an_htm_filer( file_name, me)
        elif ext in {
                        ".py"   : 1,
                    } :
            fl      = a_py_filer(   file_name, me, **kwargs)
        elif ext in {
                        ".pl"   : 1,
                        ".pm"   : 1,
                    } :
            fl      = a_pl_filer(   file_name, me, **kwargs)
        elif ext in {
                        ".sh"   : 1,
                    } :
            fl      = a_sh_filer(   file_name, me, **kwargs)
        else :
            fl      = a_filer(      file_name, me)

        tfile_name  = file_name + ".tmp"

        mode        = mode or fl.get_write_mode()

        super(a_file, me).__init__(tfile_name, "w" + mode)

        me.tfile_name   = tfile_name
        me.filer        = fl

        me.filer.write_header()



    def close(me) :
        me.filer.write_trailer()

        rv  = super(a_file, me).close()

        replace_file.replace_file(me.filer.file_name, me.tfile_name, me.filer.file_name + ".bak")

        return(rv)


    pass    # a_file



#
#
#       Test
#
#
if __name__ == '__main__' :

    import  sys

    import  TZCommandLineAtFile


    program_name    = sys.argv.pop(0)
    TZCommandLineAtFile.expand_at_sign_command_line_files(sys.argv)

    for fn in sys.argv :
        f   = a_file(fn)
        f.write("Now is the time for all good men!")
        f.close()

    pass

#
#
#
# eof

