# Copyright (C) 2013-2015 MetaMorph Software, Inc

# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this data, including any software or models in source or binary
# form, as well as any drawings, specifications, and documentation
# (collectively "the Data"), to deal in the Data without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Data, and to
# permit persons to whom the Data is furnished to do so, subject to the
# following conditions:

# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Data.

# THE DATA IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS, SPONSORS, DEVELOPERS, CONTRIBUTORS, OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE DATA OR THE USE OR OTHER DEALINGS IN THE DATA.  

# =======================
# This version of the META tools is a fork of an original version produced
# by Vanderbilt University's Institute for Software Integrated Systems (ISIS).
# Their license statement:

# Copyright (C) 2011-2014 Vanderbilt University

# Developed with the sponsorship of the Defense Advanced Research Projects
# Agency (DARPA) and delivered to the U.S. Government with Unlimited Rights
# as defined in DFARS 252.227-7013.

# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this data, including any software or models in source or binary
# form, as well as any drawings, specifications, and documentation
# (collectively "the Data"), to deal in the Data without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Data, and to
# permit persons to whom the Data is furnished to do so, subject to the
# following conditions:

# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Data.

# THE DATA IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS, SPONSORS, DEVELOPERS, CONTRIBUTORS, OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE DATA OR THE USE OR OTHER DEALINGS IN THE DATA.  

import os
import time
import shutil
import datetime
import logging
import subprocess
from py_modelica.modelica_simulation_tools.tool_base import ToolBase
from py_modelica.modelica_simulation_tools.openmodelica_element_tree import OpenModelicaElementTree
from py_modelica.utility_functions import subprocess_call
from py_modelica.exception_classes import ModelicaInstantiationError, ModelicaCompilationError,\
    ModelicaSimulationError


class OpenModelica(ToolBase):

    tool_name = "OpenModelica"
    model_statistics = {}
    compile_errors = []
    om_home = ""
    om_etree = None      # OpenModelicaElementTree for parsing .xml files
    short_name = ""

    def __init__(self, model_config, om_home=""):
        """
        Constructor for OpenModelica class, called before ToolBase's
        _initialize.

        This method only makes sure that there is a environment
        OPENMODELICAHOME defined.

        """
        if not om_home:
            self.om_home = os.getenv("OPENMODELICAHOME")
            if self.om_home:
                if os.path.exists(self.om_home):
                    self.tool_path = os.path.join(self.om_home, "bin")
                else:
                    msg = "OpenModelica path not found at env: {0}".format(self.om_home)
                    raise ModelicaInstantiationError(msg)
            else:
                if os.name == "nt":
                    msg = "No environment variable OPENMODELICAHOME defined."
                    raise ModelicaInstantiationError(msg)
        elif os.path.exists(om_home):
            self.om_home = om_home
            self.tool_path = os.path.join(self.om_home, "bin")
        else:
            msg = "Given OpenModelica home not found at: {0}".format(om_home)
            raise ModelicaInstantiationError(msg)
        self._initialize(model_config)
    # end of _set_tool_home

    def _write_mos_script(self, log):
        """
        Writes out .mos-script for translation of the modelica model

        """

        log.debug("Entered _write_mos_script")

        with open(self.mos_file_name, 'wb') as file_out:
            lines = ['// OpenModelica script file to run a model']
            lines.append('loadModel(Modelica, {"' + self.msl_version + '"});')
            for lib_name in self.lib_package_names:
                lines.append('loadModel({0});'.format(lib_name))
            if self.model_file_name != "":
                lines.append('cd("{0}");'.format(self.mo_dir.replace("\\", "/")))
                lines.append('loadFile("{0}");'.format(os.path.basename(self.model_file_name)))

            translate = 'translateModel(' + self.model_name
            #if self.variable_filter:
            #    translate += ', variable_filter=['
            #    for var in self.variable_filter:
            #        translate += var
            #    translate += ']'
            translate += ', fileNamePrefix="{0}"'.format(self.short_name)
            translate += ');'
            lines.append(translate)
            lines.append('getErrorString();')
            file_out.write("\n".join(lines))
            log.debug("Generated .mos-script at : {0}".format(self.mos_file_name))
    # end of _write_mos_script

    def _setup_libs_env_vars(self, log):
        """
        Function adds given library paths to environment-variable OPENMODELICALIBRARY.
        Which is updated in os.environ and returned.

        If path does not exist on hard-drive it looks for it at; /working_dir/Modelica
        (This is where the packages are put during remote execution.)

        """

        log.debug('Entered _setup_libs_env_vars')

        my_env = os.environ