/////////////////////////////////////////////////////////////////////////////
// Name:        compiler.h
// Purpose:     wxCompilerSettings - compilers supported by wxPackage API
// Author:      Francesco Montorsi
// Modified by:
// Created:     2006-11-07
// RCS-ID:      $Id: compiler.h,v 1.3 2007/01/28 15:56:10 frm Exp $
// Copyright:   (c) Francesco Montorsi
// Licence:     wxWidgets licence
/////////////////////////////////////////////////////////////////////////////

#ifndef _COMPILER_H_
#define _COMPILER_H_

// Includes
#include "wx/tokenzr.h"
#include "wxp/wxputils.h"

// Forward declarations
class wxStringHashMap;
class wxPackageCommandOptionArray;
class wxConfigBase;
class wxPackageInfo;
class wxPackageArray;


// ----------------------------------------------------------------------------
// enums
// ----------------------------------------------------------------------------

//! One of the stage handled by wxPM API.
enum wxPackageBuildSystemStage
{
    wxPBSS_INVALID = -1,

    wxPBSS_BUILD = 1,
    wxPBSS_INSTALL = 2,
    wxPBSS_UNINSTALL = 4,
    wxPBSS_CLEAN = 8,

    wxPBSS_MAX = 4
};

//! The possible types of build systems of a wxPackage.
//! These flags must be OR-combinable (see #s_nBuildSystemTypeMask).
enum wxPackageBuildSystemType
{
    wxPBST_INVALID = -1,

    wxPBST_BAKEFILE = 1,
    wxPBST_CMAKE = 2,
    wxPBST_SCONS = 4,
    wxPBST_MAKEFILE = 8,

    wxPBST_MAX = 4
};

//! List of supported compilers by the various build systems
//! (bakefile, cmake, scons, etc): these values are not
//! build-system dependent as they are mainly used to store
//! compiler paths which are the same for each compiler
//! regardless of the build system which uses it.
//!
//! NB: for bakefile & cmake (which are makefiles-generators)
//!     only makefile formats are supported.
//!     IDE formats cannot be used to build the package from
//!     wxPM and thus are skipped.
//!
//! NB2: if you change this enum, also change the wxPackageCompilerNotes
//!      array in wxCompilerSettingsPanel sources.
//!
enum wxPackageCompilerFormat
{
    wxPCF_INVALID = -1,

    // win32 main makefile formats
    wxPCF_BORLAND = 1,
    wxPCF_MSVC = 2,
    wxPCF_WATCOM = 4,
    wxPCF_MINGW = 8,
    wxPCF_MSYS = 16,

    // unix main formats
    wxPCF_GNUMAKEFILE = 32,
    wxPCF_AUTOCONF = 64,

    wxPCF_MAX = 7
};

//! The type of compiler paths stored by wxCompilerSettings.
enum wxPackageCompilerPathType
{
    wxPCPT_INVALID = -1,

    wxPCPT_BIN,
    wxPCPT_INCLUDE,
    wxPCPT_LIB,

    wxPCPT_MAX
};

wxDEFINE_STRING2COMBINEABLE_ENUM(PackageBuildSystemStage)
wxDEFINE_STRING2COMBINEABLE_ENUM(PackageBuildSystemType)
wxDEFINE_STRING2COMBINEABLE_ENUM(PackageCompilerFormat)
wxDEFINE_STRING2ENUM(PackageCompilerPathType)


// additional global utilities:

//! Returns true if the given compiler format is supported by the given
//! build system type.
bool wxIsCompilerFormatSupportedBy(wxPackageCompilerFormat fmt,
                                   wxPackageBuildSystemType buildsys);

//! Returns the list of build systems which support the given compiler format.
int wxGetBuildSystemsSupportingCompilerFormat(wxPackageCompilerFormat fmt);

//! Returns true if the given compiler format is supported by current platform.
bool wxIsCompilerFormatSupportedByThisPlatform(wxPackageCompilerFormat fmt);


// ----------------------------------------------------------------------------
// wxCompilerSettings
// ----------------------------------------------------------------------------

//! The compiler settings both global and package-specific.
class wxCompilerSettings
{
protected:          // static

    //! The paths for the selected compiler tools.
    static wxPathList s_paths[wxPCF_MAX][wxPCPT_MAX];

    //! The default compiler.
    static wxPackageCompilerFormat s_defaultFormat;

protected:

