// $Id: variableCmd.cpp,v 1.2 2003/03/10 15:45:08 fukasawa Exp $

//=============================================================================
/**
 *  @file    variableCmd.cpp
 *
 *  @author  Fukasawa Mitsuo
 *
 *
 *    Copyright (C) 2002 BEE Co.,Ltd. All rights reserved.
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
//=============================================================================

#define BEE_BUILD_DLL

#ifdef _MSC_VER
#pragma warning(disable: 4786)  // too long identifier
#endif

#include "JGEquipment.h"
#include "JGInfoManager.h"
#include "tclbee.h"

#ifdef _MSC_VER
#include <windows.h>
#endif

// function prototype
static int dump_variables(Tcl_Interp * interp, JGEquipment * jyugem);
static int set_value(Tcl_Interp * interp, string& valueStr, JGVariable * var);
static JGVariable * find_variable(Tcl_Interp * interp,
                                  JGEquipment * jyugem, string& vidStr);

/*
 *----------------------------------------------------------------------
 *
 * Gem_variableCmd --
 *
 *      This procedure is invoked to process the "gem::variable"
 *      command. See the user documentation for details on what it does.
 *
 * Results:
 *      A standard Tcl result.
 *
 * Side effects:
 *      See the user documentation.
 *
 *----------------------------------------------------------------------
 */

    /* ARGSUSED */
int
Gem_variableCmd(ClientData arg, Tcl_Interp * interp, int objc,
              Tcl_Obj *CONST objv[])
{
    static char *gemcmds[] = {
        "init",
        "set",
        "get",
        "dump",
        NULL
    };
    /*
     * All commands enums below ending in X are compatibility
     */
    enum gemcmds {
        GEMCMD_INIT,
        GEMCMD_SET,
        GEMCMD_GET,
        GEMCMD_DUMP,
    };

    Tcl_Obj * res;
    int    cmdindex, result;
    JGVariable * variable;
    BS2value value;
    string  vidStr;
    string  valueStr;
    string  buf;

    Tcl_ResetResult(interp);
    result = TCL_OK;

    JGEquipment * jyugem = (JGEquipment *)arg;

    /*
     * Get the command name index from the object based on the spoolcmds
     * defined above.
     */
    if (Tcl_GetIndexFromObj(interp,
        objv[1], (const char **)gemcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
        return TCL_ERROR;

    res = NULL;
    switch ((enum gemcmds)cmdindex) {
    case GEMCMD_INIT:
        break;
    case GEMCMD_SET:
        if (objc != 4)
        {
            Tcl_WrongNumArgs(interp, 2, objv, "vid value");
            return TCL_ERROR;
        }
        vidStr = Tcl_GetStringFromObj(objv[2], NULL);

        // Find variable by vidStr
        variable = find_variable(interp, jyugem, vidStr);
        if (variable == NULL)
        {
            return TCL_ERROR;
        }

        // Convert string to value
        valueStr = Tcl_GetStringFromObj(objv[3], NULL);
        set_value(interp, valueStr, variable);

        break;
    case GEMCMD_GET:
        if (objc != 3)
        {
            Tcl_WrongNumArgs(interp, 2, objv, "vid");
            return TCL_ERROR;
        }
        vidStr = Tcl_GetStringFromObj(objv[2], NULL);

        // Find variable by vidStr
        variable = find_variable(interp, jyugem, vidStr);
        if (variable == NULL)
        {
            return TCL_ERROR;
        }

        value = variable->curval();
        value.get(valueStr);
        Tcl_AppendResult(interp, valueStr.c_str(), NULL);

        break;
    case GEMCMD_DUMP:
        if (objc == 2)
        {
            dump_variables(interp, jyugem);
        }
        else if (objc == 3)
        {
            vidStr = Tcl_GetStringFromObj(objv[2], NULL);

            // Find variable by vidStr
            variable = find_variable(interp, jyugem, vidStr);
            if (variable == NULL)
            {
                return TCL_ERROR;
            }
            variable->printOn(buf);
            Tcl_AppendResult(interp, "{", NULL);            // print header
            Tcl_AppendResult(interp, buf.c_str(), NULL);
            Tcl_AppendResult(interp, "} ", NULL);
        }
        else
        {
            Tcl_WrongNumArgs(interp, 2, objv, "?vid ?");
            return TCL_ERROR;
        }
        break;

    }

    /*
     * For each different arg call different function to create
     * new commands (or if version, get/return it).
     */
    if (result == TCL_OK && res != NULL)
        Tcl_SetObjResult(interp, res);

    return TCL_OK;
}

/*----------------------------------------------------------------------
 * Dump all variables
 *----------------------------------------------------------------------
 */
int
dump_variables(Tcl_Interp * interp, JGEquipment * jyugem)
{
    string buf;

    // Variable tables in the equipment
    JGVariableTable * vartbl = jyugem->getInfoManager()->varTable();
    JGVariableTable::iterator var_it = vartbl->begin();

    for ( ; var_it != vartbl->end(); ++var_it)
    {
        JGVariable * var = &((*var_it).second);
        var->printOn(buf);

        Tcl_AppendResult(interp, "{", NULL);            // print header
        Tcl_AppendResult(interp, buf.c_str(), NULL);
        Tcl_AppendResult(interp, "} ", NULL);
    }
    return TCL_OK;
}

/*----------------------------------------------------------------------
 * Set value in the variable
 *----------------------------------------------------------------------
 */
int set_value(Tcl_Interp * interp, string& valueStr, JGVariable * var)
{
    JGvalue value;
    value.set(valueStr, var->format());
    var->setv(value);
    return TCL_OK;
}

//---------------------------------------------------------------------------
// Parse vid in command parameter
//---------------------------------------------------------------------------
static JGVariable * find_variable(Tcl_Interp * interp, JGEquipment * jyugem,
                                  string& vidStr)
{
    JGid  vid;

    const string& typeName = jyugem->getConf(_TX("IdentificationType"));
    if (typeName == _TX("UINT4"))
    {
        unsigned int num = strtoul(vidStr.c_str(), NULL, 0);
        if (num == 0)
        {
            Tcl_AppendResult(interp, _TX("Illegal VID : "), vidStr.c_str(), NULL);
            return NULL;
        }
        vid = num;
    }
    else
    {
        vid = vidStr.c_str();
    }

    JGVariable * variable = jyugem->variable(vid);
    return variable;
}

