/**********************************************************************
 *
 *    FILE:            ProxyNode.cpp
 *
 *    DESCRIPTION:    Read/Write osg::ProxyNode in binary format to disk.
 *
 *    CREATED BY:        Auto generated by iveGenerate
 *                    and later modified by Rune Schmidt Jensen.
 *
 *    HISTORY:        Created 24.3.2003
 *
 *    Copyright 2003 VR-C
 **********************************************************************/

#include <osgDB/WriteFile>
#include <osgDB/ReadFile>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <osg/Notify>

#include "Exception.h"
#include "ProxyNode.h"
#include "Node.h"

using namespace ive;
/*
for(osgDB::FilePathList::iterator itr=osgDB::getDataFilePathList().begin(); itr!=osgDB::getDataFilePathList().end(); ++itr)
printf("#1######%s\n", itr->c_str());
for(osgDB::FilePathList::const_iterator itrO=in->getOptions()->getDatabasePathList().begin(); itrO!=in->getOptions()->getDatabasePathList().end(); ++itrO)
printf("#2######%s\n", itrO->c_str());
namespace osgDB {
class PushAndPopDataPath
{
    public:
        PushAndPopDataPath(const std::string& path)
        {
            getDataFilePathList().push_front(path);
        }

        ~PushAndPopDataPath()
        {
            getDataFilePathList().pop_front();
        }
};
}
*/

void ProxyNode::write(DataOutputStream* out)
{
    // Write ProxyNode's identification.
    out->writeInt(IVEPROXYNODE);

    // If the osg class is inherited by any other class we should also write this to file.
    osg::Node* node = dynamic_cast<osg::Node*>(this);
    if(node)
    {
        static_cast<ive::Node*>(node)->write(out);
    }
    else
        out_THROW_EXCEPTION("ProxyNode::write(): Could not cast this osg::ProxyNode to an osg::Node.");

    out->writeFloat(getRadius());
    out->writeInt(getCenterMode());
    out->writeVec3(getCenter());

    if (out->getVersion() >= VERSION_0045)
    {
        out->writeInt(getLoadingExternalReferenceMode());
    }

    out->writeUInt(getNumFileNames());
    unsigned int numChildrenToWriteOut = 0;
    unsigned int i;

    std::string writeDirectory;
    if (!(out->getOptions()->getDatabasePathList().empty())) writeDirectory = out->getOptions()->getDatabasePathList().front();

    if (!writeDirectory.empty()) writeDirectory = writeDirectory + "/";

    bool writeOutExternalIVEFIles = !out->getIncludeExternalReferences() && out->getWriteExternalReferenceFiles() && !out->getUseOriginalExternalReferences();

    for(i=0; i<getNumFileNames(); i++)
    {
        if (getFileName(i).empty())
        {
            out->writeString("");

            if (i<getNumChildren()) ++numChildrenToWriteOut;
        }
        else
        {
            if(!writeOutExternalIVEFIles)
            {
                out->writeString(getFileName(i));
            }
            else
            {
                std::string ivename = writeDirectory + osgDB::getStrippedName(getFileName(i)) +".ive";
                out->writeString(ivename);
            }
        }
    }

    if(out->getIncludeExternalReferences()) //--------- inlined mode
    {
        out->writeUInt(getNumChildren());
        for(i=0; i<getNumChildren(); i++)
        {
            out->writeNode(getChild(i));
        }
    }
    else //----------------------------------------- no inlined mode
    {
        out->writeUInt(numChildrenToWriteOut);

        for(i=0; i<getNumFileNames(); i++)
        {
            if (i<getNumChildren())
            {
                if (getFileName(i).empty())
                {
                    out->writeNode(getChild(i));
                }
                else if(out->getWriteExternalReferenceFiles())
                {
                    if(!writeOutExternalIVEFIles)
                    {
                        if (!out->getExternalFileWritten(getFileName(i)))
                        {
                            osgDB::writeNodeFile(*getChild(i), getFileName(i));
                            out->setExternalFileWritten(getFileName(i), true);
                        }
                    }
                    else
                    {
                        std::string ivename = writeDirectory + osgDB::getStrippedName(getFileName(i)) +".ive";
                        if (!out->getExternalFileWritten(ivename))
                        {
                            osgDB::writeNodeFile(*getChild(i), ivename);
                            out->setExternalFileWritten(ivename, true);
                        }
                    }
                }
            }
        }
    }
}

void ProxyNode::read(DataInputStream* in)
{
    // Peek on ProxyNode's identification.
    int id = in->peekInt();
    if(id == IVEPROXYNODE)
    {
        // Read ProxyNode's identification.
        id = in->readInt();
        // If the osg class is inherited by any other class we should also read this from file.
        osg::Node* nodePtr = dynamic_cast<osg::Node*>(this);
        if(nodePtr)
        {
            ((ive::Node*)(nodePtr))->read(in);
        }
        else
            in_THROW_EXCEPTION("ProxyNode::read(): Could not cast this osg::ProxyNode to an osg::Node.");

        if (in->getOptions() && !in->getOptions()->getDatabasePathList().empty())
        {
            const std::string& path = in->getOptions()->getDatabasePathList().front();
            if (!path.empty())
            {
                setDatabasePath(path);
            }
        }

        setRadius(in->readFloat());
        setCenterMode((osg::ProxyNode::CenterMode)in->readInt());
        setCenter(in->readVec3());

        if (in->getVersion() >= VERSION_0045)
        {
            setLoadingExternalReferenceMode( (osg::ProxyNode::LoadingExternalReferenceMode)in->readInt() );
        }

        unsigned int numFileNames = in->readUInt();
        unsigned int i;
        for(i=0; i<numFileNames; i++)
        {
            setFileName(i, in->readString());
        }

        unsigned int numChildren = in->readUInt();
        for(i=0; i<numChildren; i++)
        {
            osgDB::FilePathList& fpl = ((osgDB::ReaderWriter::Options*)in->getOptions())->getDatabasePathList();
            fpl.push_front( fpl.empty() ? osgDB::getFilePath(getFileName(i)) : fpl.front()+'/'+ osgDB::getFilePath(getFileName(i)));
            addChild(in->readNode());
            fpl.pop_front();
        }

        if( in->getLoadExternalReferenceFiles() )
        {
            for(i=0; i<numFileNames; i++)
            {
                if(i>=numChildren && !getFileName(i).empty())
                {
                    osgDB::FilePathList& fpl = ((osgDB::ReaderWriter::Options*)in->getOptions())->getDatabasePathList();
                    fpl.push_front( fpl.empty() ? osgDB::getFilePath(getFileName(i)) : fpl.front()+'/'+ osgDB::getFilePath(getFileName(i)));
                    osg::ref_ptr<osg::Node> node = osgDB::readRefNodeFile(getFileName(i), in->getOptions());
                    fpl.pop_front();

                    if(node)
                    {
                        insertChild(i, node);
                    }
                }
            }
        }
    }
    else
    {
        in_THROW_EXCEPTION("ProxyNode::read(): Expected ProxyNode identification.");
    }
}
