/*
 Copyright 2019 Alain Dargelas

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

/*
 * File:   PythonAPI.cpp
 * Author: alain
 *
 * Created on May 13, 2017, 4:42 PM
 */

#include "SourceCompile/SymbolTable.h"
#include "Utils/StringUtils.h"
#include "Utils/FileUtils.h"
#include "CommandLine/CommandLineParser.hpp"
#include "ErrorReporting/ErrorContainer.h"
#include "SourceCompile/CompilationUnit.h"
#include "SourceCompile/PreprocessFile.h"
#include "SourceCompile/CompileSourceFile.h"
#include "SourceCompile/Compiler.h"
#include "SourceCompile/ParseFile.h"
#include "antlr4-runtime.h"
using namespace std;
using namespace antlr4;

#include "parser/SV3_1aParserBaseListener.h"

#include "API/SV3_1aPythonListener.h"

using namespace SURELOG;

#include <sstream>
#include <string>
#include <fstream>
#include <iostream>
#include <cstdio>
#include "Python.h"
#include "API/PythonAPI.h"
#include "API/SLAPI.h"
#include "API/slapi_wrap.cxx"
#include "API/slapi.h"
#include "API/vobjecttypes_py.h"
#include <cstdlib>
#include "SourceCompile/PythonListen.h"

std::string PythonAPI::m_invalidScriptResult = "INVALID_PYTHON_SCRIPT_RESULT";

PyThreadState* PythonAPI::m_mainThreadState = NULL;

std::string PythonAPI::m_programPath = "";

bool PythonAPI::m_listenerLoaded = false;

std::string PythonAPI::m_listenerScript;

bool PythonAPI::m_strictMode = false;

std::string PythonAPI::m_builtinPath;

PythonAPI::PythonAPI() {}

PythonAPI::PythonAPI(const PythonAPI& orig) {}

PythonAPI::~PythonAPI() {}

static struct PyModuleDef SLAPI_module = {PyModuleDef_HEAD_INIT,
                                          "slapi",
                                          NULL,
                                          -1,
                                          SwigMethods,
                                          NULL,
                                          NULL,
                                          NULL,
                                          NULL};

static PyObject* PyInit_slapi(void) { return PyModule_Create(&SLAPI_module); }

void PythonAPI::shutdown() {
  PyEval_RestoreThread(m_mainThreadState);
  Py_Finalize();
}

bool PythonAPI::loadScript(std::string name, bool check) {
  PyEval_AcquireThread(m_mainThreadState);
  bool status = loadScript_(name, check);
  PyEval_ReleaseThread(m_mainThreadState);
  return status;
}

bool PythonAPI::loadScript_(std::string name, bool check) {
  if (FileUtils::fileExists(name)) {
    FILE* fp = fopen(name.c_str(), "r");
    PyRun_SimpleFile(fp, name.c_str());
    PyErr_Print();
    fclose(fp);
    return true;
  } else {
    if (check)
      std::cout << "PYTHON API ERROR: Script \"" << name
                << "\" does not exist.\n";
  }
  return false;
}

PyThreadState* PythonAPI::initNewInterp() {
  PyEval_AcquireThread(m_mainThreadState);
  PyThreadState* interpState = Py_NewInterpreter();

  loadScriptsInInterp_();
  // PyEval_ReleaseThread(m_mainThreadState);

  PyEval_ReleaseThread(interpState);
  return interpState;
}

void PythonAPI::shutdown(PyThreadState* interp) {
  if (interp != m_mainThreadState) {
    PyEval_AcquireThread(interp);
    Py_EndInterpreter(interp);
    PyEval_ReleaseLock();
  }
}

