/** \file
 *
 *  Contains the LuaAPI class definition.
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 *
 */

/** \defgroup lua Lua
 *
 * Lua has been selected as a scripting language for Tethys/LRAUV for a
 * variety of reasons.  Foremost, it has clear and concise instructions and
 * examples for embedding in a larger application.  It is relatively
 * fast (only 9.9x slower than c++, faster than most other scripting languages),
 * and our compiled Lua library is only 311KB when compiled for our target
 * platform 273KB when compiled for the host). This is larger than the smallest
 * implementation of Tcl, but small enough for our needs.
 */

#ifndef LUAAPI_H_
#define LUAAPI_H_

#include "missionScript/ScriptAPI.h"

/// This pushes the Lua library include down into the LuaAPI.cpp file.
class lua_State;
class DataReader;
class DataWriter;
class InputInfo;
class LuaNode;
class ScriptNode;
class Unit;

/**
 * A wrapper for the lua programming language interface.  Allows scripted
 * modules and components to share much of the same API as c++ modules and
 * components.  Works closely with Tethys.lua code.
 *
 *  \ingroup lua
 */
class LuaAPI: public ScriptAPI
{
public:

    virtual ~LuaAPI();

    /** Returns a ScriptNode within the namespace of componentName
      * that contains a function with the given methodName, with
      * arguments of the given inputNames, with the indicated code
      */
    virtual ScriptNode* makeScriptFunction( const char* moduleName,
                                            const char* componentName, const char* methodName,
                                            FlexArray<InputInfo*>& inputs, FlexArray<SettingInfo*>& settings,
                                            const char* code, Logger& logger );

protected:

    friend class LuaMissionAPI;

    class LuaState
    {
    public:
        LuaState();
        ~LuaState();
        operator lua_State*()
        {
            return lua_;
        }
    private:
        // Note that the copy constructor below is private and not given a body.
        // Any attempt to call it will return a compiler error.
        LuaState( const LuaState& old ); // disallow copy constructor
        lua_State* lua_;
    };

    static LuaState LUA_;

    friend class LuaNode;

    /// Loads the indicated file.
    /// Returns pointer to error message if unable to do so.
    static const char* LoadFile( const char* filename );

    /// Runs the specified command, with no return.
    /// Returns pointer to error message if unable to do so.
    static const char* Exec( const char* command );

    /// Runs the function on top of the stack with the indicated args
    /// and returns the indicated outputs.  If boolValue is true, it will
    /// be set to the single boolean result of the function.
    static bool Exec( FlexArray<DataReader*>* inputs, FlexArray<SettingReader*>* settings,
                      bool& boolValue, FlexArray<DataWriter*>* outputs, FlexArray<const Unit*>* outUnits,
                      Logger& logger );

    /// Runs whatever is on top of the stack with no args and no return.
    /// Returns pointer to error message if unable to do so.
    static const char* Run();

    /// Runs specified function from the currently open table.
    /// Returns pointer to error message if unable to do so.
    static const char* RunFunction( const char* functionName, Str& returnValue, bool isRoot = false );

    /// Is the item at the top of the stack a table?
    static bool IsTable( bool isRoot );

    /// Opens an item from the table on the top of the stack by its zero-based index
    /// it must be closed later with CloseTableItem()
    static bool OpenTableItemByIndex( int index, bool isRoot );

    /// Opens an item from the table on the top of the stack by its name
    /// it must be closed later with CloseTableItem()
    static bool OpenTableItemByName( const char* name, bool isRoot );

    /// Pushes a nil onto the stack
    static void PushNil();

    /// returns the height of the stack
    static int GetStackHeight();

    /// Returns the size of the table on the top of the stack
    /// Returns -1 if not a table.
    static int GetTableSize( bool isRoot );

    /// Just pops the top item off the lua stack.
    static void CloseTableItem();

    /// gets a boolean from the top of the stack
    static bool GetBool( bool& readTo, bool isRoot );

    /// gets a number from the top of the stack
    static bool GetNumber( double& readTo, bool isRoot );

    /// gets a unsigned char string from the top of the stack
    static bool GetString( Str& readTo, bool isRoot );

    /// creates a new empty table and adds to open node, returns true if successful
    static bool NewTable( const char* name, bool isRoot );

    /// creates a new function and adds to open node, returns error message if error
    static const char* NewFunction( const char* functionName, const char* functionBody, bool isRoot );

private:
    // Note that the copy constructor below is private and not given a body.
    // Any attempt to call it will return a compiler error.
    LuaAPI( const LuaAPI& old ); // disallow copy constructor

    /// Private constructor for singleton
    LuaAPI();

    static LuaAPI Instance_;

    LuaNode* rootNode_;

};

#endif /* LUAAPI_H_ */