    // NOTE: there isn't a selected build system variable in this class
    //       because a package always have a single build system !

    //! The selected compiler.
    wxPackageCompilerFormat s_selFormat;

public:

    wxCompilerSettings()
        { s_selFormat=s_defaultFormat; }


public:     // static getters

    //! Returns the wxArrayString of the paths for the selected compiler.
    static wxPathList &GetCompilerPaths(wxPackageCompilerFormat n,
                                        wxPackageCompilerPathType t)
        { return s_paths[wxPackageCompilerFormat2Idx(n)][t]; }

    //! Returns the default compiler.
    static wxPackageCompilerFormat GetDefaultFormat()
        { return s_defaultFormat; }

public:     // static setters

    //! Sets the currently selected compiler.
    static void SetDefaultFormat(wxPackageCompilerFormat newfmt)
        { s_defaultFormat=newfmt; }


public:     // non-static getters

    wxPathList GetCompilerPaths(wxPackageCompilerPathType t) const
        { return GetCompilerPaths(s_selFormat, t); }

    //! Returns the currently selected compiler.
    wxPackageCompilerFormat GetSelFormat() const
        { return s_selFormat; }

    //! Sets the currently selected compiler.
    void SetSelFormat(wxPackageCompilerFormat newfmt)
        { wxASSERT(newfmt!=wxPCF_INVALID); s_selFormat=newfmt; }

public:     // options

    //! Returns an hashmap with the option names + default values for the
    //! currently selected compiler & build-system.
    //! The returned options are options heavily compiler-dependent whose
    //! default values are usually left untouched.
    wxStringHashMap GetOptionsWithDefaults(wxPackageBuildSystemType) const;

public:     // static paths utilities

    //! Returns true if all the tools required by currently selected format
    //! can be found in the given pathlist.
    static bool IsValidPathList(wxPackageCompilerFormat fmt, const wxPathList &);

    //! Returns the absolute path for the given compiler program or
    //! an empty string if it could not be found in the selected
    //! compiler's paths.
    static wxString GetToolPath(wxPackageCompilerFormat fmt, const wxString &program)
        { return s_paths[fmt][wxPCPT_BIN].FindAbsoluteValidPath(program); }

    //! Returns the wxArrayString of the compiler tools required by the currently
    //! selected compiler.
    //! NB: the returned list cannot be placed in a static wxString table as the
    //!     number of required tools is different for different compilers.
    static wxArrayString GetRequiredToolsList(wxPackageCompilerFormat fmt);

    //! Sets the wxArrayString fo the paths for the selected compiler.
    static void SetCompilerPaths(wxPackageCompilerFormat n, 
                                 wxPackageCompilerPathType t,
                                 const wxPathList &str)
        { s_paths[wxPackageCompilerFormat2Idx(n)][t] = str; }

    //! Adds a path.
    static void AddPath(wxPackageCompilerFormat f, 
                        wxPackageCompilerPathType t,
                        const wxString &str)
        { s_paths[wxPackageCompilerFormat2Idx(f)][t].Add(str); }

public:     // non-static paths utilities

    bool IsValidPathList(const wxPathList &pl) const
        { return IsValidPathList(s_selFormat, pl); }

    wxArrayString GetRequiredToolsList() const
        { return GetRequiredToolsList(s_selFormat); }

    wxString GetToolPath(const wxString &program) const
        { return GetToolPath(s_selFormat, program); }

    //! Updates the PATH, INCLUDE and LIB environment variables of the currently
    //! running process adding paths for the selected compiler tools &
    //! setting the location of the currently selected wx build.
    void UpdateEnvVars();
    void UpdateEnvVar(const wxString &name, wxPackageCompilerPathType t);

    //! Returns the substitution table for format-specific keywords and eventually 
    //! also some build-system specific keywords in the given string.
    wxStringHashMap GetSubstitutionHashMap(wxPackageBuildSystemType t = wxPBST_INVALID) const;

public:     // load/save

    //! Loads the selected compiler & build-system from given path.
    bool Load(wxConfigBase *, const wxString &path);

    //! Saves the selected compiler & build-system to given path.
    void Save(wxConfigBase *, const wxString &path) const;

    //! Loads the compiler paths from given path.
    static bool LoadGlobals(wxConfigBase *, const wxString &path);

    //! Saves the compiler paths to given path.
    static void SaveGlobals(wxConfigBase *, const wxString &path);
};

#endif      // _COMPILER_H_

