/*
 * 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.
 */
/*
 * PdxType.cpp
 *
 *  Created on: Nov 3, 2011
 *      Author: npatel
 */

#include "PdxType.hpp"
#include "PdxHelper.hpp"
#include "PdxFieldType.hpp"
#include "Utils.hpp"
#include "PdxTypeRegistry.hpp"
#include "PdxHelper.hpp"
#include <ace/OS.h>

namespace apache {
namespace geode {
namespace client {

const char* PdxType::m_javaPdxClass = "org.apache.geode.pdx.internal.PdxType";

PdxType::~PdxType() noexcept {
  _GEODE_SAFE_DELETE(m_pdxFieldTypes);
  _GEODE_SAFE_DELETE_ARRAY(m_remoteToLocalFieldMap);
  _GEODE_SAFE_DELETE_ARRAY(m_localToRemoteFieldMap);
}

PdxType::PdxType(PdxTypeRegistry& pdxTypeRegistry,
                 const std::string& pdxDomainClassName, bool isLocal)
    : Serializable(),
      m_pdxFieldTypes(new std::vector<std::shared_ptr<PdxFieldType>>()),
      m_className(pdxDomainClassName),
      m_geodeTypeId(0),
      m_isLocal(isLocal),
      m_numberOfVarLenFields(0),
      m_varLenFieldIdx(0),
      m_numberOfFieldsExtra(0),
      m_isVarLenFieldAdded(false),
      m_remoteToLocalFieldMap(nullptr),
      m_localToRemoteFieldMap(nullptr),
      m_noJavaClass(false),
      m_pdxTypeRegistry(pdxTypeRegistry) {}

void PdxType::toData(DataOutput& output) const {
  output.write(static_cast<int8_t>(DSCode::DataSerializable));  // 45
  output.write(static_cast<int8_t>(DSCode::Class));             // 43
  output.writeString(m_javaPdxClass);

  // m_className
  output.writeString(m_className);

  // m_noJavaClass
  output.writeBoolean(m_noJavaClass);

  // m_geodeTypeId
  output.writeInt(m_geodeTypeId);

  // m_varLenFieldIdx
  output.writeInt(m_varLenFieldIdx);

  output.writeArrayLen(static_cast<int32_t>(m_pdxFieldTypes->size()));

  for (std::vector<std::shared_ptr<PdxFieldType>>::iterator it =
           m_pdxFieldTypes->begin();
       it != m_pdxFieldTypes->end(); ++it) {
    auto pdxPtr = *it;
    pdxPtr->toData(output);
  }
}

void PdxType::fromData(DataInput& input) {
  input.read();        // ignore dsByte
  input.read();        // ignore classByte
  input.readString();  // ignore classtypeId

  m_className = input.readString();

  m_noJavaClass = input.readBoolean();

  m_geodeTypeId = input.readInt32();

  m_varLenFieldIdx = input.readInt32();

  int len = input.readArrayLength();

  bool foundVarLenType = false;

  for (int i = 0; i < len; i++) {
    auto pft = std::make_shared<PdxFieldType>();
    pft->fromData(input);

    m_pdxFieldTypes->push_back(pft);

    if (pft->IsVariableLengthType() == true) foundVarLenType = true;
  }

  // as m_varLenFieldIdx starts with 0
  if (m_varLenFieldIdx != 0) {
    m_numberOfVarLenFields = m_varLenFieldIdx + 1;
  } else if (foundVarLenType) {
    m_numberOfVarLenFields = 1;
  }

  InitializeType();
}

void PdxType::addFixedLengthTypeField(const std::string& fieldName,
                                      const std::string& className,
                                      PdxFieldTypes typeId, int32_t size) {
  if (m_fieldNameVsPdxType.find(fieldName) != m_fieldNameVsPdxType.end()) {
    throw IllegalStateException("Field: " + fieldName +
                                " is already added to PdxWriter");
  }
  auto pfxPtr = std::make_shared<PdxFieldType>(
      fieldName, className, typeId,
      static_cast<int32_t>(m_pdxFieldTypes->size()), false, size, 0);
  m_pdxFieldTypes->push_back(pfxPtr);
  m_fieldNameVsPdxType[fieldName] = pfxPtr;
}

void PdxType::addVariableLengthTypeField(const std::string& fieldName,
                                         const std::string& className,
                                         PdxFieldTypes typeId) {
  if (m_fieldNameVsPdxType.find(fieldName) != m_fieldNameVsPdxType.end()) {
    throw IllegalStateException("Field: " + fieldName +
                                " is already added to PdxWriter");
  }

  if (m_isVarLenFieldAdded) {
    m_varLenFieldIdx++;  // it initial value is zero so variable length field
                         // idx start with zero
  }
  m_numberOfVarLenFields++;
  m_isVarLenFieldAdded = true;
  auto pfxPtr = std::make_shared<PdxFieldType>(
      fieldName, className, typeId,
      static_cast<int32_t>(m_pdxFieldTypes->size()), true, -1,
      m_varLenFieldIdx);
  m_pdxFieldTypes->push_back(pfxPtr);
  m_fieldNameVsPdxType[fieldName] = pfxPtr;
}

void PdxType::initRemoteToLocal() {
  // This method is to check if we have some extra fields in remote PdxType that
  // are absent in local PdxType.
  // 1. Get local PdxType from type registry
  // 2. Get list of PdxFieldTypes from it
  // 3. Use m_pdxFieldTypes for remote PdxType, that is populated in fromData
  // 4. Iterate over local and remote PdxFieldTypes to compare individual type
  // 5. If found update in m_remoteToLocalFieldMap that field there in remote
  // type. else update m_numberOfFieldsExtra
  // 6. else update in m_remoteToLocalFieldMap that local type don't have this
  // fields
  // 7. 1 = field there in remote type
  //  -1 = local type don't have this VariableLengthType field
  //  -2 = local type don't have this FixedLengthType field

  std::shared_ptr<PdxType> localPdxType = nullptr;
  //[TODO - open this up once PdxTypeRegistry is done]
  localPdxType = m_pdxTypeRegistry.getLocalPdxType(m_className);
  m_numberOfFieldsExtra = 0;

  if (localPdxType != nullptr) {
    std::vector<std::shared_ptr<PdxFieldType>>* localPdxFields =
        localPdxType->getPdxFieldTypes();
    int32_t fieldIdx = 0;

    m_remoteToLocalFieldMap = new int32_t[m_pdxFieldTypes->size()];
    LOGDEBUG(
        "PdxType::initRemoteToLocal m_pdxFieldTypes->size() =%d AND "
        "localPdxFields->size()=%d",
        m_pdxFieldTypes->size(), localPdxFields->size());
    for (std::vector<std::shared_ptr<PdxFieldType>>::iterator remotePdxField =
             m_pdxFieldTypes->begin();
         remotePdxField != m_pdxFieldTypes->end(); ++remotePdxField) {
      bool found = false;

      for (std::vector<std::shared_ptr<PdxFieldType>>::iterator localPdxfield =
               localPdxFields->begin();
           localPdxfield != localPdxFields->end(); ++localPdxfield) {
        // PdxFieldType* remotePdx = (*(remotePdxField)).get();
        // PdxFieldType* localPdx = (*(localPdxfield)).get();
        if ((*localPdxfield)->equals(*remotePdxField)) {
          found = true;
          m_remoteToLocalFieldMap[fieldIdx++] = 1;  // field there in remote
                                                    // type
          break;
        }
      }

      if (!found) {
        // while writing take this from weakhashmap
        // local field is not in remote type
        // if((*(remotePdxField)).get()->IsVariableLengthType()) {
        if ((*remotePdxField)->IsVariableLengthType()) {
          m_remoteToLocalFieldMap[fieldIdx++] =
              -1;  // local type don't have this fields
        } else {
          m_remoteToLocalFieldMap[fieldIdx++] =
              -2;  // local type don't have this fields
        }
        m_numberOfFieldsExtra++;
      }
    }
  }
}

void PdxType::initLocalToRemote() {
  // This method is to check if we have some extra fields in remote PdxType that
  // are absent in local PdxType.
  // 1. Get local PdxType from type registry
  // 2. Get list of PdxFieldTypes from it
  // 3. Iterate over local PdxFields to compare it with remote PdxFields and if
  // they r equal that means there sequence is same mark it with -2
  // 4. Iterate over local PdxFields and remote PdxFields and if they are equal
  // then mark m_localToRemoteFieldMap with remotePdxField sequenceId
  // 5. else if local field is not in remote type then -1

  std::shared_ptr<PdxType> localPdxType = nullptr;
  localPdxType = m_pdxTypeRegistry.getLocalPdxType(m_className);

  if (localPdxType != nullptr) {
    std::vector<std::shared_ptr<PdxFieldType>>* localPdxFields =
        localPdxType->getPdxFieldTypes();

    int32_t fieldIdx = 0;
    // type which need to read/write should control local type
    int32_t localToRemoteFieldMapSize =
        static_cast<int32_t>(localPdxType->m_pdxFieldTypes->size());
    m_localToRemoteFieldMap = new int32_t[localToRemoteFieldMapSize];

    for (int32_t i = 0; i < localToRemoteFieldMapSize &&
                        i < static_cast<int32_t>(m_pdxFieldTypes->size());
         i++) {
      // PdxFieldType* localPdx = localPdxFields->at(fieldIdx).get();
      // PdxFieldType* remotePdx = m_pdxFieldTypes->at(i).get();
      if (localPdxFields->at(fieldIdx)->equals(m_pdxFieldTypes->at(i))) {
        // fields are in same order, we can read as it is
        m_localToRemoteFieldMap[fieldIdx++] = -2;
      } else {
        break;
      }
    }

    for (; fieldIdx < localToRemoteFieldMapSize;) {
      auto localPdxField = localPdxType->m_pdxFieldTypes->at(fieldIdx);
      bool found = false;

      for (std::vector<std::shared_ptr<PdxFieldType>>::iterator remotePdxfield =
               m_pdxFieldTypes->begin();
           remotePdxfield != m_pdxFieldTypes->end(); ++remotePdxfield)
      // for each(PdxFieldType^ remotePdxfield in m_pdxFieldTypes)
      {
        // PdxFieldType* localPdx = localPdxField.get();
        PdxFieldType* remotePdx = (*(remotePdxfield)).get();
        if (localPdxField->equals(*remotePdxfield)) {
          found = true;
          // store pdxfield type position to get the offset quickly
          m_localToRemoteFieldMap[fieldIdx++] = remotePdx->getSequenceId();
          break;
        }
      }

      if (!found) {
        // local field is not in remote type
        m_localToRemoteFieldMap[fieldIdx++] = -1;
      }
    }
  }
}

void PdxType::InitializeType() {
  initRemoteToLocal();  // for writing
  initLocalToRemote();  // for reading
  generatePositionMap();
}

int32_t PdxType::getFieldPosition(const std::string& fieldName,
                                  uint8_t* offsetPosition, int32_t offsetSize,
                                  int32_t pdxStreamlen) {
  auto pft = this->getPdxField(fieldName);
  if (pft != nullptr) {
    if (pft->IsVariableLengthType()) {
      return variableLengthFieldPosition(pft, offsetPosition, offsetSize);
    } else {
      return fixedLengthFieldPosition(pft, offsetPosition, offsetSize,
                                      pdxStreamlen);
    }
  }
  return -1;
}

int32_t PdxType::getFieldPosition(int32_t fieldIdx, uint8_t* offsetPosition,
                                  int32_t offsetSize, int32_t pdxStreamlen) {
  auto pft = m_pdxFieldTypes->at(fieldIdx);
  if (pft != nullptr) {
    if (pft->IsVariableLengthType()) {
      return variableLengthFieldPosition(pft, offsetPosition, offsetSize);
    } else {
      return fixedLengthFieldPosition(pft, offsetPosition, offsetSize,
                                      pdxStreamlen);
    }
  }
  return -1;
}

int32_t PdxType::fixedLengthFieldPosition(
    std::shared_ptr<PdxFieldType> fixLenField, uint8_t* offsetPosition,
    int32_t offsetSize, int32_t pdxStreamlen) {
  int32_t offset = fixLenField->getVarLenOffsetIndex();
  if (fixLenField->getRelativeOffset() >= 0) {
    // starting fields
    return fixLenField->getRelativeOffset();
  } else if (offset == -1)  // Pdx length
  {
    // there is no var len field so just subtracts relative offset from behind
    return pdxStreamlen + fixLenField->getRelativeOffset();
  } else {
    // need to read offset and then subtract relative offset
    // TODO
    return PdxHelper::readInt(
               offsetPosition +
                   (m_numberOfVarLenFields - offset - 1) * offsetSize,
               offsetSize) +
           fixLenField->getRelativeOffset();
  }
}

int32_t PdxType::variableLengthFieldPosition(
    std::shared_ptr<PdxFieldType> varLenField, uint8_t* offsetPosition,
    int32_t offsetSize) {
  int32_t offset = varLenField->getVarLenOffsetIndex();
  if (offset == -1) {
    return /*first var len field*/ varLenField->getRelativeOffset();
  } else {
    // we write offset from behind
    return PdxHelper::readInt(
        offsetPosition + (m_numberOfVarLenFields - offset - 1) * offsetSize,
        offsetSize);
  }
}

int32_t* PdxType::getLocalToRemoteMap() {
  if (m_localToRemoteFieldMap != nullptr) {
    return m_localToRemoteFieldMap;
  }

  ReadGuard guard(m_lockObj);
  if (m_localToRemoteFieldMap != nullptr) {
    return m_localToRemoteFieldMap;
  }
  initLocalToRemote();

  return m_localToRemoteFieldMap;
}

int32_t* PdxType::getRemoteToLocalMap() {
  if (m_remoteToLocalFieldMap != nullptr) {
    return m_remoteToLocalFieldMap;
  }

  ReadGuard guard(m_lockObj);
  if (m_remoteToLocalFieldMap != nullptr) {
    return m_remoteToLocalFieldMap;
  }
  initRemoteToLocal();

  return m_remoteToLocalFieldMap;
}
std::shared_ptr<PdxType> PdxType::isContains(std::shared_ptr<PdxType> first,
                                             std::shared_ptr<PdxType> second) {
  int j = 0;
  for (int i = 0; i < static_cast<int>(second->m_pdxFieldTypes->size()); i++) {
    auto secondPdt = second->m_pdxFieldTypes->at(i);
    bool matched = false;
    for (; j < static_cast<int>(first->m_pdxFieldTypes->size()); j++) {
      auto firstPdt = first->m_pdxFieldTypes->at(j);
      // PdxFieldType* firstType = firstPdt.get();
      // PdxFieldType* secondType = secondPdt.get();
      if (firstPdt->equals(secondPdt)) {
        matched = true;
        break;
      }
    }
    if (!matched) return nullptr;
  }
  return first;
}
std::shared_ptr<PdxType> PdxType::clone() {
  auto clone = std::make_shared<PdxType>(m_pdxTypeRegistry, m_className, false);
  clone->m_geodeTypeId = 0;
  clone->m_numberOfVarLenFields = m_numberOfVarLenFields;

  for (std::vector<std::shared_ptr<PdxFieldType>>::iterator it =
           m_pdxFieldTypes->begin();
       it != m_pdxFieldTypes->end(); ++it) {
    auto pdxPtr = *it;
    clone->m_pdxFieldTypes->push_back(pdxPtr);
  }
  return clone;
}
std::shared_ptr<PdxType> PdxType::isLocalTypeContains(
    std::shared_ptr<PdxType> otherType) {
  if (m_pdxFieldTypes->size() >= otherType->m_pdxFieldTypes->size()) {
    return isContains(shared_from_this(), otherType);
  }
  return nullptr;
}
std::shared_ptr<PdxType> PdxType::isRemoteTypeContains(
    std::shared_ptr<PdxType> remoteType) {
  if (m_pdxFieldTypes->size() <= remoteType->m_pdxFieldTypes->size()) {
    return isContains(remoteType, shared_from_this());
  }
  return nullptr;
}
std::shared_ptr<PdxType> PdxType::mergeVersion(
    std::shared_ptr<PdxType> otherVersion) {
  // int nTotalFields = otherVersion->m_pdxFieldTypes->size();
  std::shared_ptr<PdxType> contains = nullptr;

  if (isLocalTypeContains(otherVersion) != nullptr) return shared_from_this();

  if (isRemoteTypeContains(otherVersion) != nullptr) return otherVersion;

  // need to create new one, clone of local
  auto newone = clone();
  int varLenFields = newone->getNumberOfVarLenFields();

  for (std::vector<std::shared_ptr<PdxFieldType>>::iterator it =
           otherVersion->m_pdxFieldTypes->begin();
       it != otherVersion->m_pdxFieldTypes->end(); ++it) {
    bool found = false;
    // for each(PdxFieldType^ tmpNew in newone->m_pdxFieldTypes)
    for (std::vector<std::shared_ptr<PdxFieldType>>::iterator it2 =
             newone->m_pdxFieldTypes->begin();
         it2 != newone->m_pdxFieldTypes->end(); ++it2) {
      if ((*it2)->equals(*it)) {
        found = true;
        break;
      }
    }
    if (!found) {
      auto newFt = std::make_shared<PdxFieldType>(
          (*it)->getFieldName(), (*it)->getClassName(), (*it)->getTypeId(),
          static_cast<int32_t>(newone->m_pdxFieldTypes->size()),  // sequence id
          (*it)->IsVariableLengthType(), (*it)->getFixedSize(),
          ((*it)->IsVariableLengthType()
               ? varLenFields++ /*it increase after that*/
               : 0));
      newone->m_pdxFieldTypes->push_back(
          newFt);  // fieldnameVsPFT will happen after that
    }
  }

  newone->setNumberOfVarLenFields(varLenFields);
  if (varLenFields > 0) newone->setVarLenFieldIdx(varLenFields);

  // need to keep all versions in local version
  // m_otherVersions->Add(newone);
  return newone;
}

void PdxType::generatePositionMap() {
  bool foundVarLen = false;
  int lastVarLenSeqId = 0;
  int prevFixedSizeOffsets = 0;
  // set offsets from back first
  std::shared_ptr<PdxFieldType> previousField = nullptr;

  for (int i = static_cast<int>(m_pdxFieldTypes->size()) - 1; i >= 0; i--) {
    auto tmpft = m_pdxFieldTypes->at(i);
    std::string temp = tmpft->getFieldName();
    std::pair<std::string, std::shared_ptr<PdxFieldType>> pc(temp, tmpft);
    m_fieldNameVsPdxType.insert(pc);

    if (tmpft->IsVariableLengthType()) {
      tmpft->setVarLenOffsetIndex(tmpft->getVarLenFieldIdx());
      tmpft->setRelativeOffset(0);
      foundVarLen = true;
      lastVarLenSeqId = tmpft->getVarLenFieldIdx();
    } else {
      if (foundVarLen) {
        tmpft->setVarLenOffsetIndex(lastVarLenSeqId);
        // relative offset is subtracted from var len offsets
        tmpft->setRelativeOffset(-tmpft->getFixedSize() +
                                 previousField->getRelativeOffset());
      } else {
        tmpft->setVarLenOffsetIndex(-1);  // Pdx header length
        // relative offset is subtracted from var len offsets
        tmpft->setRelativeOffset(-tmpft->getFixedSize());
        if (previousField != nullptr) {  // boundary condition
          tmpft->setRelativeOffset(-tmpft->getFixedSize() +
                                   previousField->getRelativeOffset());
        }
      }
    }

    previousField = tmpft;
  }

  foundVarLen = false;
  prevFixedSizeOffsets = 0;
  // now do optimization till you don't fine var len
  for (uint32_t i = 0; (i < m_pdxFieldTypes->size()) && !foundVarLen; i++) {
    auto tmpft = m_pdxFieldTypes->at(i);

    if (tmpft->IsVariableLengthType()) {
      tmpft->setVarLenOffsetIndex(-1);  // first var len field
      tmpft->setRelativeOffset(prevFixedSizeOffsets);
      foundVarLen = true;
    } else {
      tmpft->setVarLenOffsetIndex(0);  // no need to read offset
      tmpft->setRelativeOffset(prevFixedSizeOffsets);
      prevFixedSizeOffsets += tmpft->getFixedSize();
    }
  }
}

bool PdxType::Equals(std::shared_ptr<PdxType> otherObj) {
  if (otherObj == nullptr) return false;

  PdxType* ot = dynamic_cast<PdxType*>(otherObj.get());

  if (ot == nullptr) return false;

  if (ot == this) return true;

  if (ot->m_pdxFieldTypes->size() != m_pdxFieldTypes->size()) return false;

  for (uint32_t i = 0; i < m_pdxFieldTypes->size(); i++) {
    if (!ot->m_pdxFieldTypes->at(i)->equals(m_pdxFieldTypes->at(i))) {
      return false;
    }
  }
  return true;
}

bool PdxType::operator<(const PdxType& other) const {
  return this->m_className < other.m_className;
}

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