# Copyright (c) 2011 Dave McCoy (dave.mccoy@cospandesign.com)
#
# This file is part of Nysa.
#
#       (http://wiki.cospandesign.com/index.php?title=Nysa.org)
#
# Nysa is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# any later version.
#
# Nysa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Nysa; If not, see <http://www.gnu.org/licenses/>.

# -*- coding: utf-8 -*-

"""Module Factory

Generates verilog modules. The generation of a verilog module may by simply
copying the module or generating the module with a script or a combination
of the two
"""

__author__ = 'dave.mccoy@cospandesign.com (Dave McCoy)'

"""Changes:
06/11/2012
    -Added Documentation and licsense
    -Moved two functions from sapfile to utils
      is_module_in_file
      find_module_filename
09/18/2013
    -Changed license to GPL V3
"""


import os
import glob
import sys
import importlib

from inspect import isclass
from ibuilder_error import ModuleNotFound
from ibuilder_error import ModuleFactoryError
import utils

sys.path.append(os.path.join( os.path.dirname(__file__),
                              "gen_scripts"))

sys.path.append(os.path.join( os.path.dirname(__file__),
                              os.pardir,
                              os.pardir,
                              "cbuilder",
                              "scripts"))

from gen_scripts import gen



class ModuleProcessor:
  """Generates a module

  Based on the script template the modules may be created with a gen script
  or simply copying a file
  """

  def __init__ (self, user_paths = []):
#    print "SAPLIB_BASE: " + os.environ["SAPLIB_BASE"]
#    print "Path: " + str(sys.path)
    self.user_paths = list(set(user_paths))
    self.gen_module = None
    self.gen = None
    self.buf = ""
    self.tags = {}
    self.verilog_file_list = []
    self.verilog_dependency_list = []
    return

  def write_file(self, location = "", filename=""):
    """write_file

    Search through the specified location, if the location doesn't exist then
    create the location.
    then write out the specified file

    Args:
      location: the location where the file is to be written
      filename: the name of the output file to write

    Returns:
      Nothing

    Raises:
      IOError
    """
    home = False
    location = utils.resolve_path(location)
    if not os.path.exists(location):
       utils.create_dir(location)
    fname = os.path.join(location, filename)
    fileout = open(fname, "w")
    fileout.write(self.buf)
    fileout.close()
    return

  def apply_tags(self):
    """apply_tags

    Substitutes that tags with the data specific to this project

    Args:
      None

    Return:
      Nothing

    Raises:
      KeyError
    """
    #search through the buf for any tags that match something within
    #our tag map
    try:
      self.buf = self.buf.format(self.tags)
    except KeyError as err:
      if ('$' in err):
        raise KeyError(str(err))
    except ValueError as err:
      print "Value Error with the Buffer (shown below): %s" % str(err)
      print "Tags:"
      for t in self.tags:
        print "\t%s: %s" % (t, str(self.tags[t]))
      print "Buffer: %s" % self.buf
    return

  def set_tags(self, tags={}):
    """set_tags

    set the tags for this module

    Args:
      tags: project specific tags

    Return:
      Nothing

    Raises:
      Nothing
    """
    self.tags = tags
    return

  def process_file(self, filename, file_dict, directory="", debug=False):
    """process_file

    read in a file, modify it (if necessary), then write it to the location
    specified by the directory variable

    Args:
      filename: the name of the file to process
      file_dict: dictionary associated with this file
      directory: output directory

    Return:

    Raises:
      ModuleFactoryError
      IOError

    """
    verbose = False
    debug = False
    if (filename.endswith(".v")):
        self.verilog_file_list.append(filename)

    if debug:
        print "in process file"
        print "\t%s" % filename
    #maybe load a tags??

    #using the location value in the file_dict find the file and
    #pull it into a buf

    self.buf = ""
    file_location = ""
    paths = self.user_paths


    #There are two types of files
    #ones that are copied over from a location
    #ones that are generated by scripts

    #The file is specified by a location and basically needs to be copied over
    if file_dict.has_key("location"):
        #print "Location: %s" % file_dict["location"]
        #file_location = os.path.join( utils.nysa_base,
        loc = file_dict["location"].split("/")
        #print "Loc list: %s" % str(loc)
        if loc[0] == "${NYSA}":
            loc[0]  = utils.nysa_base