/****************************************************************************
**
** https://www.qxorm.com/
** Copyright (C) 2013 XDL Team (ic-east.com)
**
** This file is part of the QxOrm library
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any
** damages arising from the use of this software
**
** Commercial Usage
** Licensees holding valid commercial QxOrm licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and XDL Team
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file 'license.gpl3.txt' included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met : http://www.gnu.org/copyleft/gpl.html
**
** If you are unsure which license is appropriate for your use, or
** if you have questions regarding the use of this file, please contact :
** ic-east.com
**
****************************************************************************/

#include <QxPrecompiled.h>

#include <QxSerialize/QDataStream/QxSerializeQDataStream_qx_registered_class.h>
#include <QxSerialize/QxSerializeCheckInstance.h>

#include <QxMemLeak/mem_leak.h>

namespace qx
{

   QDataStream &QxSerializeRegistered_Helper::save(QDataStream &stream, IxClass *pClass, const void *pOwner)
   {
      if (!pClass || !pOwner)
      {
         qAssert(false);
         return stream;
      }
      stream << (quint32)(13939);
      bool bJustId = false;

      if (qx::serialization::helper::QxSerializeCheckInstance::contains(pOwner, pClass))
      {
         bJustId = true;
         stream << bJustId;
         qx::IxDataMember *pId = pClass->getId(true);
         if (!pId)
         {
            return stream;
         }
         QVariant val = pId->toVariant(pOwner);
         stream << val;
         return stream;
      }
      qx::serialization::helper::QxSerializeCheckInstance checker(pOwner, pClass);
      stream << bJustId;
      Q_UNUSED(checker);

      do
      {
         qx::QxSerializeRegistered_Helper::saveHelper(stream, pClass, pOwner);
         pClass = pClass->getBaseClass();
      } while (pClass != NULL);

      return stream;
   }

   QDataStream &QxSerializeRegistered_Helper::load(QDataStream &stream, IxClass *pClass, void *pOwner)
   {
      if (!pClass || !pOwner)
      {
         qAssert(false);
         return stream;
      }

      bool bJustId = false;
      quint32 magic = 0;
      stream >> magic;
      if ((magic != 13937) && (magic != 13939))
      {
         qDebug("[QxOrm] qx::QxSerializeRegistered_Helper::load() : %s", "input binary data is not valid");
         return stream;
      }
      if (magic > 13937)
      {
         stream >> bJustId;
      }

      if (bJustId)
      {
         qx::IxDataMember *pId = pClass->getId(true);
         if (!pId)
         {
            return stream;
         }
         QVariant val;
         stream >> val;
         pId->fromVariant(pOwner, val);
         return stream;
      }

      do
      {
         qx::QxSerializeRegistered_Helper::loadHelper(stream, pClass, pOwner);
         pClass = pClass->getBaseClass();
      } while (pClass != NULL);

      return stream;
   }

   void QxSerializeRegistered_Helper::saveHelper(QDataStream &stream, IxClass *pClass, const void *pOwner)
   {
      IxDataMemberX *pDataMemberX = (pClass ? pClass->getDataMemberX() : NULL);
      if (!pDataMemberX)
      {
         return;
      }
      qint16 iVersion = static_cast<qint16>(pClass->getVersion());
      stream << iVersion;

      for (long l = 0; l < pDataMemberX->count(); l++)
      {
         IxDataMember *pDataMember = pDataMemberX->get(l);
         if (!pDataMember || !pDataMember->getSerialize())
         {
            continue;
         }
         if (pDataMember->getVersion() > static_cast<long>(iVersion))
         {
            qAssert(false);
            continue;
         }
         QVariant vValue = pDataMember->toVariant(pOwner, -1, qx::cvt::context::e_serialize_registered);
         stream << vValue;
      }
   }

   void QxSerializeRegistered_Helper::loadHelper(QDataStream &stream, IxClass *pClass, void *pOwner)
   {
      IxDataMemberX *pDataMemberX = (pClass ? pClass->getDataMemberX() : NULL);
      if (!pDataMemberX)
      {
         return;
      }
      qint16 iVersion = 0;
      stream >> iVersion;

      for (long l = 0; l < pDataMemberX->count(); l++)
      {
         IxDataMember *pDataMember = pDataMemberX->get(l);
         if (!pDataMember || !pDataMember->getSerialize())
         {
            continue;
         }
         if (pDataMember->getVersion() > static_cast<long>(iVersion))
         {
            continue;
         }
         QVariant vValue;
         stream >> vValue;
         pDataMember->fromVariant(pOwner, vValue, -1, qx::cvt::context::e_serialize_registered);
      }
   }

} // namespace qx
