/*=========================================================================

  Program:   ParaView
  Module:    $RCSfile$

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#ifndef __vtkProcessModulePythonInitializePython_h
#define __vtkProcessModulePythonInitializePython_h

#include "vtkPythonInterpreter.h"
#include <string>
#include <vtksys/SystemTools.hxx>
#include "vtkPVConfig.h" //  needed for PARAVIEW_FREEZE_PYTHON

/* The maximum length of a file name.  */
#if defined(PATH_MAX)
# define VTK_PYTHON_MAXPATH PATH_MAX
#elif defined(MAXPATHLEN)
# define VTK_PYTHON_MAXPATH MAXPATHLEN
#else
# define VTK_PYTHON_MAXPATH 16384
#endif
namespace
{
  // ParaView should setup Python Path to find the modules in the following
  // locations for various platforms. There are always two cases to handle: when
  // running from build-location and when running from installed-location.

  //----------------------------------------------------------------------------
  void vtkPythonAppInitPrependPythonPath(const std::string& dir)
    {
    if (dir != "")
      {
      std::string collapsed_dir =
        vtksys::SystemTools::CollapseFullPath(dir.c_str());
      if (vtksys::SystemTools::FileIsDirectory(collapsed_dir.c_str()))
        {
        vtkPythonInterpreter::PrependPythonPath(collapsed_dir.c_str());
        }
      }
    }

  //===========================================================================
  // Linux/UNIX (not OsX)
  // Key:
  //    - SELF_DIR: directory containing the pvserver/pvpython/paraview
  //      executables. For installed locations, this corresponds to the "real"
  //      executable, not the shared-forwarded executable (if applicable).
  //---------------------------------------------------------------------------
  // + BUILD_LOCATION
  //    + ParaView C/C++ library location
  //      - SELF_DIR/../lib
  //    + ParaView Python modules
  //      - SELF_DIR/../lib/site-packages
  //  + INSTALL_LOCATION
  //    + ParaView C/C++ library location
  //      - SELF_DIR
  //    + ParaView Python modules
  //      - SELF_DIR/site-packages
  //    + VTK Python Module libraries
  //      - SELF_DIR/site-packages/vtk
  void vtkPythonAppInitPrependPathLinux(const std::string& SELF_DIR)
    {
    // Determine if running from build or install dir.
    //    If SELF_DIR/site-packages exists, it must be running from an installed
    //    location.
    bool is_build_dir = vtksys::SystemTools::FileExists(
      (SELF_DIR + "/site-packages").c_str()) == false;
    if (is_build_dir)
      {
      vtkPythonAppInitPrependPythonPath(SELF_DIR + "/../lib");
      vtkPythonAppInitPrependPythonPath(SELF_DIR + "/../lib/site-packages");
      }
    else
      {
      vtkPythonAppInitPrependPythonPath(SELF_DIR);
      vtkPythonAppInitPrependPythonPath(SELF_DIR + "/site-packages");
      // site-packages/vtk needs to be added so the Python wrapped VTK modules
      // can be loaded from paraview e.g. import vtkCommonCorePython can work
      // (BUG #14263).
      vtkPythonAppInitPrependPythonPath(SELF_DIR + "/site-packages/vtk");
      }
    }
  //===========================================================================


  //===========================================================================
  // Windows
  // Key:
  //    - SELF_DIR: directory containing the pvserver/pvpython/paraview
  //      executables.
  //---------------------------------------------------------------------------
  //  + BUILD_LOCATION
  //    + ParaView C/C++ library location
  //      - SELF_DIR
  //    + ParaView Python modules
  //      - SELF_DIR/../lib/site-packages    (when CMAKE_INTDIR is not defined).
  //          OR
  //      - SELF_DIR/../../lib/site-packages (when CMAKE_INTDIR is defined).
  //  + INSTALL_LOCATION
  //    + ParaView C/C++ library location
  //      - SELF_DIR
  //      - SELF_DIR/../lib/paraview-<major>.<minor>/
  //    + ParaView Python modules
  //      - SELF_DIR/../lib/paraview-<major>.<minor>/site-packages
  //    + VTK Python Module libraries
  //      - SELF_DIR/../lib/paraview-<major>.<minor>/site-packages/vtk
  //===========================================================================
  void vtkPythonAppInitPrependPathWindows(const std::string& SELF_DIR)
    {
    // For use in MS VS IDE builds we need to account for selection of
    // build configuration in the IDE. CMAKE_INTDIR is how we know which
    // configuration user has selected. It will be one of Debug, Release,
    // ... etc. With in VS builds SELF_DIR will be set like
    // "builddir/bin/CMAKE_INTDIR". PYHTONPATH should have SELF_DIR and
    // "builddir/lib/CMAKE_INTDIR"
    std::string build_dir_site_packages;
#if defined(CMAKE_INTDIR)
    build_dir_site_packages = SELF_DIR + "/../../lib/site-packages";
#else
    build_dir_site_packages = SELF_DIR + "/../lib/site-packages";
#endif
    bool is_build_dir =
      vtksys::SystemTools::FileExists(build_dir_site_packages.c_str());
    if (is_build_dir)
      {
      vtkPythonAppInitPrependPythonPath(SELF_DIR);
#if defined(CMAKE_INTDIR)
      vtkPythonAppInitPrependPythonPath(
        SELF_DIR + "/../../lib/" + std::string(CMAKE_INTDIR));
#else
      vtkPythonAppInitPrependPythonPath(SELF_DIR + "/../lib");
#endif
      vtkPythonAppInitPrependPythonPath(build_dir_site_packages);
      }
    else
      {
      vtkPythonAppInitPrependPythonPath(SELF_DIR);
      vtkPythonAppInitPrependPythonPath(
        SELF_DIR + "/../lib/paraview-" PARAVIEW_VERSION);
      vtkPythonAppInitPrependPythonPath(
        SELF_DIR + "/../lib/paraview-" PARAVIEW_VERSION "/site-packages");
      // BUG #14263 happened with windows installed versions too. This addresses
      // that problem.
      vtkPythonAppInitPrependPythonPath(
        SELF_DIR + "/../lib/paraview-" PARAVIEW_VERSION "/site-packages/vtk");
      }
    }