void PythonAPI::loadScriptsInInterp_() {
  // Loads the python SWIG generated defs
  std::string script;
  for (auto s : slapi_scripts) {
    script += s;
  }
  for (auto s : slapi_types) {
    script += s;
  }
  PyRun_SimpleString(script.c_str());

  PyRun_SimpleString("import sys");
  PyRun_SimpleString("sys.path.append(\".\")");
  PyRun_SimpleString(
      std::string("sys.path.append(\"" + m_programPath + "\")").c_str());

  std::string waivers = m_programPath + "/python/slwaivers.py";
  bool waiverLoaded = loadScript_(waivers);
  waivers =  "/usr/lib/surelog/slwaivers.py";
  waiverLoaded = loadScript_(waivers) || waiverLoaded;
  waivers =  "/usr/local/lib/surelog/slwaivers.py";
  waiverLoaded = loadScript_(waivers) || waiverLoaded;
  waivers = "./slwaivers.py";
  waiverLoaded = loadScript_(waivers) || waiverLoaded;

  std::string format = m_programPath + "/python/slformatmsg.py";
  bool messageFormatLoaded = loadScript_(format);
  format = "/usr/lib/surelog/slformatmsg.py";
  messageFormatLoaded = loadScript_(format) || messageFormatLoaded;
  format = "/usr/local/lib/surelog/slformatmsg.py";
  messageFormatLoaded = loadScript_(format) || messageFormatLoaded;
  format = "./slformatmsg.py";
  messageFormatLoaded = loadScript_(format) || messageFormatLoaded;

  if (m_listenerScript != "") {
    if (FileUtils::fileExists(m_listenerScript)) {
      m_listenerLoaded = loadScript_(m_listenerScript);
    }
  }

  if (!m_listenerLoaded) {
    std::string listener =
        m_programPath + "/python/slSV3_1aPythonListener.py";
    if (FileUtils::fileExists(listener)) m_listenerScript = listener;
    m_listenerLoaded = loadScript_(listener);

    listener = "/usr/lib/surelog/slSV3_1aPythonListener.py";
    if (FileUtils::fileExists(listener)) m_listenerScript = listener;
    m_listenerLoaded = loadScript_(listener) || m_listenerLoaded;
    listener = "/usr/local/lib/surelog/slSV3_1aPythonListener.py";
    if (FileUtils::fileExists(listener)) m_listenerScript = listener;
    m_listenerLoaded = loadScript_(listener) || m_listenerLoaded;
    listener = "./slSV3_1aPythonListener.py";
    if (FileUtils::fileExists(listener)) m_listenerScript = listener;
    m_listenerLoaded = loadScript_(listener) || m_listenerLoaded;
  }
}

void PythonAPI::init(int argc, const char** argv) {
  m_programPath = argv[0];
  m_programPath = StringUtils::rtrim(m_programPath, '/');
  for (int i = 1; i < argc; i++) {
      if (!strcmp(argv[i], "-builtin")) {
          if (i < argc - 1) {
            m_builtinPath = argv[i + 1];
          }
      }
  }
  Py_SetProgramName((wchar_t*)argv[0]); /* optional but recommended */

  PyImport_AppendInittab("slapi", &PyInit_slapi);

  Py_Initialize();
  PyEval_InitThreads();
  m_mainThreadState = PyEval_SaveThread();
  PyEval_AcquireThread(m_mainThreadState);

  loadScriptsInInterp_();

  PyEval_ReleaseThread(m_mainThreadState);
}

void PythonAPI::evalScript(std::string function, SV3_1aPythonListener* listener,
                           ParserRuleContext* ctx) {
  PyEval_AcquireThread(listener->getPyThreadState());
  PyObject *pModuleName, *pModule, *pFunc;
  PyObject *pArgs, *pValue;
  pModuleName = PyString_FromString("__main__");
  pModule = PyImport_Import(pModuleName);
  Py_DECREF(pModuleName);
  pFunc = PyObject_GetAttrString(pModule, function.c_str());
  if (!pFunc || !PyCallable_Check(pFunc)) {
    if (m_strictMode)
      std::cout << "PYTHON API ERROR: Function \"" << function
                << "\" does not exist.\n";
    PyEval_ReleaseThread(listener->getPyThreadState());
    return;
  }
  pArgs = PyTuple_New(2);
  pValue = SWIG_NewPointerObj(SWIG_as_voidptr(listener),
                              SWIGTYPE_p_SURELOG__SV3_1aPythonListener, 0 | 0);
  PyTuple_SetItem(pArgs, 0, pValue);
  pValue = SWIG_NewPointerObj(SWIG_as_voidptr(ctx),
                              SWIGTYPE_p_ParserRuleContext, 0 | 0);
  PyTuple_SetItem(pArgs, 1, pValue);
  PyObject_CallObject(pFunc, pArgs);
  PyErr_Print();
  Py_DECREF(pArgs);
  Py_XDECREF(pFunc);
  Py_DECREF(pModule);
  PyEval_ReleaseThread(listener->getPyThreadState());
}

