# -*- coding: utf-8 -*-
# @configure_input@

#-------------------------------------------------------------------------------

# This file is part of Code_Saturne, a general-purpose CFD tool.
#
# Copyright (C) 1998-2013 EDF S.A.
#
# This program 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 2 of the License, or (at your option) any later
# version.
#
# This program 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
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# Street, Fifth Floor, Boston, MA 02110-1301, USA.

#-------------------------------------------------------------------------------

import os
import sys
from optparse import OptionParser

#-------------------------------------------------------------------------------

# Prerequisites libraries
#------------------------

class prerequisite:

    def __init__(self, name, have = "no",
                 variant = None, dynamic_load = False,
                 prefix = None, execprefix = None,
                 bindir = None, includedir = None, libdir = None,
                 flags = None):

        # Library name
        self.name = name

        # Have
        self.have = have

        # Loaded dynamically on demand (linked separately)
        self.dynamic_load = dynamic_load

        # Library variant
        self.variant = variant

        # Library installation directories
        self.prefix = prefix
        self.execprefix = execprefix
        self.bindir = bindir
        self.includedir = includedir
        self.libdir = libdir

        # Library build (dictionnary {cppflags, ldflags, libs})
        self.flags = flags

    def print_config(self):

        print("Prequisite: " + self.name)


# Configuration info
#-------------------

