// $Id: ppCmd.cpp,v 1.4 2003/03/16 14:51:02 fukasawa Exp $

//=============================================================================
/**
 *  @file    ppCmd.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 "JGProcProgManager.h"
#include "BS2Message.h"
#include "tclbee.h"

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

// function prototype

/*
 *----------------------------------------------------------------------
 *
 * Gem_ppCmd --
 *
 *      This procedure is invoked to process the "gem::pp"
 *      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_ppCmd(ClientData arg, Tcl_Interp * interp, int objc,
                Tcl_Obj *CONST objv[])
{
    // MELDeviceManager * melmngr;
    static char *gemcmds[] = {
        "read",
        "write",
        "del",
        "purge",
        "upload",
        "download",
        "verified",
        "dump",
        NULL
    };
    /*
     * All commands enums below ending in X are compatibility
     */
    enum gemcmds {
        PP_READ,
        PP_WRITE,
        PP_DEL,
        PP_PURGE,
        PP_UPLOAD,
        PP_DOWNLOAD,
        PP_VERIFIED,
        PP_DUMP,
    };

    Tcl_Obj * res;
    int  cmdindex, result;
    JGid vid;

    JGEquipment * jyugem = (JGEquipment *)arg;
    JGProcProgManager * pp = (JGProcProgManager *)jyugem->findManager(CATEGORY_PROCPROG);

    Tcl_ResetResult(interp);
    result = TCL_OK;

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

    res = NULL;
    switch ((enum gemcmds)cmdindex) {
    case PP_READ:
        {
            if (objc != 3)
            {
                Tcl_WrongNumArgs(interp, 2, objv, "ppid");
                return TCL_ERROR;
            }
            string ppidStr = Tcl_GetString(objv[2]);
            JGid ppid(ppidStr);
            BYTE * datap;
            size_t size;
            result = pp->read(ppid, datap, size);
            if (result < 0)
            {
                return TCL_ERROR;
            }
            bee_memdump(interp, (char *)datap, size, 2);
            delete[] datap;
            break;
        }
        break;
    case PP_WRITE:
        {
            if (objc != 3)
            {
                Tcl_WrongNumArgs(interp, 2, objv, "ppid");
                return TCL_ERROR;
            }
            string ppidStr = Tcl_GetString(objv[2]);
            JGid ppid(ppidStr);
            size_t size = 256;
            BYTE * datap = new BYTE[size];
            for (size_t i = 0; i < size; i++)
            {
                *(datap + i) = (BYTE)(i & 0xFF);
            }
            pp->write(ppid, datap, size);
            delete[] datap;
            break;
        }
        break;
    case PP_DEL:
        {
            if (objc != 3)
            {
                Tcl_WrongNumArgs(interp, 2, objv, "ppid");
                return TCL_ERROR;
            }
            string ppidStr = Tcl_GetString(objv[2]);
            JGid ppid(ppidStr);
            pp->del(ppid);
            break;
        }
        break;
    case PP_PURGE:
        {
            pp->purge();
            break;
        }
        break;
    case PP_UPLOAD:
        {
            if (objc < 3 || objc > 5)
            {
                Tcl_WrongNumArgs(interp, 2, objv, "ppid ?timer? ?retry?");
                return TCL_ERROR;
            }
            string ppidStr = Tcl_GetString(objv[2]);
            JGid ppid(ppidStr);

            int watchdogTime = JGProcProgManager::MAX_WAITING_TIME;
            int retryCount = JGProcProgManager::MAX_RETRY_COUNT;
            if (objc >= 4)
            {
                result = Tcl_GetIntFromObj(interp, objv[3], &watchdogTime);
                if (result != TCL_OK)
                {
                    return result;
                }
                if (objc == 5)
                {
                    result = Tcl_GetIntFromObj(interp, objv[4], &retryCount);
                    if (result != TCL_OK)
                    {
                        return result;
                    }
                }
            }
            result = pp->upload(ppid, watchdogTime, retryCount);

            break;
        }
        break;
    case PP_DOWNLOAD:
        {
            if (objc < 3 || objc > 4)
            {
                Tcl_WrongNumArgs(interp, 2, objv, "ppid ?timer?");
                return TCL_ERROR;
            }
            string ppidStr = Tcl_GetString(objv[2]);
            JGid ppid(ppidStr);

            int watchdogTime = JGProcProgManager::MAX_WAITING_TIME;
            if (objc == 4)
            {
                result = Tcl_GetIntFromObj(interp, objv[3], &watchdogTime);
                if (result != TCL_OK)
                {
                    return result;
                }
            }
            result = pp->download(ppid, watchdogTime);

            break;
        }
        break;
    case PP_VERIFIED:
        {
            if (objc != 6)
            {
                Tcl_WrongNumArgs(interp, 2, objv, "ppid ackc7 seqnum errw7");
                return TCL_ERROR;
            }
            string ppidStr = Tcl_GetString(objv[2]);
            JGid ppid(ppidStr);

            int ackc7;
            int seqnum;
            result = Tcl_GetIntFromObj(interp, objv[3], &ackc7);
            if (result != TCL_OK)
            {
                return result;
            }
            result = Tcl_GetIntFromObj(interp, objv[4], &seqnum);
            if (result != TCL_OK)
            {
                return result;
            }
            string errw7 = Tcl_GetString(objv[5]);
            ProcProgVerification ppv(ackc7, seqnum, errw7);
            vector<ProcProgVerification> ppvs;
            ppvs.push_back(ppv);
            result = pp->verified(ppid, ppvs);

            break;
        }
        break;
    case PP_DUMP:
        {
            pp->dump();
            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;
}