  //===========================================================================
  // OsX
  // Key:
  //    - SELF_DIR: directory containing the pvserver/pvpython/paraview
  //      executables. This is different for app and non-app executables.
  //---------------------------------------------------------------------------
  //  + BUILD_LOCATION
  //    - LIB_DIR
  //      - SELF_DIR/../lib       (when executable is not APP, e.g pvpython)
  //          OR
  //      - SELF_DIR/../../../../lib (when executable is APP, e.g. paraview)
  //    + ParaView C/C++ library location
  //      - LIB_DIR
  //    + ParaView Python modules
  //      - LIB_DIR/site-packages
  //  + INSTALL_LOCATION
  //    - APP_ROOT
  //      - SELF_DIR/../..        (this is same for paraview and pvpython)
  //    - ParaView C/C++ library location
  //      - APP_ROOT/Contents/Libraries/
  //    - ParaView Python modules
  //      - APP_ROOT/Contents/Python
  //===========================================================================
  void vtkPythonAppInitPrependPathOsX(const std::string &SELF_DIR)
    {
    bool is_app = false;
      {
      // if SELF_DIR/../ is named "Contents", we are in an App.
      std::string contents_dir = vtksys::SystemTools::CollapseFullPath(
        (SELF_DIR + "/..").c_str());
      is_app = (vtksys::SystemTools::GetFilenameName(contents_dir) == "Contents");
      }

    std::string lib_dir = (is_app==false)? (SELF_DIR + "/../lib") :
                                           (SELF_DIR + "/../../../../lib");
    lib_dir = vtksys::SystemTools::CollapseFullPath(lib_dir.c_str());

    bool is_build_dir = vtksys::SystemTools::FileExists(lib_dir.c_str());
    if (is_build_dir)
      {
      vtkPythonAppInitPrependPythonPath(lib_dir);
      vtkPythonAppInitPrependPythonPath(lib_dir + "/site-packages");
      }
    else
      {
      std::string app_root = SELF_DIR + "/../..";
      app_root = vtksys::SystemTools::CollapseFullPath(app_root.c_str());
      // The Contents/Libraries may not be needed. We should verify that.
      vtkPythonAppInitPrependPythonPath(app_root + "/Contents/Libraries");
      vtkPythonAppInitPrependPythonPath(app_root + "/Contents/Python");
      }
    }

  //----------------------------------------------------------------------------
  void vtkPythonAppInitPrependPath(const std::string &SELF_DIR)
    {
    // We don't initialize Python paths when Frozen Python is being used. This
    // avoid unnecessary file-system accesses..
#ifndef PARAVIEW_FREEZE_PYTHON
# if defined(_WIN32)
    vtkPythonAppInitPrependPathWindows(SELF_DIR);
# elif defined(__APPLE__)
    vtkPythonAppInitPrependPathOsX(SELF_DIR);
# else
    vtkPythonAppInitPrependPathLinux(SELF_DIR);
# endif
#endif // ifndef PARAVIEW_FREEZE_PYTHON

    // *** The following maybe obsolete. Need to verify and remove. ***

    // This executable does not actually link to the python wrapper
    // libraries, though it probably should now that the stub-modules
    // are separated from them.  Since it does not we have to make
    // sure the wrapper libraries can be found by the dynamic loader
    // when the stub-modules are loaded.  On UNIX this executable must
    // be running in an environment where the main VTK libraries (to
    // which this executable does link) have been found, so the
    // wrapper libraries will also be found.  On Windows this
    // executable may have simply found its .dll files next to itself
    // so the wrapper libraries may not be found when the wrapper
    // modules are loaded.  Solve this problem by adding this
    // executable's location to the system PATH variable.  Note that
    // this need only be done for an installed VTK because in the
    // build tree the wrapper modules are in the same directory as the
    // wrapper libraries.
#if defined(_WIN32)
    static char system_path[(VTK_PYTHON_MAXPATH+1)*10] = "PATH=";
    strcat(system_path, SELF_DIR.c_str());
    if(char* oldpath = getenv("PATH"))
      {
      strcat(system_path, ";");
      strcat(system_path, oldpath);
      }
    putenv(system_path);
#endif // if defined(_WIN32)
    }
}

#endif
// VTK-HeaderTest-Exclude: vtkProcessModuleInitializePython.h