class config:

    def __init__(self):

        # List of optionnal features

        self.optfeatures = ['debug', 'relocatable', 'shared',
                            'gui', 'frontend',
                            'openmp', 'socket',
                            'long-gnum', 'nls']
        self.features = {}

        # List of mandatory and optionnal libraries to link with
        # The order is important so as to have a coherent link command

        self.deplibs = ['saturne',                    # Code_Saturne
                        'ple',                        # PLE
                        'latex', 'doxygen', 'sphinx', # docs
                        'eos',                        # Equations of state
                        'freesteam',                  # Freesteam
                        'cgns', 'med', 'hdf5', 'ccm', # Mesh filters
                        'catalyst',                   # co-processing library
                        'medcoupling', 'paramedmem',  # MED coupling
                        'metis', 'scotch',            # Partionning libraries
                        'mpi',                        # MPI
                        'libxml2',                    # XML reader
                        'blas',                       # BLAS (benchmark use)
                        'system']                     # User & system libraries

        # Compilers, flags and special commands

        self.compilers = {'cc': "@CC@",
                          'cxx': "@CXX@",
                          'fc': "@FC@",
                          'ld': "@CS_LD@"}

        self.flags = {'cflags': "@CFLAGS@ @CFLAGS_DBG@ @CFLAGS_OPT@",
                      'cxxflags': "@CXXFLAGS@ @CXXFLAGS_DBG@ @CXXFLAGS_OPT@",
                      'fcflags': "@FCFLAGS@ @FCFLAGS_DBG@ @FCFLAGS_OPT@"}

        self.fcmodinclude = "@FCMODINCLUDE@"
        self.rpath = "@LDRPATH@"
        self.special_user_link = "@cs_special_user_link@"

        # Constants for system-dependant file extensions
        if sys.platform.startswith("win"):
            self.cfgext = ".ini"
            self.exeext = ".exe"
            self.shext = ".bat"
        else:
            self.cfgext = ".cfg"
            self.exeext = ""
            self.shext = ""

        # Python-related information

        self.python = "@PYTHON@"
        self.pyuic4 = "@PYUIC4@"
        self.pyrcc4 = "@PYRCC4@"

        # Execution environment

        self.env_modules = "@cs_env_modules@"
        self.env_modulecmd = "@MODULECMD@"

        # SALOME-related information

        self.have_salome = "@cs_have_salome_kernel@"
        self.salome_env = "@SALOMEENVCMD@"
        self.salome_run = "@SALOMERUN@"
        self.salome_kernel = "@SALOME_KERNEL@"

        # Setup the optionnal features

        self.features['debug'] = "@debug@"
        self.features['relocatable'] = "@relocatable@"
        self.features['shared'] = "@enable_shared@"
        self.features['gui'] = "@cs_have_gui@"
        self.features['frontend'] = "@cs_have_frontend@"
        self.features['openmp'] = "@cs_have_openmp@"
        self.features['long-gnum'] = "@cs_have_long_gnum@"
        self.features['nls'] = '@USE_NLS@'

        # Now, one can setup the prerequisites information

        self.libs = {}

        # Setup Code_Saturne libraries
        # Here, CPPFLAGS and LDFLAGS will be provided by a get_dir method

        self.libs['saturne'] = \
            prerequisite("Code_Saturne",
                         have = "yes",
                         flags = {'cppflags': "",
                                  'ldflags': "",
                                  'libs': "-lsaturne"})

        # Setup PLE library
        # Here, the variant (internal or external) will be used to add
        # paths to the command line

        self.libs['ple'] = \
            prerequisite("PLE",
                         have = "yes",
                         variant = "@ple_type@",
                         flags = {'cppflags': "@PLE_CPPFLAGS@",
                                  'ldflags': "@PLE_LDFLAGS@",
                                  'libs': "@PLE_LIBS@"})

        # Setup latex for docs

        self.libs['latex'] = \
            prerequisite("Latex",
                         have = "@cs_have_latex@",
                         flags = {'cppflags': "",
                                  'ldflags': "",
                                  'libs': ""})

        self.libs['doxygen'] = \
            prerequisite("Doxygen",
                         have = "@cs_have_doxygen@",
                         flags = {'cppflags': "",
                                  'ldflags': "",
                                  'libs': ""})

        self.libs['sphinx'] = \
            prerequisite("Sphinx",
                         have = "@cs_have_sphinx@",
                         flags = {'cppflags': "",
                                  'ldflags': "",
                                  'libs': ""})

        # Setup user and system libraries

        self.libs['system'] = \
            prerequisite("System",
                         have = "yes",
                         flags = {'cppflags': "@CPPFLAGS@",
                                  'ldflags': "@LDFLAGS@",
                                  'libs': "@LIBINTL@ @LIBS@ @FCLIBS@"})

        # Setup the optionnal libraries

        self.libs['blas'] = \
            prerequisite("BLAS",
                         have = "@cs_have_blas@",
                         flags = {'cppflags': "@BLAS_CPPFLAGS@",
                                  'ldflags': "@BLAS_LDFLAGS@",
                                  'libs': "@BLAS_LIBS@"})

        self.libs['ccm'] = \
            prerequisite("CCM",
                         have = "@cs_have_ccm@",
                         flags = {'cppflags': "@CCM_CPPFLAGS@",
                                  'ldflags': "@CCM_LDFLAGS@",
                                  'libs': "@CCM_LIBS@"})

        self.libs['cgns'] = \
            prerequisite("CGNS",
                         have = "@cs_have_cgns@",
                         flags = {'cppflags': "@CGNS_CPPFLAGS@",
                                  'ldflags': "@CGNS_LDFLAGS@",
                                  'libs': "@CGNS_LIBS@"})

        self.libs['hdf5'] = \
            prerequisite("HDF5",
                         have = "@cs_have_hdf5@",
                         flags = {'cppflags': "@HDF5_CPPFLAGS@",
                                  'ldflags': "@HDF5_LDFLAGS@",
                                  'libs': "@HDF5_LIBS@"})

        self.libs['libxml2'] = \
            prerequisite("LibXml2",
                         have = "@cs_have_libxml2@",
                         flags = {'cppflags': "@LIBXML2_CPPFLAGS@",
                                  'ldflags': "@LIBXML2_LDFLAGS@",
                                  'libs': "@LIBXML2_LIBS@"})

        self.libs['med'] = \
            prerequisite("MED",
                         have = "@cs_have_med@",
                         flags = {'cppflags': "@MED_CPPFLAGS@",
                                  'ldflags': "@MED_LDFLAGS@",
                                  'libs': "@MED_LIBS@"})

        self.libs['catalyst'] = \
            prerequisite("CATALYST",
                         have = "@cs_have_catalyst@",
                         dynamic_load = @cs_py_have_plugins@,
                         flags = {'cppflags': "@CATALYST_CPPFLAGS@",
                                  'ldflags': "@CATALYST_LDFLAGS@",
                                  'libs': "@CATALYST_LIBS@"})

        self.libs['medcoupling'] = \
            prerequisite("MEDCOUPLING",
                         have = "@cs_have_medcoupling@",
                         dynamic_load = True,
                         flags = {'cppflags': "@MEDCOUPLING_CPPFLAGS@",
                                  'ldflags': "@MEDCOUPLING_LDFLAGS@",
                                  'libs': "@MEDCOUPLING_LIBS@"})

        self.libs['paramedmem'] = \
            prerequisite("PARAMEDMEM",
                         have = "@cs_have_paramedmem@",
                         dynamic_load = True,
                         flags = {'cppflags': "@PARAMEDMEM_CPPFLAGS@",
                                  'ldflags': "@PARAMEDMEM_LDFLAGS@",
                                  'libs': "@PARAMEDMEM_LIBS@"})

        self.libs['eos'] = \
            prerequisite("EOS",
                         have = "@cs_have_eos@",
                         prefix="@eos_prefix@",
                         flags = {'cppflags': "@EOS_CPPFLAGS@",
                                  'ldflags': "@EOS_LDFLAGS@",
                                  'libs': "@EOS_LIBS@"})

        self.libs['freesteam'] = \
            prerequisite("FREESTEAM",
                         have = "@cs_have_freesteam@",
                         prefix="@freesteam_prefix@",
                         flags = {'cppflags': "@FREESTEAM_CPPFLAGS@",
                                  'ldflags': "@FREESTEAM_LDFLAGS@",
                                  'libs': "@FREESTEAM_LIBS@"})

        self.libs['metis'] = \
            prerequisite("METIS",
                         have = "@cs_have_metis@",
                         flags = {'cppflags': "@METIS_CPPFLAGS@",
                                  'ldflags': "@METIS_LDFLAGS@",
                                  'libs': "@METIS_LIBS@"})

        self.libs['mpi'] = \
            prerequisite("MPI",
                         have = "@cs_have_mpi@",
                         variant = "@mpi_type@",
                         bindir = "@mpi_bindir@",
                         libdir = "@mpi_libdir@",
                         flags = {'cppflags': "@MPI_CPPFLAGS@",
                                  'ldflags': "@MPI_LDFLAGS@",
                                  'libs': "@MPI_LIBS@"})

        self.libs['scotch'] = \
            prerequisite("SCOTCH",
                         have = "@cs_have_scotch@",
                         flags = {'cppflags': "@SCOTCH_CPPFLAGS@",
                                  'ldflags': "@SCOTCH_LDFLAGS@",
                                  'libs': "@SCOTCH_LIBS@"})


    def print_config(self):

        for lib in self.deplibs:
            self.libs[lib].print_config()

