/*
 *
 * VRML to RW converter plug-in
 */

/****************************************************************************
 *  
 * VRML 2.0 to RW3.0 Converter
 * Copyright (C) 1998 Criterion Technologies
 *
 * Author  : Damian Scallan 
 *
 * Module  : Route.h
 *                                                                         
 * Purpose : Creates route information between nodes
 *          
 ****************************************************************************/

#include "rpplugin.h"
#include "route.h"
#include "symtable.h"
#include "abstractnode.h"
#include "vrmlnodetype.h"
#include "rpvrmlanim.h"
#include "rpvrml.h"
#include "llinklist.h"

static const char __RWUNUSED__ rcsid[] =
    "@@(#)$Id: route.c,v 1.21 2001/01/26 12:10:52 johns Exp $";

RouteRec           *
Route_CreateRecord(AbstractNode * toNode, const RwChar * toEvent)
{
    RWFUNCTION(RWSTRING("Route_CreateRecord"));
    RWASSERT(toNode);
    RWASSERT(toEvent);

    if (toNode && toEvent)
    {
        RouteRec           *routeRec;

        routeRec = (RouteRec *) RwMalloc(sizeof(RouteRec));
        if (routeRec)
        {
            routeRec->toNode = toNode;
            rwstrdup(routeRec->toEvent, toEvent);
        }

        RWRETURN(routeRec);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(NULL);
}

RwBool
Route_DestroyRecord(RouteRec * routeRec)
{
    RWFUNCTION(RWSTRING("Route_DestroyRecord"));
    RWASSERT(routeRec);

    if (routeRec)
    {
        RwFree(routeRec->toEvent);
        RwFree(routeRec);

        RWRETURN(TRUE);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(FALSE);
}

RwBool
Route_Set(const RwChar * fromName, const RwChar * eventOutName,
          const RwChar * toName, const RwChar * eventInName)
{
    RWFUNCTION(RWSTRING("Route_Set"));
    RWASSERT(fromName);
    RWASSERT(eventOutName);
    RWASSERT(toName);
    RWASSERT(eventInName);

    if (fromName && eventOutName && toName && eventInName)
    {
        AbstractNode       *fromANode = NULL;
        AbstractNode       *toANode = NULL;
        VrmlNodeType       *fromTNode = NULL;
        VrmlNodeType       *toTNode = NULL;
        RwInt32             outType, inType;
        RouteRec           *routeOutRec = NULL;
        RouteRec           *routeInRec = NULL;
        AbstractEvent      *aeOut, *aeIn;

        /* get 'from node' */
        fromANode = SymTab_GetEntry(fromName);
        if (!fromANode)
        {
            RWRETURN(FALSE);
        }
        fromTNode = TypeList_find(fromANode->name);
        RWASSERT(fromTNode);

        /* get 'to node' */
        toANode = SymTab_GetEntry(toName);
        if (!toANode)
        {
            RWRETURN(FALSE);
        }
        toTNode = TypeList_find(toANode->name);
        RWASSERT(toTNode);

        /* setup event records */
        outType = VrmlNodeType_hasEventOut(fromTNode, eventOutName);
        inType = VrmlNodeType_hasEventIn(toTNode, eventInName);
        if ((outType == 0) || (inType == 0) || (inType != outType))
        {
            RWRETURN(FALSE);
        }

        /* get the eventIns & eventOuts */
        routeOutRec = Route_CreateRecord(toANode, eventInName);
        if (!routeOutRec)
        {
            RWRETURN(FALSE);
        }
        aeOut =
            AbstractNode_GetAbstractEventOut(fromANode, eventOutName);
        if (!aeOut)
        {
            /* doesn't already exits so add */
            aeOut = AbstractEvent_Create(eventOutName, outType);
            if (!aeOut)
            {
                RWRETURN(FALSE);
            }
            LLinkList_AddData(&fromANode->eventOuts, aeOut);
        }
        LLinkList_AddData(&aeOut->eventRecList, routeOutRec);

        routeInRec = Route_CreateRecord(fromANode, eventOutName);
        if (!routeInRec)
        {
            RWRETURN(FALSE);
        }
        aeIn = AbstractNode_GetAbstractEventIn(toANode, eventInName);
        if (!aeIn)
        {
            /* doesn't already exits so add */
            aeIn = AbstractEvent_Create(eventInName, inType);
            if (!aeIn)
            {
                RWRETURN(FALSE);
            }
            LLinkList_AddData(&toANode->eventIns, aeIn);
        }
        LLinkList_AddData(&aeIn->eventRecList, routeInRec);

        RWRETURN(FALSE);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(FALSE);
}

AbstractNode       *
Route_GetFirstCoordInterpolator(AbstractNode * an)
{
    RWFUNCTION(RWSTRING("Route_GetFirstCoordInterpolator"));
    RWASSERT(an);

    if (an)
    {
        AbstractEvent      *ae = NULL;

        ae = AbstractNode_GetAbstractEventIn(an, RWSTRING("set_point"));
        if (ae)
        {
            RouteRec           *routeRec;

            LLinkList_IteratorReset(&ae->eventRecList);
            routeRec =
                (RouteRec *) LLinkList_IteratorNext(&ae->eventRecList);
            if (routeRec)
            {
                RWRETURN(routeRec->toNode);
            }
        }

        RWRETURN(NULL);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(FALSE);
}

AbstractNode       *
Route_GetNextCoordInterpolator(AbstractNode * an)
{
    RWFUNCTION(RWSTRING("Route_GetNextCoordInterpolator"));
    RWASSERT(an);

    if (an)
    {
        AbstractEvent      *ae = NULL;

        ae = AbstractNode_GetAbstractEventIn(an, RWSTRING("set_point"));
        if (ae)
        {
            RouteRec           *routeRec;

            routeRec =
                (RouteRec *) LLinkList_IteratorNext(&ae->eventRecList);
            if (routeRec)
            {
                RWRETURN(routeRec->toNode);
            }
        }

        RWRETURN(NULL);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(NULL);
}

/* temp code to test new animation stuff */
AbstractNode       *
Route_GetFirstOrientationInterpolator(AbstractNode * an)
{
    RWFUNCTION(RWSTRING("Route_GetFirstOrientationInterpolator"));
    RWASSERT(an);

    if (an)
    {
        AbstractEvent      *ae = NULL;

        ae = AbstractNode_GetAbstractEventIn(an,
                                             RWSTRING("set_rotation"));
        if (ae)
        {
            RouteRec           *routeRec;

            LLinkList_IteratorReset(&ae->eventRecList);
            routeRec =
                (RouteRec *) LLinkList_IteratorNext(&ae->eventRecList);
            if (routeRec)
            {
                RWRETURN(routeRec->toNode);
            }
        }

        RWRETURN(NULL);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(NULL);
}

AbstractNode       *
Route_GetNextOrientationInterpolator(AbstractNode * an)
{
    RWFUNCTION(RWSTRING("Route_GetNextOrientationInterpolator"));
    RWASSERT(an);

    if (an)
    {
        AbstractEvent      *ae = NULL;

        ae = AbstractNode_GetAbstractEventIn(an,
                                             RWSTRING("set_rotation"));
        if (ae)
        {
            RouteRec           *routeRec;

            routeRec =
                (RouteRec *) LLinkList_IteratorNext(&ae->eventRecList);
            if (routeRec)
            {
                RWRETURN(routeRec->toNode);
            }
        }

        RWRETURN(NULL);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(NULL);
}

AbstractNode       *
Route_GetFirstPositionInterpolator(AbstractNode * an)
{
    RWFUNCTION(RWSTRING("Route_GetFirstPositionInterpolator"));
    RWASSERT(an);

    if (an)
    {
        AbstractEvent      *ae = NULL;

        ae = AbstractNode_GetAbstractEventIn(an,
                                             RWSTRING
                                             ("set_translation"));
        if (ae)
        {
            RouteRec           *routeRec;

            LLinkList_IteratorReset(&ae->eventRecList);
            routeRec =
                (RouteRec *) LLinkList_IteratorNext(&ae->eventRecList);
            if (routeRec)
            {
                RWRETURN(routeRec->toNode);
            }
        }

        RWRETURN(NULL);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(NULL);
}

AbstractNode       *
Route_GetNextPositionInterpolator(AbstractNode * an)
{
    RWFUNCTION(RWSTRING("Route_GetNextPositionInterpolator"));
    RWASSERT(an);

    if (an)
    {
        AbstractEvent      *ae = NULL;

        ae = AbstractNode_GetAbstractEventIn(an,
                                             RWSTRING
                                             ("set_translation"));
        if (ae)
        {
            RouteRec           *routeRec;

            routeRec =
                (RouteRec *) LLinkList_IteratorNext(&ae->eventRecList);
            if (routeRec)
            {
                RWRETURN(routeRec->toNode);
            }
        }

        RWRETURN(NULL);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(NULL);
}

AbstractNode       *
Route_GetFirstScaleInterpolator(AbstractNode * an)
{
    RWFUNCTION(RWSTRING("Route_GetFirstScaleInterpolator"));
    RWASSERT(an);

    if (an)
    {
        AbstractEvent      *ae = NULL;

        ae = AbstractNode_GetAbstractEventIn(an, RWSTRING("set_scale"));
        if (ae)
        {
            RouteRec           *routeRec;

            LLinkList_IteratorReset(&ae->eventRecList);
            routeRec =
                (RouteRec *) LLinkList_IteratorNext(&ae->eventRecList);
            if (routeRec)
            {
                RWRETURN(routeRec->toNode);
            }
        }

        RWRETURN(NULL);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(NULL);
}

AbstractNode       *
Route_GetNextScaleInterpolator(AbstractNode * an)
{
    RWFUNCTION(RWSTRING("Route_GetNextScaleInterpolator"));
    RWASSERT(an);

    if (an)
    {
        AbstractEvent      *ae = NULL;

        ae = AbstractNode_GetAbstractEventIn(an, RWSTRING("set_scale"));
        if (ae)
        {
            RouteRec           *routeRec;

            routeRec =
                (RouteRec *) LLinkList_IteratorNext(&ae->eventRecList);
            if (routeRec)
            {
                RWRETURN(routeRec->toNode);
            }
        }

        RWRETURN(NULL);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(NULL);
}

AbstractNode       *
Route_GetFirstScaleOrientInterpolator(AbstractNode * an)
{
    RWFUNCTION(RWSTRING("Route_GetFirstScaleOrientInterpolator"));
    RWASSERT(an);

    if (an)
    {
        AbstractEvent      *ae = NULL;

        ae = AbstractNode_GetAbstractEventIn(an,
                                             RWSTRING
                                             ("set_scaleOrientation"));
        if (ae)
        {
            RouteRec           *routeRec;

            LLinkList_IteratorReset(&ae->eventRecList);
            routeRec =
                (RouteRec *) LLinkList_IteratorNext(&ae->eventRecList);
            if (routeRec)
            {
                RWRETURN(routeRec->toNode);
            }
        }

        RWRETURN(NULL);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(NULL);
}

AbstractNode       *
Route_GetNextScaleOrientInterpolator(AbstractNode * an)
{
    RWFUNCTION(RWSTRING("Route_GetNextScaleOrientInterpolator"));
    RWASSERT(an);

    if (an)
    {
        AbstractEvent      *ae = NULL;

        ae = AbstractNode_GetAbstractEventIn(an,
                                             RWSTRING
                                             ("set_scaleOrientation"));
        if (ae)
        {
            RouteRec           *routeRec;

            routeRec =
                (RouteRec *) LLinkList_IteratorNext(&ae->eventRecList);
            if (routeRec)
            {
                RWRETURN(routeRec->toNode);
            }
        }

        RWRETURN(NULL);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(NULL);
}

AbstractNode       *
Anstractnode_GetTimeSensor(AbstractNode * an)
{
    RWFUNCTION(RWSTRING("Anstractnode_GetTimeSensor"));
    RWASSERT(an);

    if (an)
    {
        AbstractEvent      *ae = NULL;

        ae = AbstractNode_GetAbstractEventIn(an, RWSTRING("set_time"));
        if (ae)
        {
            RouteRec           *routeRec;

            routeRec =
                (RouteRec *) LLinkList_IteratorNext(&ae->eventRecList);
            if (routeRec)
            {
                RWRETURN(routeRec->toNode);
            }
        }

        ae = AbstractNode_GetAbstractEventIn(an,
                                             RWSTRING("set_fraction"));
        if (ae)
        {
            RouteRec           *routeRec;

            routeRec =
                (RouteRec *) LLinkList_IteratorNext(&ae->eventRecList);
            if (routeRec)
            {
                RWRETURN(routeRec->toNode);
            }
        }

        RWRETURN(NULL);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(NULL);
}

RwBool
Route_IsNodeStatic(AbstractNode * an)
{
    RWFUNCTION(RWSTRING("Route_IsNodeStatic"));
    RWASSERT(an);

    if (an)
    {
        AbstractEvent      *ae = NULL;

        ae = AbstractNode_GetAbstractEventIn(an, "set_point");
        if (ae)
        {
            RWRETURN(FALSE);
        }

        ae = AbstractNode_GetAbstractEventIn(an, "set_rotation");
        if (ae)
        {
            RWRETURN(FALSE);
        }

        ae = AbstractNode_GetAbstractEventIn(an, "set_translation");
        if (ae)
        {
            RWRETURN(FALSE);
        }

        ae = AbstractNode_GetAbstractEventIn(an, "set_scale");
        if (ae)
        {
            RWRETURN(FALSE);
        }

        /* must be static */
        RWRETURN(TRUE);
    }

    RWERROR((E_RW_NULLP));
    RWRETURN(FALSE);
}
