/*
 * 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 "Cache.hpp"
#include "ReflectionBasedAutoSerializer.hpp"
#include "PdxIdentityFieldAttribute.hpp"
#include "Serializable.hpp"
#pragma warning(disable:4091)
#include <msclr/lock.h>
#include "ExceptionTypes.hpp"
#include "impl/DotNetTypes.hpp"
#include "TypeRegistry.hpp"

namespace Apache
{
  namespace Geode
  {
    namespace Client
    {
      ref class FieldWrapper
      {
      private:
        //static readonly Module Module = typeof(Program).Module;
        static array<Type^>^ oneObj = gcnew array<Type^>(1) { Type::GetType("System.Object") };
        static array<Type^>^ twoObj = gcnew array<Type^>(2) { Type::GetType("System.Object"), Type::GetType("System.Object") };
        delegate void MySetter(Object^ t1, Object^ t2);
        delegate Object^ MyGetter(Object^ t1);

        static Type^ setterDelegateType = Type::GetType("Apache.Geode.Client.FieldWrapper+MySetter");
        static Type^ getterDelegateType = Type::GetType("Apache.Geode.Client.FieldWrapper+MyGetter");

        FieldInfo^ m_fi;
        String^    m_fieldName;
        bool       m_isIdentityField;
        FieldType  m_fieldType;
        int        m_pdxType;

        MyGetter^ m_getter;
        MySetter^ m_setter;

        static MySetter^ createFieldSetter(FieldInfo^ fieldInfo)
        {
          DynamicMethod^ dynam = gcnew DynamicMethod("", Internal::DotNetTypes::VoidType , twoObj, fieldInfo->DeclaringType, true);
          ILGenerator^ il = dynam->GetILGenerator();

          if (!fieldInfo->IsStatic)
            pushInstance(il, fieldInfo->DeclaringType);

          il->Emit(OpCodes::Ldarg_1);
          unboxIfNeeded(il, fieldInfo->FieldType);
          il->Emit(OpCodes::Stfld, fieldInfo);
          il->Emit(OpCodes::Ret);

          return (MySetter^)dynam->CreateDelegate( setterDelegateType );
        }

        static MyGetter^ createFieldGetter(FieldInfo^ fieldInfo)
            {
              DynamicMethod^ dynam = gcnew DynamicMethod( "", Internal::DotNetTypes::ObjectType, oneObj, fieldInfo->DeclaringType, true);
              ILGenerator^ il = dynam->GetILGenerator();

              if (!fieldInfo->IsStatic)
                pushInstance(il, fieldInfo->DeclaringType);

              il->Emit(OpCodes::Ldfld, fieldInfo);
              boxIfNeeded(il, fieldInfo->FieldType);
              il->Emit(OpCodes::Ret);

              return (MyGetter^)dynam->CreateDelegate(getterDelegateType);
            }

        static void boxIfNeeded(ILGenerator^ il, Type^ type)
            {
              if (type->IsValueType)
                il->Emit(OpCodes::Box, type);
            }

        static void pushInstance( ILGenerator^ il, Type^ type)
            {
              il->Emit(OpCodes::Ldarg_0);
              if (type->IsValueType)
                il->Emit(OpCodes::Unbox, type);
            }

        static void unboxIfNeeded( ILGenerator^ il, Type^ type)
            {
              if (type->IsValueType)
                il->Emit(OpCodes::Unbox_Any, type);
            }
        public:
        FieldWrapper(FieldInfo^ fi, String^ fieldName, bool isIdentityField, FieldType  fieldtype)
            {
              m_fi = fi;
              m_fieldName = fieldName;
              m_isIdentityField = isIdentityField;
              m_fieldType = fieldtype;

              m_setter = createFieldSetter(fi);
              m_getter = createFieldGetter(fi);
            }

        property bool isIdentityField
            {
              bool get(){return m_isIdentityField;}
            }

        property Type^ FType
            {
               Type^ get() {return m_fi->FieldType;}
            }

        property String^ FieldName
            {
             String^ get(){return m_fieldName;}
            }

        property FieldInfo^ FI
            {
              FieldInfo^  get(){return m_fi;}
            }
        
        void SetFieldValue(Object^ parent, Object^ val)
            {
              m_setter(parent, val);
            }

        Object^ GetFieldValue(Object^ parent)
            {
              return m_getter(parent);
            }

        void SerializeField(IPdxWriter^ w, Object^ value)
            {
              switch(m_fieldType)
              {
                case FieldType::BOOLEAN:
                  w->WriteBoolean(m_fieldName, (bool)value);
                break;
			          case FieldType::BYTE:
                  w->WriteByte(m_fieldName, (SByte)value);
                break;
			          case FieldType::CHAR:
                  w->WriteChar(m_fieldName, (Char)value);
                break;
			          case FieldType::SHORT:
                  w->WriteShort(m_fieldName, (short)value);
                break;
			          case FieldType::USHORT:
                  w->WriteShort(m_fieldName, (short)(UInt16)value);
                break;
			          case FieldType::INT:
                  w->WriteInt(m_fieldName, (int)value);
                break;
			          case FieldType::UINT:
                  w->WriteInt(m_fieldName, (int)(UInt32)value);
                break;
			          case FieldType::LONG:
                  w->WriteLong(m_fieldName, (Int64)value);
                break;
			          case FieldType::ULONG:
                  w->WriteLong(m_fieldName, (long)(UInt64)value);
                break;
			          case FieldType::FLOAT:
                  w->WriteFloat(m_fieldName, (float)value);
                break;
			          case FieldType::DOUBLE:
                  w->WriteDouble(m_fieldName, (double)value);
                break;
			          case FieldType::DATE:
                  w->WriteDate(m_fieldName, (DateTime)value);
                break;
			          case FieldType::STRING:
                  w->WriteString(m_fieldName, (String^)value);
                break;
			          case FieldType::OBJECT:
                  w->WriteObject(m_fieldName, value);
                break;
			          case FieldType::BOOLEAN_ARRAY:
                  w->WriteBooleanArray(m_fieldName, (array<bool>^)value);
                break;
			          case FieldType::CHAR_ARRAY:
                  w->WriteCharArray(m_fieldName, (array<Char>^)value);
                break;
			          case FieldType::BYTE_ARRAY:
                  w->WriteByteArray(m_fieldName, (array<Byte>^)value);
                break;
			          case FieldType::SBYTE_ARRAY:
                  w->WriteByteArray(m_fieldName, (array<Byte>^)value);
                break;
			          case FieldType::SHORT_ARRAY:
                  w->WriteShortArray(m_fieldName, (array<Int16>^)value);
                break;
			          case FieldType::USHORT_ARRAY:
                  w->WriteShortArray(m_fieldName, (array<Int16>^)(array<UInt16>^)value);
                break;
			          case FieldType::INT_ARRAY:
                  w->WriteIntArray(m_fieldName, (array<Int32>^)value);
                break;
			          case FieldType::UINT_ARRAY:
                  w->WriteIntArray(m_fieldName, (array<Int32>^)(array<UInt32>^)value);
                break;
			          case FieldType::LONG_ARRAY:
                  w->WriteLongArray(m_fieldName, (array<Int64>^)value);
                break;
			          case FieldType::ULONG_ARRAY:
                  w->WriteLongArray(m_fieldName, (array<Int64>^)(array<UInt64>^)value);
                break;
			          case FieldType::FLOAT_ARRAY:
                  w->WriteFloatArray(m_fieldName, (array<float>^)value);
                break;
			          case FieldType::DOUBLE_ARRAY:
                  w->WriteDoubleArray(m_fieldName, (array<double>^)value);
                break;
			          case FieldType::STRING_ARRAY:
                  w->WriteStringArray(m_fieldName, (array<String^>^)value);
                break;
			          case FieldType::OBJECT_ARRAY:
                  w->WriteObjectArray(m_fieldName, safe_cast<System::Collections::Generic::List<Object^>^>(value));
                break;
			          case FieldType::ARRAY_OF_BYTE_ARRAYS:
                  w->WriteArrayOfByteArrays(m_fieldName, (array<array<Byte>^>^)value);
                break;
			          case FieldType::GUID:
                     w->WriteByteArray(m_fieldName, ((System::Guid)value).ToByteArray());
                     break;
			          case FieldType::DECIMAL:
                     w->WriteIntArray(m_fieldName, Decimal::GetBits((System::Decimal)value));
                     break;
			          default:
                  throw gcnew IllegalStateException("Not found FieldType: " + m_fieldType.ToString());
              }
            }

        Object^ DeserializeField(IPdxReader^ r)
            {
             switch(m_fieldType)
              {
                case FieldType::BOOLEAN:
                  return r->ReadBoolean(m_fieldName);
                break;
			          case FieldType::BYTE:
                  return r->ReadByte(m_fieldName);
                break;
			          case FieldType::SBYTE:
                  return r->ReadByte(m_fieldName);
                break;
			          case FieldType::CHAR:
                  return r->ReadChar(m_fieldName);
                break;
			          case FieldType::SHORT:
                  return r->ReadShort(m_fieldName);
                break;
                case FieldType::USHORT:
                  return (USHORT)r->ReadShort(m_fieldName);
                break;
			          case FieldType::INT:
                  return r->ReadInt(m_fieldName);
                break;
			          case FieldType::UINT:
                  return (UINT)r->ReadInt(m_fieldName);
                break;
			          case FieldType::LONG:
                  return r->ReadLong(m_fieldName);
                break;
			          case FieldType::ULONG:
                  return (ULONGLONG)r->ReadLong(m_fieldName);
                break;
			          case FieldType::FLOAT:
                  return r->ReadFloat(m_fieldName);
                break;
			          case FieldType::DOUBLE:
                  return r->ReadDouble(m_fieldName);
                break;
			          case FieldType::DATE:
                  return r->ReadDate(m_fieldName);
                break;
			          case FieldType::STRING:
                  return r->ReadString(m_fieldName);
                break;
			          case FieldType::OBJECT:
                  return r->ReadObject(m_fieldName);
                break;
			          case FieldType::BOOLEAN_ARRAY:
                  return r->ReadBooleanArray(m_fieldName);
                break;
			          case FieldType::CHAR_ARRAY:
                  return r->ReadCharArray(m_fieldName);
                break;
			          case FieldType::BYTE_ARRAY:
                  return r->ReadByteArray(m_fieldName);
                break;
			          case FieldType::SBYTE_ARRAY:
                  return (array<SByte>^)r->ReadByteArray(m_fieldName);
                break;
			          case FieldType::SHORT_ARRAY:
                  return r->ReadShortArray(m_fieldName);
                break;
			          case FieldType::USHORT_ARRAY:
                  return (array<USHORT>^)r->ReadShortArray(m_fieldName);
                break;
			          case FieldType::INT_ARRAY:
                  return r->ReadIntArray(m_fieldName);
                break;
			          case FieldType::UINT_ARRAY:
                  return (array<UINT>^)r->ReadIntArray(m_fieldName);
                break;
			          case FieldType::LONG_ARRAY:
                  return r->ReadLongArray(m_fieldName);
                break;
			          case FieldType::ULONG_ARRAY:
                  return (array<ULONGLONG>^)r->ReadLongArray(m_fieldName);
                break;
			          case FieldType::FLOAT_ARRAY:
                  return r->ReadFloatArray(m_fieldName);
                break;
			          case FieldType::DOUBLE_ARRAY:
                  return r->ReadDoubleArray(m_fieldName);
                break;
			          case FieldType::STRING_ARRAY:
                  return r->ReadStringArray(m_fieldName);
                break;
			          case FieldType::OBJECT_ARRAY:
                  return r->ReadObjectArray(m_fieldName);
                break;
			          case FieldType::ARRAY_OF_BYTE_ARRAYS:
                  return r->ReadArrayOfByteArrays(m_fieldName);
                break;
			          case FieldType::GUID:
                  return gcnew Guid(r->ReadByteArray(m_fieldName));
                break;
			          case FieldType::DECIMAL:
                  return gcnew Decimal(r->ReadIntArray(m_fieldName));
                break;
			          default:
                  throw gcnew IllegalStateException("Not found FieldType: " + m_fieldType.ToString());
              }
              return nullptr;
            }
      };

      ReflectionBasedAutoSerializer::ReflectionBasedAutoSerializer()
      {
        PdxIdentityFieldAttribute^ pif = gcnew PdxIdentityFieldAttribute();
        PdxIdentityFieldAttributeType = pif->GetType();
        classNameVsFieldInfoWrapper = gcnew Dictionary<String^, List<FieldWrapper^>^>();
      }

		  bool ReflectionBasedAutoSerializer::ToData( Object^ o,IPdxWriter^ writer )
      {
        serializeFields(o, writer);
        return true;
      }

      Object^ ReflectionBasedAutoSerializer::FromData(String^ o, IPdxReader^ reader)
      {
        return deserializeFields(o, reader);
      }

      void ReflectionBasedAutoSerializer::serializeFields(Object^ o,IPdxWriter^ writer )
      {
        Type^ ty = o->GetType();
        for each(FieldWrapper^ fi in GetFields(o->GetType()))
        {
          Object^ originalValue = fi->GetFieldValue(o);

          // Transform the value, in case the base class is overridden 
          originalValue = WriteTransform(fi->FI, fi->FType, originalValue);

          fi->SerializeField(writer, originalValue);

          if(fi->isIdentityField)
          {
            writer->MarkIdentityField(fi->FieldName);
          }
        }
      }

      Object^ ReflectionBasedAutoSerializer::deserializeFields(String^ className, IPdxReader^ reader)
      {
        Object^ object = this->CreateObject(className, reader->Cache);

        for each(FieldWrapper^ fi in GetFields(object->GetType()))
        {
          Object^ serializeValue = fi->DeserializeField(reader);

          // Transform the value, in case the base class is overridden 
          serializeValue = ReadTransform( fi->FI, fi->FType, serializeValue);

          fi->SetFieldValue(object, serializeValue);
        }

        return object;
      }
      
      Object^ ReflectionBasedAutoSerializer::CreateObject(String^ className, Cache^ cache)
      {
        return cache->TypeRegistry->CreateObject(className);
      }

      bool ReflectionBasedAutoSerializer::IsPdxIdentityField(FieldInfo^ fi)
      {
        array<Object^>^ cAttr=  fi->GetCustomAttributes(PdxIdentityFieldAttributeType, true);
        if(cAttr != nullptr && cAttr->Length > 0)
        {
          PdxIdentityFieldAttribute^ pifa = (PdxIdentityFieldAttribute^)(cAttr[0]);
          return true;
        }
        return false;
      }

      List<FieldWrapper^>^ ReflectionBasedAutoSerializer::GetFields(Type^ domaimType)
      {
        List<FieldWrapper^>^ retVal = nullptr;

        String^ className = domaimType->FullName;
        System::Collections::Generic::Dictionary<String^, List<FieldWrapper^>^>^ tmp = classNameVsFieldInfoWrapper;
        tmp->TryGetValue(className, retVal);
        if(retVal != nullptr)
          return retVal;
        msclr::lock lockInstance(classNameVsFieldInfoWrapper);
        {
          tmp = classNameVsFieldInfoWrapper;
          tmp->TryGetValue(className, retVal);
          if(retVal != nullptr)
            return retVal;
           
          List<FieldWrapper^>^ collectFields = gcnew List<FieldWrapper^>();
          while(domaimType != nullptr)
          {
            for each(FieldInfo^ fi in domaimType->GetFields(BindingFlags::Public| BindingFlags::NonPublic | BindingFlags::Instance
              |BindingFlags::DeclaredOnly
              ))
            {
              if(!fi->IsNotSerialized && !fi->IsStatic && !fi->IsLiteral && !fi->IsInitOnly)
              {
                //to ignore the fild
                if(IsFieldIncluded(fi, domaimType))
                {                      
                  //This are all hooks which app can implement

                  String^ fieldName = GetFieldName(fi, domaimType);
                  bool isIdentityField = IsIdentityField(fi, domaimType);
                  FieldType ft = GetFieldType(fi, domaimType);
  
                  FieldWrapper^ fw = gcnew FieldWrapper(fi, fieldName, isIdentityField, ft);

                  collectFields->Add(fw);
                }
              }
            }
            domaimType = domaimType->BaseType;
          }
          tmp = gcnew System::Collections::Generic::Dictionary<String^, List<FieldWrapper^>^>(classNameVsFieldInfoWrapper); 
          tmp->Add(className, collectFields);
          classNameVsFieldInfoWrapper = tmp;

          return collectFields;
        }
      }

      String^ ReflectionBasedAutoSerializer::GetFieldName(FieldInfo^ fi, Type^ type)
      {
        return fi->Name;
      }

      bool ReflectionBasedAutoSerializer::IsIdentityField(FieldInfo^ fi, Type^ type)
      {
        return IsPdxIdentityField(fi);
      }

      FieldType ReflectionBasedAutoSerializer::GetFieldType(FieldInfo^ fi, Type^ type)
      {
        return getPdxFieldType(fi->FieldType);
      }

      bool ReflectionBasedAutoSerializer::IsFieldIncluded(FieldInfo^ fi, Type^ type)
      {
        return true;
      }

      Object^ ReflectionBasedAutoSerializer::WriteTransform(FieldInfo^ fi, Type^ type, Object^ originalValue)
      {
        return originalValue;
      }

      Object^ ReflectionBasedAutoSerializer::ReadTransform(FieldInfo^ fi, Type^ type, Object^ serializeValue)
      {
        return serializeValue;
      }

      FieldType ReflectionBasedAutoSerializer::getPdxFieldType( Type^ type)
      {
        if(type->Equals(Internal::DotNetTypes::IntType))
        {
          return FieldType::INT;
        }
        else if(type->Equals(Internal::DotNetTypes::UIntType))
        {
          return FieldType::UINT;
        }
        else if(type->Equals(Internal::DotNetTypes::StringType))
        {
          return FieldType::STRING;
        }
        else if(type->Equals(Internal::DotNetTypes::BooleanType))
        {
          return FieldType::BOOLEAN;
        }
        else if(type->Equals(Internal::DotNetTypes::FloatType))
        {
          return FieldType::FLOAT;
        }
        else if(type->Equals(Internal::DotNetTypes::DoubleType))
        {
          return FieldType::DOUBLE;
        }
        else if(type->Equals(Internal::DotNetTypes::CharType))
        {
          return FieldType::CHAR;
        }
        else if(type->Equals(Internal::DotNetTypes::SByteType))
        {
          return FieldType::BYTE;
        }
        else if(type->Equals(Internal::DotNetTypes::ShortType))
        {
          return FieldType::SHORT;
        }
        else if(type->Equals(Internal::DotNetTypes::UShortType))
        {
          return FieldType::USHORT;
        }
        else if(type->Equals(Internal::DotNetTypes::LongType))
        {
          return FieldType::LONG;
        }
        else if(type->Equals(Internal::DotNetTypes::ULongType))
        {
          return FieldType::ULONG;
        }
        else if(type->Equals(Internal::DotNetTypes::ByteArrayType))
        {
          return FieldType::BYTE_ARRAY;
        }
        else if(type->Equals(Internal::DotNetTypes::SByteArrayType))
        {
          return FieldType::SBYTE_ARRAY;
        }
        else if(type->Equals(Internal::DotNetTypes::DoubleArrayType))
        {
          return FieldType::DOUBLE_ARRAY;
        }
        else if(type->Equals(Internal::DotNetTypes::FloatArrayType))
        {
          return FieldType::FLOAT_ARRAY;
        }
        else if(type->Equals(Internal::DotNetTypes::ShortArrayType))
        {
          return FieldType::SHORT_ARRAY;
        }
        else if(type->Equals(Internal::DotNetTypes::UShortArrayType))
        {
          return FieldType::USHORT_ARRAY;
        }
        else if(type->Equals(Internal::DotNetTypes::IntArrayType))
        {
          return FieldType::INT_ARRAY;
        }
        else if(type->Equals(Internal::DotNetTypes::UIntArrayType))
        {
          return FieldType::UINT_ARRAY;
        }
        else if(type->Equals(Internal::DotNetTypes::LongArrayType))
        {
          return FieldType::LONG_ARRAY;
        }
        else if(type->Equals(Internal::DotNetTypes::ULongArrayType))
        {
          return FieldType::ULONG_ARRAY;
        }
        else if(type->Equals(Internal::DotNetTypes::BoolArrayType))
        {
          return FieldType::BOOLEAN_ARRAY;
        }
        else if(type->Equals(Internal::DotNetTypes::CharArrayType))
        {
          return FieldType::CHAR_ARRAY;
        }
        else if(type->Equals(Internal::DotNetTypes::StringArrayType))
        {
          return FieldType::STRING_ARRAY;
        }
        else if(type->Equals(Internal::DotNetTypes::DateType))
        {
          return FieldType::DATE;
        }
        else if(type->Equals(Internal::DotNetTypes::ByteArrayOfArrayType))
        {
          return FieldType::ARRAY_OF_BYTE_ARRAYS;
        }
        else if(type->Equals(Internal::DotNetTypes::GuidType))
        {
          return FieldType::GUID;
        }
        else if(type->Equals(Internal::DotNetTypes::DecimalType))
        {
          return FieldType::DECIMAL;
        }
        /*else if(type->Equals(Internal::DotNetTypes::ObjectArrayType))
        {
          //Giving more preference to arraylist instead of Object[] in java side
          //return this->WriteObjectArray(fieldName, safe_cast<System::Collections::Generic::List<Object^>^>(fieldValue));
          return FieldType::OBJECT_ARRAY;
        }*/
        else
        {
          return FieldType::OBJECT;
        }
      }
    }  // namespace Client
  }  // namespace Geode
}  // namespace Apache
