/***************************************************************************
 *                          Zanoza Modeler v2.x                            *
 *      This is unpublished propietary source code of Zanoza Software.     *
 *      The copyright notice does not evidence any actual or intended      *
 *                    publication of such source code.                     *
 *                                                                         *
 *                   Copyright (c) 2002 Zanoza Software.                   *
 *                                                                         *
 *                        All rights reserved.                             *
 ***************************************************************************
 *--------------------------------------------------------------------------
 * @author:   Oleg M.
 *--------------------------------------------------------------------------
 * @purpose:  ZModeler 2.x serialization helpers
 *--------------------------------------------------------------------------
 * @histroy: 06.12.2003. Created
 */
#ifndef zmserializationhelper_h_included
#define zmserializationhelper_h_included

#include <core/io/ISerializeable.h>
#include <core/INamed.h>
#include <scene/IBoundable.h>
#include <scene/ITransformable.h>

namespace core
{
  namespace io
  {
    struct tChunkInfo
    {
      tChunkInfo() {m_dwType = Z3D_ID_DATA; m_dwID = m_dwSize = m_dwVersion = 0;}
      DWORD                     m_dwType;
      DWORD                     m_dwID;
      DWORD                     m_dwVersion;
      DWORD                     m_dwSize;
    };
    //
    // helper for reading chunks from stream: autoseek support
    //
    struct tAutoSeekChunkInfo : public tChunkInfo
    {
      tAutoSeekChunkInfo(core::io::IStream* pStream) : tChunkInfo()
      {
        m_pStream = pStream;
        m_dwPos = pStream->getPosition();
        pStream->read(this, sizeof(tChunkInfo));
      }
      ~tAutoSeekChunkInfo()
      {
        m_pStream->seekTo(m_dwPos + m_dwSize + sizeof(tChunkInfo));
      }
      DWORD m_dwPos;
      ZPtr<core::io::IStream>     m_pStream;
    };


    //--------------------------------------------
    //  CChunk
    //--------------------------------------------
    class DLL_LINKAGE CChunk
    {
    protected:
      CChunk() {}
    public:
      CChunk(core::io::IStream* pStream, 
             DWORD dwType, DWORD dwID, DWORD dwVersion=0);
      virtual ~CChunk();
    protected:
    //-----------------------
    // data members:
    //-----------------------
      ZPtr<core::io::IStream> m_pStream;
      DWORD                   m_dwStartedFrom;//location in stream;
    };//class

    //--------------------------------------------
    //  CDataChunk
    //--------------------------------------------
    class DLL_LINKAGE CDataChunk : public CChunk
    {
    protected:
      CDataChunk() : CChunk() {}
    public:
      CDataChunk(core::io::IStream* pStream, DWORD dwID, DWORD dwVersion=0) : CChunk (pStream, Z3D_ID_DATA, dwID, dwVersion) {}
      virtual ~CDataChunk() {}
    };//class



//-------------------------------------------------------
// @name : ZAPICALL splitPath
// Splits supplied filename to path, filename and extension
// @param  ZString strPathName           : [in]  full filename
// @param ZString& strPath               : [out] path (without trailing '\')
// @param ZString& strFile               : [out] file title
// @param ZString& strExt                : [out] file extension (without leading '.')
//
// @return DLL_LINKAGE ZRESULT : 
//-------------------------------------------------------
    DLL_LINKAGE ZRESULT ZAPICALL splitPath( ZString strPathName, 
                                            ZString& strPath,
                                            ZString& strFile,
                                            ZString& strExt);
//-------------------------------------------------------
// @name : ZAPICALL writeDeclaration
// Function writes standard declaration chunk.
// @param PCTSTR pszClassName            : class name for re-creation
// @param core::io::ISerializeable* pSerial : serializeable (added to map)
// @param services::IOpenSaveService* pSrv : 
//
// @return DLL_LINKAGE ZRESULT : 
//-------------------------------------------------------
    DLL_LINKAGE ZRESULT ZAPICALL writeDeclaration(
                                      core::io::IStream* pStream,
                                      LPCTSTR pszClassName, 
                                      core::io::ISerializeable* pSerial, 
                                      services::IOpenSaveService* pSrv,
                                      DWORD dwVersion=0,
                                      LPCTSTR pszResolvationName = NULL);


    DLL_LINKAGE ZRESULT ZAPICALL registerSerializeable(ZUnknown* pUnk, bool bHold=true);
    DLL_LINKAGE ZRESULT ZAPICALL registerSerializeable(LPCTSTR strClass, eReCreationMode mode);
    DLL_LINKAGE ZRESULT ZAPICALL writeString(core::io::IStream* pStream, LPCTSTR str);
    DLL_LINKAGE ZRESULT ZAPICALL readString(core::io::IStream* pStream, ZString& str);
    inline void writeLong(core::io::IStream* pStream, const long n) {pStream->write(&n, sizeof(n)); }
    DLL_LINKAGE ZRESULT ZAPICALL writeInterface(core::io::IStream* pStream, services::IOpenSaveService* pSrv, ZUnknown* pUnk);
    DLL_LINKAGE ZRESULT ZAPICALL readInterface(core::io::IStream* pStream, services::IOpenSaveService* pSrv, LPCTSTR _iid, void** ppIntr);
    //returns amount of bytes written. writes in JPEG format
    DLL_LINKAGE DWORD ZAPICALL   writeThumbnail(core::io::IStream* pStream);

//-------------------------------
//
//    Serialization operators
//
//-------------------------------
    DLL_LINKAGE void write(ZEntityBase& b, IStream*& pStream);
    DLL_LINKAGE void read (ZEntityBase& b, IStream*& pStream);
    DLL_LINKAGE void write(ZVertex& v, IStream*& pStream);
    DLL_LINKAGE void read (ZVertex& v, IStream*& pStream);
    DLL_LINKAGE void write(ZPoly& p, IStream*& pStream);
    DLL_LINKAGE void read (ZPoly& p, IStream*& pStream);
    DLL_LINKAGE void write(core::INamed* pNamed, IStream*& pStream);
    DLL_LINKAGE void read (core::INamed* pNamed, IStream*& pStream);
    DLL_LINKAGE void write(scene::IBoundable* pBoundable, IStream*& pStream);
    DLL_LINKAGE void read (scene::IBoundable* pBoundable, IStream*& pStream);
    DLL_LINKAGE void write(scene::ITransformable* pTrans, IStream*& pStream);
    DLL_LINKAGE void read (scene::ITransformable* pTrans, IStream*& pStream);
    template <class T> void write(ZSequence<T>& seq, IStream*& pStream)
    {
      long len = seq.length();
      pStream->write(&len, sizeof(long));
      pStream->write(seq.getBuffer(), sizeof(T)*len);
    }
    template <class T> void read(ZSequence<T>& seq, IStream*& pStream)
    {
      long len;
      pStream->read(&len, sizeof(long));
      seq.length(len);
      pStream->read(seq.getBuffer(), sizeof(T)*len);
    }

  };//io
};//core


#endif //zmserializationhelper_h_included