#-------------------------------------------------------------------------------

def process_cmd_line(argv):
    """
    Processes the passed command line arguments.

    Input Argument:
      arg -- This can be either a list of arguments as in
             sys.argv[1:] or a string that is similar to the one
             passed on the command line.  If it is a string,
             it is split to create a list of arguments.
    """

    parser = OptionParser(usage="usage: %prog [options]")

    parser.add_option("--cc", dest="print_cc",
                      action="store_true",
                      help="C compiler used for build")

    parser.add_option("--cxx", dest="print_cxx",
                      action="store_true",
                      help="C++ compiler used for build")

    parser.add_option("--fc", dest="print_fc",
                      action="store_true",
                      help="Fortran compiler used for build")

    parser.add_option("--cflags", dest="print_cflags",
                      action="store_true",
                      help="C compiler flags")

    parser.add_option("--cxxflags", dest="print_cxxflags",
                      action="store_true",
                      help="C++ compiler flags")

    parser.add_option("--fcflags", dest="print_fcflags",
                      action="store_true",
                      help="Fortran compiler flags")

    parser.add_option("--rpath", dest="print_rpath",
                      action="store_true",
                      help="Linker rpath command line")

    parser.add_option("--python", dest="print_python",
                      action="store_true",
                      help="Python interpreter")

    parser.add_option("--pyuic4", dest="print_pyuic4",
                      action="store_true",
                      help="pyuic4 tool for PyQt4 support")

    parser.add_option("--pyrcc4", dest="print_pyrcc4",
                      action="store_true",
                      help="pyrcc4 tool for PyQt4 support")

    parser.add_option("--have", dest="have", metavar="<lib>",
                      help="supported feature or librarie")

    parser.add_option("--cppflags", dest="cppflags", metavar="<lib>",
                      help="C preprocessor flags (e.g. -D<macro>, ...)")

    parser.add_option("--ldflags", dest="ldflags", metavar="<lib>",
                      help="linker flags (e.g. -g, -L<path>, ...)")

    parser.add_option("--libs", dest="libs", metavar="<lib>",
                      help="librairies used (e.g. -l<libname>, ...)")

    parser.set_defaults(print_cc=False)
    parser.set_defaults(print_cxx=False)
    parser.set_defaults(print_fc=False)

    parser.set_defaults(print_cflags=False)
    parser.set_defaults(print_cxxflags=False)
    parser.set_defaults(print_fcflags=False)

    parser.set_defaults(print_rpath=False)

    parser.set_defaults(print_python=False)
    parser.set_defaults(print_pyrcc4=False)
    parser.set_defaults(print_pyuic4=False)

    parser.set_defaults(have=None)
    parser.set_defaults(cppflags=None)
    parser.set_defaults(ldflags=None)
    parser.set_defaults(libs=None)

    (options, args) = parser.parse_args(argv)

    if len(args) > 0:
        parser.print_help()
        sys.exit(1)

    return options

