/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * PdxRemoteWriter.cpp
 *
 *  Created on: Nov 3, 2011
 *      Author: npatel
 */

#include "PdxRemoteWriter.hpp"
#include "PdxTypeRegistry.hpp"

namespace apache {
namespace geode {
namespace client {

PdxRemoteWriter::PdxRemoteWriter(
    DataOutput& output, std::shared_ptr<PdxType> pdxType,
    std::shared_ptr<PdxRemotePreservedData> preservedData,
    std::shared_ptr<PdxTypeRegistry> pdxTypeRegistry)
    : PdxLocalWriter(output, pdxType, pdxTypeRegistry),
      m_preserveDataIdx(0),
      m_currentDataIdx(-1),
      m_remoteTolocalMapLength(0) {
  m_preserveData = preservedData;
  if (m_pdxType != nullptr) {
    m_remoteTolocalMap = m_pdxType->getRemoteToLocalMap();
    m_remoteTolocalMapLength = m_pdxType->getTotalFields();
  }
  m_pdxClassName = pdxType->getPdxClassName();

  initialize();
}

PdxRemoteWriter::PdxRemoteWriter(
    DataOutput& output, std::string pdxClassName,
    std::shared_ptr<PdxTypeRegistry> pdxTypeRegistry)
    : PdxLocalWriter(output, nullptr, pdxClassName, pdxTypeRegistry),
      m_preserveDataIdx(0),
      m_currentDataIdx(-1),
      m_remoteTolocalMapLength(0) {
  m_preserveData = nullptr;
  if (m_pdxType != nullptr) {
    m_remoteTolocalMapLength = m_pdxType->getTotalFields();
    m_remoteTolocalMap = m_pdxType->getRemoteToLocalMap();
  }
  initialize();
}

void PdxRemoteWriter::endObjectWriting() {
  writePreserveData();
  // write header
  PdxLocalWriter::writePdxHeader();
}

void PdxRemoteWriter::writePreserveData() {
  m_currentDataIdx++;  // it starts from -1
  LOGDEBUG("PdxRemoteWriter::writePreserveData m_currentDataIdx = %d",
           m_currentDataIdx);
  LOGDEBUG("PdxRemoteWriter::writePreserveData m_remoteTolocalMap->Length = %d",
           m_remoteTolocalMapLength);

  if (m_preserveData != nullptr) {
    while (m_currentDataIdx < m_remoteTolocalMapLength) {
      if (m_remoteTolocalMap[m_currentDataIdx] ==
          -1)  // need to add preserve data with offset
      {
        PdxLocalWriter::addOffset();
        for (size_t i = 0;
             i < (m_preserveData->getPreservedData(m_preserveDataIdx)).size();
             i++) {
          m_dataOutput->write(
              (m_preserveData->getPreservedData(m_preserveDataIdx))[i]);
        }
        m_preserveDataIdx++;
        m_currentDataIdx++;
      } else if (m_remoteTolocalMap[m_currentDataIdx] ==
                 -2)  // need to add preserve data WITHOUT offset
      {
        for (size_t i = 0;
             i < (m_preserveData->getPreservedData(m_preserveDataIdx)).size();
             i++) {
          m_dataOutput->write(
              (m_preserveData->getPreservedData(m_preserveDataIdx))[i]);
        }
        m_preserveDataIdx++;
        m_currentDataIdx++;

      } else {
        break;  // continue writing local data..
      }
    }
  }
}

void PdxRemoteWriter::initialize() {
  // this is default case
  if (m_preserveData == nullptr) {
    m_pdxType = getPdxTypeRegistry()->getLocalPdxType(m_pdxClassName);
  }
}

bool PdxRemoteWriter::isFieldWritingStarted() {
  return m_currentDataIdx != -1;  // field writing NOT started. do we need
                                  // this??
}

PdxWriter& PdxRemoteWriter::writeUnreadFields(
    std::shared_ptr<PdxUnreadFields> unread) {
  PdxLocalWriter::writeUnreadFields(unread);
  m_remoteTolocalMap = m_pdxType->getRemoteToLocalMap();
  m_remoteTolocalMapLength = m_pdxType->getTotalFields();
  return *this;
}

PdxWriter& PdxRemoteWriter::writeChar(
    const std::string& fieldName, char16_t value) {
  writePreserveData();
  PdxLocalWriter::writeChar(fieldName, value);
  return *this;
}
PdxWriter& PdxRemoteWriter::writeBoolean(const std::string& fieldName,
                                         bool value) {
  writePreserveData();
  PdxLocalWriter::writeBoolean(fieldName, value);
  return *this;
}
PdxWriter& PdxRemoteWriter::writeByte(const std::string& fieldName,
                                      int8_t value) {
  writePreserveData();
  PdxLocalWriter::writeByte(fieldName, value);
  return *this;
}
PdxWriter& PdxRemoteWriter::writeShort(const std::string& fieldName,
                                       int16_t value) {
  writePreserveData();
  PdxLocalWriter::writeShort(fieldName, value);
  return *this;
}
PdxWriter& PdxRemoteWriter::writeInt(const std::string& fieldName,
                                     int32_t value) {
  writePreserveData();
  PdxLocalWriter::writeInt(fieldName, value);
  return *this;
}
PdxWriter& PdxRemoteWriter::writeLong(const std::string& fieldName,
                                      int64_t value) {
  writePreserveData();
  PdxLocalWriter::writeLong(fieldName, value);
  return *this;
}
PdxWriter& PdxRemoteWriter::writeFloat(const std::string& fieldName,
                                       float value) {
  writePreserveData();
  PdxLocalWriter::writeFloat(fieldName, value);
  return *this;
}
PdxWriter& PdxRemoteWriter::writeDouble(const std::string& fieldName,
                                        double value) {
  writePreserveData();
  PdxLocalWriter::writeDouble(fieldName, value);
  return *this;
}
PdxWriter& PdxRemoteWriter::writeDate(const std::string& fieldName,
                                      std::shared_ptr<CacheableDate> date) {
  writePreserveData();
  PdxLocalWriter::writeDate(fieldName, date);
  return *this;
}

PdxWriter& PdxRemoteWriter::writeString(
    const std::string& fieldName, const std::string& value) {
  writePreserveData();
  PdxLocalWriter::writeString(fieldName, value);
  return *this;
}

PdxWriter& PdxRemoteWriter::writeStringArray(
    const std::string& fieldName, const std::vector<std::string>& array) {
  writePreserveData();
  PdxLocalWriter::writeStringArray(fieldName, array);
  return *this;
}

PdxWriter& PdxRemoteWriter::writeObject(
    const std::string& fieldName, std::shared_ptr<Serializable> value) {
  writePreserveData();
  PdxLocalWriter::writeObject(fieldName, value);
  return *this;
}
PdxWriter& PdxRemoteWriter::writeBooleanArray(const std::string& fieldName,
                                              const std::vector<bool>& array) {
  writePreserveData();
  PdxLocalWriter::writeBooleanArray(fieldName, array);
  return *this;
}

PdxWriter& PdxRemoteWriter::writeCharArray(
    const std::string& fieldName, const std::vector<char16_t>& array) {
  writePreserveData();
  PdxLocalWriter::writeCharArray(fieldName, array);
  return *this;
}

PdxWriter& PdxRemoteWriter::writeByteArray(
    const std::string& fieldName, const std::vector<int8_t>& array) {
  writePreserveData();
  PdxLocalWriter::writeByteArray(fieldName, array);
  return *this;
}
PdxWriter& PdxRemoteWriter::writeShortArray(const std::string& fieldName,
                                            const std::vector<int16_t>& array) {
  writePreserveData();
  PdxLocalWriter::writeShortArray(fieldName, array);
  return *this;
}
PdxWriter& PdxRemoteWriter::writeIntArray(const std::string& fieldName,
                                          const std::vector<int32_t>& array) {
  writePreserveData();
  PdxLocalWriter::writeIntArray(fieldName, array);
  return *this;
}
PdxWriter& PdxRemoteWriter::writeLongArray(const std::string& fieldName,
                                           const std::vector<int64_t>& array) {
  writePreserveData();
  PdxLocalWriter::writeLongArray(fieldName, array);
  return *this;
}
PdxWriter& PdxRemoteWriter::writeFloatArray(const std::string& fieldName,
                                            const std::vector<float>& array) {
  writePreserveData();
  PdxLocalWriter::writeFloatArray(fieldName, array);
  return *this;
}
PdxWriter& PdxRemoteWriter::writeDoubleArray(const std::string& fieldName,
                                             const std::vector<double>& array) {
  writePreserveData();
  PdxLocalWriter::writeDoubleArray(fieldName, array);
  return *this;
}
PdxWriter& PdxRemoteWriter::writeObjectArray(
    const std::string& fieldName, std::shared_ptr<CacheableObjectArray> array) {
  writePreserveData();
  PdxLocalWriter::writeObjectArray(fieldName, array);
  return *this;
}
PdxWriter& PdxRemoteWriter::writeArrayOfByteArrays(
    const std::string& fieldName, int8_t* const* const byteArrays,
    int arrayLength, const int* elementLength) {
  writePreserveData();
  PdxLocalWriter::writeArrayOfByteArrays(fieldName, byteArrays, arrayLength,
                                         elementLength);
  return *this;
}
std::shared_ptr<PdxTypeRegistry> PdxRemoteWriter::getPdxTypeRegistry() const {
  return m_pdxTypeRegistry;
}

}  // namespace client
}  // namespace geode
}  // namespace apache
