/*
 * 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 "../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::BYTE_SIZE;
          case PdxFieldTypes::BOOLEAN:
            return PdxTypes::BOOLEAN_SIZE;
          case PdxFieldTypes::SHORT:
            return PdxTypes::SHORT_SIZE;
          case PdxFieldTypes::CHAR:
            return PdxTypes::CHAR_SIZE;
          case PdxFieldTypes::INT:
            return PdxTypes::INTEGER_SIZE;
          case PdxFieldTypes::FLOAT:
            return PdxTypes::FLOAT_SIZE;
          case PdxFieldTypes::LONG:
            return PdxTypes::LONG_SIZE;
          case PdxFieldTypes::DOUBLE:
            return PdxTypes::DOUBLE_SIZE;
          case PdxFieldTypes::DATE:
            return PdxTypes::DATE_SIZE;

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

    }
  }
}
