/*
 * 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.
 */

#pragma once

#ifndef GEODE_PDXFIELDTYPE_H_
#define GEODE_PDXFIELDTYPE_H_

#include <string>

#include <geode/CacheableString.hpp>
#include <geode/DataInput.hpp>
#include <geode/DataOutput.hpp>
#include <geode/PdxFieldTypes.hpp>
#include <geode/Serializable.hpp>
#include <geode/internal/DataSerializableInternal.hpp>
#include <geode/internal/geode_globals.hpp>

namespace apache {
namespace geode {
namespace client {

class APACHE_GEODE_EXPORT PdxFieldType
    : public internal::DataSerializableInternal {
 private:
  std::string m_fieldName;
  std::string m_className;
  PdxFieldTypes m_typeId;
  uint32_t m_sequenceId;

  bool m_isVariableLengthType;
  bool m_isIdentityField;
  int32_t m_fixedSize;
  int32_t m_varLenFieldIdx;

  int32_t m_vlOffsetIndex;
  int32_t m_relativeOffset;

  int32_t getFixedTypeSize() const;

 public:
  PdxFieldType(std::string fieldName, std::string className,
               PdxFieldTypes typeId, int32_t sequenceId,
               bool isVariableLengthType, int32_t fixedSize,
               int32_t varLenFieldIdx);

  PdxFieldType();

  inline const char* getFieldName() { return m_fieldName.c_str(); }

  inline const char* getClassName() { return m_className.c_str(); }

  inline PdxFieldTypes getTypeId() { return m_typeId; }

  inline uint8_t getSequenceId() { return m_sequenceId; }

  inline bool IsVariableLengthType() { return m_isVariableLengthType; }

  bool getIdentityField() const { return m_isIdentityField; }

  int32_t getVarLenFieldIdx() const { return m_varLenFieldIdx; }

  void setVarLenOffsetIndex(int32_t value) { m_vlOffsetIndex = value; }

  void setRelativeOffset(int32_t value) { m_relativeOffset = value; }

  int32_t getFixedSize() const { return m_fixedSize; }
  void setIdentityField(bool identityField) {
    m_isIdentityField = identityField;
  }

  // TODO:add more getters for the remaining members.

  void toData(DataOutput& output) const override;

  virtual void fromData(DataInput& input) override;

  virtual size_t objectSize() const override {
    auto size = sizeof(PdxFieldType);
    size += m_className.length();
    size += m_fieldName.length();
    return size;
  }

  std::string toString() const override;

  ~PdxFieldType() override = default;

  bool equals(std::shared_ptr<PdxFieldType> otherObj);

  int32_t getVarLenOffsetIndex() const { return m_vlOffsetIndex; }

  int32_t getRelativeOffset() const { return m_relativeOffset; }
};

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

#endif  // GEODE_PDXFIELDTYPE_H_
