import os
import logging

from edalize.edatool import Edatool

logger = logging.getLogger(__name__)

class Xsim(Edatool):

    tool_options = {'lists' : {'xelab_options' : 'String',
                               'xsim_options'  : 'String'}}

    argtypes = ['plusarg', 'vlogdefine', 'vlogparam']

    MAKEFILE_TEMPLATE="""#Auto generated by Edalize
include config.mk

all: xsim.dir/$(TARGET)/xsimk

xsim.dir/$(TARGET)/xsimk:
	xelab $(TOPLEVEL) -prj $(TARGET).prj -snapshot $(TARGET) $(VLOG_DEFINES) $(VLOG_INCLUDES) $(VLOG_PARAMS) $(XELAB_OPTIONS)

run: xsim.dir/$(TARGET)/xsimk
	xsim --tclbatch run.tcl $(XSIM_OPTIONS) $(TARGET) $(EXTRA_OPTIONS)

run-gui: xsim.dir/$(TARGET)/xsimk
	xsim --gui --tclbatch run-gui.tcl $(XSIM_OPTIONS) $(TARGET) $(EXTRA_OPTIONS)
"""

    CONFIG_MK_TEMPLATE = """#Auto generated by Edalize
TARGET        = {target}
TOPLEVEL      = {toplevel}

VLOG_DEFINES  = {vlog_defines}
VLOG_INCLUDES = {vlog_includes}
VLOG_PARAMS   = {vlog_params}

XELAB_OPTIONS =	{xelab_options}
XSIM_OPTIONS  = {xsim_options}
"""

    RUN_TCL_TEMPLATE = """#Auto generated by Edalize
run all
quit
"""

    RUN_GUI_TCL_TEMPLATE = """#Auto generated by Edalize
add_wave -radix hex /
run all
"""

    def configure_main(self):
        self._write_config_files()

        #Check if any VPI modules are present and display warning
        if len(self.vpi_modules) > 0:
            modules = [m['name'] for m in self.vpi_modules]
            logger.error('VPI modules not supported by Xsim: %s' % ', '.join(modules))

    def _write_config_files(self):
        with open(os.path.join(self.work_root, self.name+'.prj'),'w') as f:
            (src_files, self.incdirs) = self._get_fileset_files()
            for src_file in src_files:
                cmd = ""
                if src_file.file_type.startswith("verilogSource"):
                    cmd = 'verilog'
                elif src_file.file_type == 'vhdlSource-2008':
                    cmd = 'vhdl2008'
                elif src_file.file_type.startswith("vhdlSource"):
                    cmd = 'vhdl'
                elif src_file.file_type.startswith("systemVerilogSource"):
                    cmd = 'sv'
                elif src_file.file_type in ["user"]:
                    pass
                else:
                    _s = "{} has unknown file type '{}'"
                    logger.warning(_s.format(src_file.name, src_file.file_type))
                if cmd:
                    if src_file.logical_name:
                        lib = src_file.logical_name
                    else:
                        lib = 'work'
                    f.write('{} {} {}\n'.format(cmd, lib, src_file.name))

        with open(os.path.join(self.work_root, 'config.mk'), 'w') as f:
            vlog_defines  = ' '.join(['--define {}={}'.format(k,v) for k,v, in self.vlogdefine.items()])
            vlog_includes = ' '.join(['-i '+k for k in self.incdirs])
            vlog_params   = ' '.join(['--generic_top {}={}'.format(k, self._param_value_str(v)) for k,v, in self.vlogparam.items()])
            xelab_options = ' '.join(self.tool_options.get('xelab_options', []))
            xsim_options  = ' '.join(self.tool_options.get('xsim_options' , []))

            f.write(self.CONFIG_MK_TEMPLATE.format(target=self.name,
                                                   toplevel=self.toplevel,
                                                   vlog_defines = vlog_defines,
                                                   vlog_includes = vlog_includes,
                                                   vlog_params   = vlog_params,
                                                   xelab_options = xelab_options,
                                                   xsim_options  = xsim_options))

        with open(os.path.join(self.work_root, 'run.tcl'), 'w') as f:
            f.write(self.RUN_TCL_TEMPLATE)
        with open(os.path.join(self.work_root, 'run-gui.tcl'), 'w') as f:
            f.write(self.RUN_GUI_TCL_TEMPLATE)
        with open(os.path.join(self.work_root, 'Makefile'), 'w') as f:
            f.write(self.MAKEFILE_TEMPLATE)

    def run_main(self):
        args = ['run']
        # Plusargs
        if self.plusarg:
            _s = '--testplusarg {}={}'
            args.append('EXTRA_OPTIONS='+' '.join([_s.format(k, v) for k,v in self.plusarg.items()]))

        self._run_tool('make', args)
