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




#include "PdxFieldType.hpp"
#include "../begin_native.hpp"
#include <PdxTypes.hpp>
#include <PdxFieldType.hpp>
#include "../end_native.hpp"


using namespace System;

namespace Apache
{
  namespace Geode
  {
    namespace Client
    {

      namespace Internal
      {
        Int32 PdxFieldType::SequenceId::get()
        {
          return m_sequenceId;
        }

        String^ PdxFieldType::FieldName::get()
        {
          return m_fieldName;
        }

        String^ PdxFieldType::ClassName::get()
        {
          return m_className;
        }

        Byte PdxFieldType::TypeId::get()
        {
          return m_typeId;
        }

        bool PdxFieldType::IsVariableLengthType::get()
        {
          return m_isVariableLengthType;
        }

        Int32 PdxFieldType::Size::get()
        {
          return m_fixedSize;
        }

        Int32 PdxFieldType::VarLenFieldIdx::get()
        {
          return m_varLenFieldIdx;
        }

        Int32 PdxFieldType::VarLenOffsetIndex::get()
        {
          return m_vlOffsetIndex;
        }

        void PdxFieldType::VarLenOffsetIndex::set(Int32 val)
        {
          m_vlOffsetIndex = val;
        }

        Int32 PdxFieldType::RelativeOffset::get()
        {
          return m_relativeOffset;
        }

        void PdxFieldType::RelativeOffset::set(Int32 val)
        {
          m_relativeOffset = val;
        }

        //it compares fieldname and type-id
        bool PdxFieldType::Equals(Object^ otherObj)
        {
          if (otherObj == nullptr)
            return false;

          PdxFieldType^ otherFieldType = dynamic_cast<PdxFieldType^>(otherObj);

          if (otherFieldType == nullptr)
            return false;

          if (otherFieldType == this)
            return true;

          if (otherFieldType->m_fieldName == m_fieldName && otherFieldType->m_typeId == m_typeId)
            return true;

          return false;
        }

        Int32 PdxFieldType::GetHashCode()
        {
          int hash = m_cachedHashcode;
          if (hash == 0)
          {
            if (m_fieldName != nullptr)
            {
              hash = hash * 31 + m_fieldName->GetHashCode();
            }

            hash = hash * 31 + m_typeId;
            if (hash == 0)
              hash = 1;
            m_cachedHashcode = hash;
          }

          return m_cachedHashcode;
        }

        void PdxFieldType::ToData(DataOutput^ output)
        {
          output->WriteString(m_fieldName);
          output->WriteInt32(m_sequenceId);
          output->WriteInt32(m_varLenFieldIdx);
          output->WriteByte(m_typeId);

          output->WriteInt32(m_relativeOffset);
          output->WriteInt32(m_vlOffsetIndex);
          output->WriteBoolean(m_isIdentityField);
        }

        void PdxFieldType::FromData(DataInput^ input)
        {
          m_fieldName = input->ReadString();
          m_sequenceId = input->ReadInt32();
          m_varLenFieldIdx = input->ReadInt32();
          m_typeId = input->ReadByte();

          m_relativeOffset = input->ReadInt32();
          m_vlOffsetIndex = input->ReadInt32();
          m_isIdentityField = input->ReadBoolean();

          m_fixedSize = getFixedTypeSize();

          if (m_fixedSize != -1)
            m_isVariableLengthType = false;
          else
            m_isVariableLengthType = true;
        }

        Int32 PdxFieldType::getFixedTypeSize()
        {
          switch (m_typeId)
          {
          case PdxFieldTypes::BYTE:
            return PdxTypes::kPdxByteSize;
          case PdxFieldTypes::BOOLEAN:
            return PdxTypes::kPdxBooleanSize;
          case PdxFieldTypes::SHORT:
            return PdxTypes::kPdxShortSize;
          case PdxFieldTypes::CHAR:
            return PdxTypes::kPdxCharSize;
          case PdxFieldTypes::INT:
            return PdxTypes::kPdxIntegerSize;
          case PdxFieldTypes::FLOAT:
            return PdxTypes::kPdxFloatSize;
          case PdxFieldTypes::LONG:
            return PdxTypes::kPdxLongSize;
          case PdxFieldTypes::DOUBLE:
            return PdxTypes::kPdxDoubleSize;
          case PdxFieldTypes::DATE:
            return PdxTypes::kPdxDateSize;

          default:
            return -1;
          }  // namespace Client
        }  // namespace Geode
      }  // namespace Apache

    }
  }
}
