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

#include <limits.h>

#include "ScriptComponent.h"
#include "module/ModuleLoader.h"


/// Destructor
ScriptComponent::~ScriptComponent()
{}

/// Returns a barebones instance of ScriptComponent at the indicated index
/// in the script, or NULL if the lua component can not be properly read.
Component* ScriptComponent::Instance( int tableIndex, Logger& logger )
{
    return NULL;
    /*
    // get component name
    Str name;
    if ( !lua.getTableString( name, "name_", tableIndex, logger, Syslog::ERROR ) )
    {
        logger.syslog( "Could not create component without a name", Syslog::ERROR );
        return NULL;
    }

    double componentTypeNumber;
    if ( !lua.getTableNumber( componentTypeNumber, "componentType_", tableIndex, logger, Syslog::ERROR ) )
    {
        logger.syslog( "Could not read ComponentType for " + name , Syslog::ERROR );
        return NULL;
    }

    const Module* module;
    if ( !lua.getTableLightUserData(( void** )&module, "module_", tableIndex, logger, Syslog::ERROR ) )
    {
        logger.syslog( "Could not read module for " + name , Syslog::ERROR );
        return NULL;
    }

    Component* component = NULL;
    double period;
    bool runnable;
    bool satisfiable;
    double cycleOrder;

    switch (( Component::ComponentType ) componentTypeNumber )
    {
    case Component::COMPONENT_ASYNC:
        if ( !lua.getTableNumber( period, "period_", tableIndex, logger, Syslog::ERROR ) )
        {
            logger.syslog( "Could not read Period for AsyncComponent " + name , Syslog::ERROR );
            return NULL;
        }
        component = new ScriptAsyncComponent( lua, module, name, Timespan( period ), true );
        break;
    case Component::COMPONENT_BEHAVIOR:
        if ( !lua.getTableBool( runnable, "runnable_", tableIndex, logger, Syslog::ERROR ) )
        {
            logger.syslog( "Could not read Runnable for Behavior " + name , Syslog::ERROR );
            return NULL;
        }
        if ( !lua.getTableBool( satisfiable, "satisfiable_", tableIndex, logger, Syslog::ERROR ) )
        {
            logger.syslog( "Could not read Satisfiable for Behavior " + name , Syslog::ERROR );
            return NULL;
        }
        component = new ScriptMissionComponent( lua, module, name, runnable, satisfiable );
        break;
    case Component::COMPONENT_SYNC:
        if ( !lua.getTableNumber( cycleOrder, "cycleOrder_", tableIndex, logger, Syslog::ERROR ) )
        {
            logger.syslog( "Could not read CycleOrder for SyncComponent " + name , Syslog::ERROR );
            return NULL;
        }
        component = new ScriptSyncComponent( lua, module, name, ( SyncComponent::CycleOrder )( int )cycleOrder, true );
        break;
    default:
        logger.syslog( Str( "Illegal ComponentType for " ) + name + ": " + componentTypeNumber, Syslog::ERROR );
        return NULL;
    }

    // Configure logger_ member.
    if ( lua.openTable( "logger_", tableIndex, logger, Syslog::ERROR ) )
    {
        /// configure syslog
        lua.setTableFunction( "syslog", -1, Lua::LoggerSyslog,
                              1, ( void* ) & ( component->getLogger() ), NULL, NULL );
    }
    lua.closeTable();

    return component;
    */
}

/// Initialize function
void ScriptComponent::scriptInitialize( Logger& logger )
{
    /*
    //logger.syslog( "In ScriptComponent::initialize" );
    lua_.lock();
    lua_.executeSimple( "initialize", moduleName_, index_, logger );
    lua_.unlock();
    */
}

/// The actual "payload" of the component
void ScriptComponent::scriptRun( Logger& logger )
{
    /*
    lua_.lock();
    lua_.executeSimple( "run", moduleName_, index_, logger );
    lua_.unlock();
    */
}

/// The Trigger test method
bool ScriptComponent::scriptIsSatisfied( Logger& logger )
{
    return true;
    /*
    lua_.lock();
    bool result = lua_.executeNumberReturn( "satisfied", moduleName_, index_, logger ) != 0;
    lua_.unlock();
    return result ;
    */
}

/// Uninit function
void ScriptComponent::scriptUninitialize( Logger& logger )
{
    /*
    lua_.lock();
    lua_.executeSimple( "uninitialize", moduleName_, index_, logger );
    lua_.unlock();
    */
}

/// Protected constructor called through instance()
ScriptComponent::ScriptComponent()
    : moduleName_( "Unknown" ),
      index_( 0 )
{}


/// Protected constructor for components that run in periodic asynchronous threads
ScriptAsyncComponent::ScriptAsyncComponent( const Module* module, const Str& name,
        const Timespan& period )
    : ScriptComponent(),
      AsyncComponent( name, module, period )
{}

ScriptMissionComponent::ScriptMissionComponent( const Module* module, const Str& name,
        const bool runnable, const bool satisfiable )
    : ScriptComponent(),
      Behavior( name, module, runnable, satisfiable )
{}

ScriptSyncComponent::ScriptSyncComponent( const Module* module, const Str& name,
        CycleOrder cycleOrder )
    : ScriptComponent(),
      SyncComponent( name, module, cycleOrder )
{}