std::string PythonAPI::evalScript(std::string module, std::string function,
                                  std::vector<std::string> args,
                                  PyThreadState* interp) {
  PyEval_AcquireThread(interp);

  std::string result;
  PyObject *pModuleName, *pModule, *pFunc;
  PyObject *pArgs, *pValue;

  pModuleName = PyString_FromString(module.c_str());
  pModule = PyImport_Import(pModuleName);

  Py_DECREF(pModuleName);
  if (pModule != NULL) {
    pFunc = PyObject_GetAttrString(pModule, function.c_str());
    /* pFunc is a new reference */

    if (pFunc && PyCallable_Check(pFunc)) {
      pArgs = PyTuple_New(args.size());
      for (unsigned int i = 0; i < args.size(); ++i) {
        pValue = PyString_FromString(args[i].c_str());
        /* pValue reference stolen here: */
        PyTuple_SetItem(pArgs, i, pValue);
      }
      pValue = PyObject_CallObject(pFunc, pArgs);
      Py_DECREF(pArgs);
      if (pValue != NULL) {
        long int size;
        const char* compName = PyUnicode_AsUTF8AndSize(pValue, &size);
        if (compName == NULL) {
          std::cout << "PYTHON API ERROR: Incorrect function return type, "
                       "expecting a string: "
                    << function << std::endl;
          Py_DECREF(pValue);

          PyEval_ReleaseThread(interp);
          return m_invalidScriptResult;
        }
        result = compName;
        Py_DECREF(pValue);
      } else {
        Py_DECREF(pFunc);
        Py_DECREF(pModule);
        PyErr_Print();
        std::cout << "PYTHON API ERROR: Incorrect function evaluation: "
                  << function << std::endl;
        PyEval_ReleaseThread(interp);
        return m_invalidScriptResult;
      }
    } else {
      if (PyErr_Occurred()) PyErr_Print();
      std::cout << "PYTHON API ERROR: Cannot find function " << function
                << std::endl;

      PyEval_ReleaseThread(interp);
      return m_invalidScriptResult;
    }
    Py_XDECREF(pFunc);
    Py_DECREF(pModule);
  } else {
    PyErr_Print();
    std::cout << "PYTHON API ERROR: Cannot load module " << module << std::endl;
    return m_invalidScriptResult;
  }

  PyEval_ReleaseThread(interp);
  return result;
}

bool PythonAPI::evalScriptPerFile(std::string script, ErrorContainer* errors,
                                  FileContent* fC, PyThreadState* interp) {
  PyEval_AcquireThread(interp);
  loadScript_(script);
  std::string function = "slUserCallbackPerFile";
  PyObject *pModuleName, *pModule, *pFunc;
  PyObject *pArgs, *pValue;
  pModuleName = PyString_FromString("__main__");
  pModule = PyImport_Import(pModuleName);
  Py_DECREF(pModuleName);
  pFunc = PyObject_GetAttrString(pModule, function.c_str());
  if (!pFunc || !PyCallable_Check(pFunc)) {
    std::cout << "PYTHON API ERROR: Function \"" << function
              << "\" does not exist.\n";
    PyEval_ReleaseThread(interp);
    return false;
  }
  pArgs = PyTuple_New(2);
  pValue = SWIG_NewPointerObj(SWIG_as_voidptr(errors),
                              SWIGTYPE_p_SURELOG__ErrorContainer, 0 | 0);
  PyTuple_SetItem(pArgs, 0, pValue);
  pValue = SWIG_NewPointerObj(SWIG_as_voidptr(fC),
                              SWIGTYPE_p_SURELOG__FileContent, 0 | 0);
  PyTuple_SetItem(pArgs, 1, pValue);

  PyObject_CallObject(pFunc, pArgs);
  PyErr_Print();
  Py_DECREF(pArgs);
  Py_XDECREF(pFunc);
  Py_DECREF(pModule);

  PyEval_ReleaseThread(interp);
  return true;
}

bool PythonAPI::evalScript(std::string script, Design* design) {
  PyEval_AcquireThread(m_mainThreadState);
  loadScript_(script);
  std::string function = "slUserCallbackPerDesign";
  PyObject *pModuleName, *pModule, *pFunc;
  PyObject *pArgs, *pValue;
  pModuleName = PyString_FromString("__main__");
  pModule = PyImport_Import(pModuleName);
  Py_DECREF(pModuleName);
  pFunc = PyObject_GetAttrString(pModule, function.c_str());
  if (!pFunc || !PyCallable_Check(pFunc)) {
    std::cout << "PYTHON API ERROR: Function \"" << function
              << "\" does not exist.\n";
    PyEval_ReleaseThread(m_mainThreadState);
    return false;
  }
  pArgs = PyTuple_New(2);
  pValue = SWIG_NewPointerObj(
      SWIG_as_voidptr(design->getCompiler()->getErrorContainer()),
      SWIGTYPE_p_SURELOG__ErrorContainer, 0 | 0);
  PyTuple_SetItem(pArgs, 0, pValue);
  pValue = SWIG_NewPointerObj(SWIG_as_voidptr(design),
                              SWIGTYPE_p_SURELOG__Design, 0 | 0);
  PyTuple_SetItem(pArgs, 1, pValue);
  PyObject_CallObject(pFunc, pArgs);
  PyErr_Print();
  Py_DECREF(pArgs);
  Py_XDECREF(pFunc);
  Py_DECREF(pModule);

  PyEval_ReleaseThread(m_mainThreadState);
  return true;
}
