#
import csv
import logging
import re
import sys
import os.path
import utilities
from tbl2dml_new import *

rc_index = 1
multireg_logger = logging.getLogger('multireg_logger')


@utilities.traceFunc('multireg')
def output(header, chunk, num, offset, each_gap, csv_writer):
    global rc_index
    for line in header:
        csv_writer.writerow(line)
    for i in range(num):
        for line in chunk:
            # print line
            calc_offset = int(offset, 16) + i * int(each_gap, 16) + int(line[3], 16)
            line[0] = str(rc_index)
            tmp_line1 = line[1]
            tmp_line3 = line[3]
            line[1] = line[1]# + '_%04x' % i
            line[3] = hex(calc_offset)
            csv_writer.writerow(line)
            line[1] = tmp_line1
            line[3] = tmp_line3
            rc_index = rc_index + 1


@utilities.traceFunc('multireg')
def mkdml(tablist, devname, devpath, off):
    pcon = []
    fpga = devname.replace('t_', '').replace('.dml', '')
    pcon.append("""
# This file is automatically generated by the tbl2dml.py script.
# Please consider regenerating it from the .csv file instead of
# manually changing.
    """)
    pcon.append('def %s_tbl(%s):'%(fpga,fpga))
    pcon.append('    tbl = []')

    dmlcon = []
    banklist = []
    dmlcon.append("""
/* This file is automatically generated by the tbl2dml.py script.
 * Please consider regenerating it from the .csv file instead of
 * manually changing.
 */

dml 1.2;
""")
    #r = re.compile("TBL_.*")
    try:
        with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), './output/dml/') + devname, 'w') as dmlfile:
            gap = lambda x,y: x if x != 0 else y
            for item in tablist:
                l_off = int(item[0],16)-int(off,16)
                has_file = 0
                for file in os.listdir(devpath):
                    if (file.find(item[2]) != -1) and ((file.replace(item[2],'')[0].isdigit()) or (file.replace(item[2],'')[0] == '.')):
                        has_file += 1
                        (tblsize, regsize) = main(os.path.join(devpath, file), dmlcon, l_off, True,  "parser10", 3, int(item[4]), int(item[1], 16))
                        dmlfile.writelines(item+'\n' for item in dmlcon)
                        multireg_logger.debug('write file %s', str(dmlfile))
                        dmlcon = []
                        banklist.append(hex(l_off))
                        pcon.append('    tbl.append([%s, [%s, \'r_0x%08x\'], 0, 0, %#x, None, 0, %d])'%(hex(l_off), fpga, l_off, gap(int(item[1],16),tblsize)*int(item[4]), regsize))
                    else:
                        continue
                if has_file != 1:
                    multireg_logger.error('file: %s, counter: %d ', file, has_file)
                    sys.exit(1)
            # add post_init() to handle PON values for the device.
            dmlcon.append("""
/* Provide a default post_init_extra() so it compiles
* without requiring the specific devices to implement it.
*/
method post_init_extra() default { }

method post_init() {
    call $post_init_extra;
    log "info", 2: "post_init called.";
    /* Only call do_PON on object creation. For all other occasions
     * do_hreset/do_sreset should be called.
     */
    if (!SIM_object_is_configured($obj) && !SIM_is_restoring_state($obj)) {
        log "info", 2: "post_init calling do_PON.";""")
            dmlcon.append('        call $do_PON;')
            dmlcon.append('        call $do_PON_extra;')
            dmlcon.append("""    }\n}\nparameter overlapping = true;\n""")

            dmlcon.append("""method do_PON() {""")
            for add in banklist:
                dmlcon.append('            call $r_0x%08x_do_PON;'%int(add, 16))
            dmlcon.append("""\n}\n""")

            #dmlcon.append("""method do_PON_extra() {""")
            #for add in banklist:
            #    dmlcon.append('            call $r_0x%08x_do_PON_extra;'%int(add, 16))
            #dmlcon.append("""\n}\n""")
            dmlfile.writelines(item+'\n' for item in dmlcon)
                    
            pcon.append('    return tbl')
            with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), ('./output/py/t_' + fpga + '.py')), 'w') as pyfile:
                pyfile.writelines(item+'\n' for item in pcon)
                multireg_logger.debug('write file %s', str(pyfile))
    except Exception as err:
         multireg_logger.error('mkdml with: %s', str(err))


@utilities.traceFunc('multireg')
def each_file(file, offset, each_gap, num, csv_writer, hdrflg):
    try:
        with  open(file, 'r') as each_csv:
            each_reader = csv.reader(each_csv)
            hdrcnt = 0
            header = []
            chunk = []

            for row in each_reader:
                if row and hdrcnt < 2 and hdrflg:
                    header.append(row)
                    hdrcnt = hdrcnt + 1
                else:
                    pattern = re.compile(r'^[0-9]')
                    matobj = pattern.search(row[0])
                    if matobj:
                        chunk.append(row)
            output(header, chunk, num, offset, each_gap, csv_writer)
    except Exception as err:
        multireg_logger.error('each file %s error', file)
        sys.exit(1)


@utilities.traceFunc('multireg')
def create_map_list(fpga_path):
    map_list = []
    try:
        #        cur = os.getcwd()
        for files in os.listdir(fpga_path):
            if files.find('MEMORY_MAP') != -1:
                map_list.append(files)
        multireg_logger.debug("map_list: %s", map_list)
        return map_list
    except Exception as err:
        multireg_logger.error('dir %s error', fpga_path)
        sys.exit(1)


@utilities.traceFunc('multireg')
def create_fpga(mapfile, dmlfile, off):
    devname = ''
    global rc_index
    local_path = os.path.dirname(os.path.abspath(mapfile))
    try:
        with open(mapfile) as fpgafile:
            for row in csv.reader(fpgafile):
                if row[3].find('Device name:') != -1:
                    rc_index = 1
                    devname = row[3].split(':')[1]
                    if row[4].find('32bit') == -1:
                        multireg_logger.info('register size: %s', row[4].split(':')[1])
                    break
                else:
                    multireg_logger.info('row: %s not has Device name:', row)

            hdrflg = True
            tables = []
            for row in csv.reader(fpgafile):
                if row[0][0:2] == '0x':
                    tables.append(row)
                else:
                    multireg_logger.debug('row %s is not start with 0x', row)
                mkdml(tables, dmlfile, local_path, off)
    except Exception as err:
        multireg_logger.error('dir %s error with %s', mapfile, str(err))
        sys.exit(1)


@utilities.traceFunc('multireg')
def create_all(conf):
    try:
        with open(conf) as fp:
            line = fp.readline()
            while line:
                map_list = create_map_list(line.replace('\n', ''))
                for fpga in map_list:
                    multireg_logger.debug('create fpga csv: %s', fpga)
                    create_fpga(line.replace('\n', ''), fpga)
                line = fp.readline()
    except Exception as err:
        multireg_logger.error('file %s error', conf)
        sys.exit(1)


if __name__ == "__main__":
    v_offset = "0x0"
    if len(sys.argv) > 2:
        if sys.argv[1] == '-h' or sys.argv[1] == '--h' or sys.argv[1] == 'help':
            print "Usage: multireg map_file_name dml_file_name [offset]."
        elif len(sys.argv) > 3:
            v_offset = sys.argv[3]
        multireg_logger.debug('file list: %s', sys.argv[1])
        create_fpga(sys.argv[1], sys.argv[2], v_offset)
    else:
        multireg_logger.debug('Input the map_file dml_file.')