#-------------------------------------------------------------------------------

def get_config(pkg):
    """
    Get the configuration information.
    """
    msg = """\
Compilers and associated options:
  cc = %(cc)s
  cxx = %(cxx)s
  fc = %(fc)s
  cflags = %(cflags)s
  cxxflags = %(cxxflags)s
  fcflags = %(fcflags)s
  rpath = %(rpath)s\
"""

    return msg \
        % { 'cc':pkg.config.compilers['cc'],
            'cxx': pkg.config.compilers['cxx'],
            'fc':pkg.config.compilers['fc'],
            'cflags':pkg.config.flags['cflags'],
            'cxxflags':pkg.config.flags['cxxflags'],
            'fcflags':pkg.config.flags['fcflags'],
            'rpath':pkg.config.rpath }

#-------------------------------------------------------------------------------
# Main
#-------------------------------------------------------------------------------

def main(argv, pkg):
    """
    Main configuration info function.
    """

    opts = process_cmd_line(argv)

    cfg = pkg.config

    if opts.print_cc  == True: print(cfg.compilers['cc'])
    if opts.print_cxx == True: print(cfg.compilers['cxx'])
    if opts.print_fc  == True: print(cfg.compilers['fc'])

    if opts.print_cflags   == True: print(cfg.flags['cflags'])
    if opts.print_cxxflags == True: print(cfg.flags['cxxflags'])
    if opts.print_fcflags  == True: print(cfg.flags['fcflags'])

    if opts.print_rpath == True: print(cfg.rpath)

    if opts.print_python  == True: print(cfg.python)
    if opts.print_pyuic4  == True: print(cfg.pyuic4)
    if opts.print_pyrcc4  == True: print(cfg.pyrcc4)

    if opts.have is not None:
        if opts.have in cfg.deplibs: print(cfg.libs[opts.have].have)
        if opts.have in cfg.optfeatures: print(cfg.features[opts.have])

    if opts.cppflags is not None:
        # Specific handling of Code_Saturne has pkgincludedir has to be
        # correctly expended. Likewise for PLE, if internal version is used
        if opts.cppflags == "saturne":
            print("-I" + pkg.get_dir("pkgincludedir"))
        elif opts.cppflags == "ple":
            if cfg.libs['ple'].variant == "internal":
                print("-I" + pkg.get_dir("includedir"))
            else:
                print(cfg.libs[opts.cppflags].flags['cppflags'])
        else:
            print(cfg.libs[opts.cppflags].flags['cppflags'])

    if opts.ldflags is not None:
        # Specific handling of Code_Saturne has pkgincludedir has to be
        # correctly expended. Likewise for PLE, if internal version is used
        if opts.ldflags == "saturne":
            print("-L" + pkg.get_dir("libdir"))
        elif opts.ldflags == "ple":
            if cfg.libs['ple'].variant == "internal":
                print("-L" + pkg.get_dir("libdir"))
            else:
                print(cfg.libs[opts.cppflags].flags['ldflags'])
        else:
            print(cfg.libs[opts.ldflags].flags['ldflags'])

    if opts.libs is not None:
        print(cfg.libs[opts.libs].flags['libs'])

if __name__ == '__main__':
    import sys
    import cs_package
    pkg = cs_package.package()
    main(sys.argv[1:], pkg)

