/*
 * 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 "begin_native.hpp"
#include <version.h>
#include <geode/CacheLoader.hpp>
#include <geode/CacheListener.hpp>
#include <geode/FixedPartitionResolver.hpp>
#include <geode/CacheWriter.hpp>
#include <geode/Cache.hpp>
#include <CacheImpl.hpp>
#include <CacheXmlParser.hpp>
#include <DistributedSystemImpl.hpp>
#include "end_native.hpp"

#include "Cache.hpp"
#include "Serializable.hpp"
#include "DistributedSystem.hpp"
#include "SystemProperties.hpp"
#include "CacheFactory.hpp"
#include "CacheableDate.hpp"
#include "CacheableFileName.hpp"
#include "CacheableHashMap.hpp"
#include "CacheableHashSet.hpp"
#include "CacheableHashTable.hpp"
#include "CacheableIdentityHashMap.hpp"
#include "CacheableObjectArray.hpp"
#include "CacheableString.hpp"
#include "CacheableStringArray.hpp"
#include "CacheableUndefined.hpp"
#include "CacheableVector.hpp"
#include "CacheableArrayList.hpp"
#include "CacheableLinkedList.hpp"
#include "CacheableStack.hpp"
#include "CacheableObject.hpp"
#include "CacheableObjectXml.hpp"
#include "CacheableBuiltins.hpp"
#include "Log.hpp"
#include "Struct.hpp"
#include "impl/MemoryPressureHandler.hpp"
#include "impl/SafeConvert.hpp"
#include "impl/PdxType.hpp"
#include "impl/EnumInfo.hpp"
#include "impl/ManagedPersistenceManager.hpp"

// disable spurious warning
#pragma warning(disable:4091)
#include <msclr/lock.h>
#pragma warning(default:4091)


using namespace System;

using namespace Apache::Geode::Client;

namespace apache
{
  namespace geode
  {
    namespace client
    {
      class ManagedCacheLoaderGeneric
        : public CacheLoader
      {
      public:

        static CacheLoader* create(const char* assemblyPath,
                                   const char* factoryFunctionName);
      };

      class ManagedCacheListenerGeneric
        : public CacheListener
      {
      public:

        static CacheListener* create(const char* assemblyPath,
                                     const char* factoryFunctionName);
      };

      class ManagedFixedPartitionResolverGeneric
        : public FixedPartitionResolver
      {
      public:

        static PartitionResolver* create(const char* assemblyPath,
                                         const char* factoryFunctionName);
      };

      class ManagedCacheWriterGeneric
        : public CacheWriter
      {
      public:

        static CacheWriter* create(const char* assemblyPath,
                                   const char* factoryFunctionName);
      };

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


namespace Apache
{
  namespace Geode
  {
    namespace Client
    {


      namespace native = apache::geode::client;

      DistributedSystem^ DistributedSystem::Connect(String^ name, Cache^ cache)
      {
        return DistributedSystem::Connect(name, nullptr, cache);
      }

      DistributedSystem^ DistributedSystem::Connect(String^ name, Properties<String^, String^>^ config, Cache ^ cache)
      {
        // TODO AppDomain should we be able to create a DS directly?
        _GF_MG_EXCEPTION_TRY2

        auto nativeDistributedSystem = native::DistributedSystem::create(marshal_as<std::string>(name),
                                                           config->GetNative());
        nativeDistributedSystem.connect();

        ManagedPostConnect(cache);

        return gcnew DistributedSystem(std::unique_ptr<native::DistributedSystem>(
            new native::DistributedSystem(std::move(nativeDistributedSystem))));

        _GF_MG_EXCEPTION_CATCH_ALL2
      }

      void DistributedSystem::Disconnect(Cache^ cache)
      {
        _GF_MG_EXCEPTION_TRY2
          DistributedSystem::UnregisterBuiltinManagedTypes(cache);
          m_nativeDistributedSystem->get()->disconnect();
          GC::KeepAlive(m_nativeDistributedSystem);
        _GF_MG_EXCEPTION_CATCH_ALL2
      }

      void DistributedSystem::RegisterDataSerializablePrimitives(Cache^ cache)
      {
        RegisterDataSerializablePrimitivesOverrideNativeDeserialization(cache);
      }

      void DistributedSystem::RegisterDataSerializablePrimitivesOverrideNativeDeserialization(Cache^ cache)
      {
        // Registers overrides in the C++ layer to incercept deserialization into managed layer.

        auto typeRegistry = cache->TypeRegistry;

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableBytes),
            gcnew TypeFactoryMethod(CacheableBytes::CreateDeserializable),
            Type::GetType("System.Byte[]"));

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableDoubleArray),
            gcnew TypeFactoryMethod(CacheableDoubleArray::CreateDeserializable),
            Type::GetType("System.Double[]"));

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableFloatArray),
            gcnew TypeFactoryMethod(CacheableFloatArray::CreateDeserializable),
            Type::GetType("System.Single[]"));

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableHashSet),
            gcnew TypeFactoryMethod(CacheableHashSet::CreateDeserializable),
            nullptr);

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableLinkedHashSet),
            gcnew TypeFactoryMethod(CacheableLinkedHashSet::CreateDeserializable),
            nullptr);

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableInt16Array),
            gcnew TypeFactoryMethod(CacheableInt16Array::CreateDeserializable),
            Type::GetType("System.Int16[]"));

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableInt32Array),
            gcnew TypeFactoryMethod(CacheableInt32Array::CreateDeserializable),
            Type::GetType("System.Int32[]"));

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableInt64Array),
            gcnew TypeFactoryMethod(CacheableInt64Array::CreateDeserializable),
            Type::GetType("System.Int64[]"));

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::BooleanArray),
            gcnew TypeFactoryMethod(BooleanArray::CreateDeserializable),
            Type::GetType("System.Boolean[]"));

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CharArray),
            gcnew TypeFactoryMethod(CharArray::CreateDeserializable),
            Type::GetType("System.Char[]"));

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableStringArray),
            gcnew TypeFactoryMethod(CacheableStringArray::CreateDeserializable),
            Type::GetType("System.String[]"));

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::DSFid::Struct),
            gcnew TypeFactoryMethod(Struct::CreateDeserializable),
            nullptr);
        
        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableDate),
            gcnew TypeFactoryMethod(CacheableDate::CreateDeserializable),
            Type::GetType("System.DateTime"));

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableFileName),
            gcnew TypeFactoryMethod(CacheableFileName::CreateDeserializable),
            nullptr);

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableHashMap),
            gcnew TypeFactoryMethod(CacheableHashMap::CreateDeserializable),
            nullptr);

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableHashTable),
            gcnew TypeFactoryMethod(CacheableHashTable::CreateDeserializable),
            Type::GetType("System.Collections.Hashtable"));

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableIdentityHashMap),
            gcnew TypeFactoryMethod(CacheableIdentityHashMap::CreateDeserializable),
            nullptr);

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::DSFid::CacheableUndefined),
            gcnew TypeFactoryMethod(CacheableUndefined::CreateDeserializable),
            nullptr);

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableVector),
            gcnew TypeFactoryMethod(CacheableVector::CreateDeserializable),
            nullptr);

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableObjectArray),
            gcnew TypeFactoryMethod(CacheableObjectArray::CreateDeserializable),
            nullptr);

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableArrayList),
            gcnew TypeFactoryMethod(CacheableArrayList::CreateDeserializable),
            nullptr);

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableLinkedList),
            gcnew TypeFactoryMethod(CacheableLinkedList::CreateDeserializable),
            nullptr);

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::CacheableStack),
            gcnew TypeFactoryMethod(CacheableStack::CreateDeserializable),
            nullptr);

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::InternalId::CacheableManagedObject),
            gcnew TypeFactoryMethod(CacheableObject::CreateDeserializable),
            nullptr);

        typeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::InternalId::CacheableManagedObjectXml),
            gcnew TypeFactoryMethod(CacheableObjectXml::CreateDeserializable),
            nullptr);
      }

      void DistributedSystem::RegisterDataSerializableFixedIdsOverrideNativeDeserialization(Cache^ cache)
      {
        auto typeRegistry = cache->TypeRegistry;
 
        typeRegistry->RegisterDataSerializableFixedIdTypeOverrideNativeDeserialization(
            static_cast<int8_t>(native::DSFid::EnumInfo),
            gcnew TypeFactoryMethod(Internal::EnumInfo::CreateDeserializable));
      }

      void DistributedSystem::AppDomainInstanceInitialization(Cache^ cache)
      {
        RegisterDataSerializablePrimitives(cache);
        RegisterDataSerializableFixedIdsOverrideNativeDeserialization(cache);

        // Actually an internal type being registered as a primitive
        cache->TypeRegistry->RegisterDataSerializablePrimitiveOverrideNativeDeserialization(
            static_cast<int8_t>(native::internal::DSCode::PdxType),
            gcnew TypeFactoryMethod(Apache::Geode::Client::Internal::PdxType::CreateDeserializable),
            nullptr);

        _GF_MG_EXCEPTION_TRY2

          // Set the Generic ManagedCacheLoader/Listener/Writer factory functions.
          native::CacheXmlParser::managedCacheLoaderFn =
            native::ManagedCacheLoaderGeneric::create;
          native::CacheXmlParser::managedCacheListenerFn =
            native::ManagedCacheListenerGeneric::create;
          native::CacheXmlParser::managedCacheWriterFn =
            native::ManagedCacheWriterGeneric::create;

          // Set the Generic ManagedPartitionResolver factory function
          native::CacheXmlParser::managedPartitionResolverFn =
            native::ManagedFixedPartitionResolverGeneric::create;

          // Set the Generic ManagedPersistanceManager factory function
          native::CacheXmlParser::managedPersistenceManagerFn =
            native::ManagedPersistenceManagerGeneric::create;

        _GF_MG_EXCEPTION_CATCH_ALL2
      }

      void DistributedSystem::ManagedPostConnect(Cache^ cache)
      {
        // Log the version of the C# layer being used
        Log::Config(".NET layer assembly version: {0}({1})", System::Reflection::
                    Assembly::GetExecutingAssembly()->GetName()->Version->ToString(),
                    System::Reflection::Assembly::GetExecutingAssembly()->ImageRuntimeVersion);

        Log::Config(".NET runtime version: {0} ", System::Environment::Version);
        Log::Config(".NET AppDomain: {0} - {1}",
          System::AppDomain::CurrentDomain->Id,
          System::AppDomain::CurrentDomain->FriendlyName);
      }

      void DistributedSystem::UnregisterBuiltinManagedTypes(Cache^ cache)
      {
        _GF_MG_EXCEPTION_TRY2

          TypeRegistry::UnregisterNativesGeneric(cache);

          cache->TypeRegistry->UnregisterTypeGeneric(
            static_cast<int8_t>(native::internal::DSCode::CacheableDate));
          cache->TypeRegistry->UnregisterTypeGeneric(
            static_cast<int8_t>(native::internal::DSCode::CacheableFileName));
          cache->TypeRegistry->UnregisterTypeGeneric(
            static_cast<int8_t>(native::internal::DSCode::CacheableHashMap));
          cache->TypeRegistry->UnregisterTypeGeneric(
            static_cast<int8_t>(native::internal::DSCode::CacheableHashTable));
          cache->TypeRegistry->UnregisterTypeGeneric(
            static_cast<int8_t>(native::internal::DSCode::CacheableIdentityHashMap));
          cache->TypeRegistry->UnregisterTypeGeneric(
            static_cast<int8_t>(native::internal::DSCode::CacheableVector));
          cache->TypeRegistry->UnregisterTypeGeneric(
            static_cast<int8_t>(native::internal::DSCode::CacheableObjectArray));
          cache->TypeRegistry->UnregisterTypeGeneric(
            static_cast<int8_t>(native::internal::DSCode::CacheableArrayList));
          cache->TypeRegistry->UnregisterTypeGeneric(
            static_cast<int8_t>(native::internal::DSCode::CacheableStack));
          cache->TypeRegistry->UnregisterTypeGeneric(
            static_cast<int8_t>(native::internal::InternalId::CacheableManagedObject));
          cache->TypeRegistry->UnregisterTypeGeneric(
            static_cast<int8_t>(native::internal::InternalId::CacheableManagedObjectXml));

        _GF_MG_EXCEPTION_CATCH_ALL2
      }

      Apache::Geode::Client::SystemProperties^ DistributedSystem::SystemProperties::get()
      {
        _GF_MG_EXCEPTION_TRY2

          return Apache::Geode::Client::SystemProperties::Create(
          &(m_nativeDistributedSystem->get()->getSystemProperties()));

        _GF_MG_EXCEPTION_CATCH_ALL2
      }

      String^ DistributedSystem::Name::get()
      {
        try
        {
          return marshal_as<String^>(m_nativeDistributedSystem->get()->getName());
        }
        finally
        {
          GC::KeepAlive(m_nativeDistributedSystem);
        }
      }

      void DistributedSystem::HandleMemoryPressure(System::Object^ state)
      {
        // TODO global - Need single memory pressue event running?
        ACE_Time_Value dummy(1);
        MemoryPressureHandler handler;
        handler.handle_timeout(dummy, nullptr);
      }

      DistributedSystem^ DistributedSystem::Create(native::DistributedSystem* nativeptr)
      {
        auto instance = gcnew DistributedSystem(nativeptr);
        return instance;
      }

      DistributedSystem::DistributedSystem(std::unique_ptr<native::DistributedSystem> nativeDistributedSystem)
      {
        m_nativeDistributedSystem = gcnew native_conditional_unique_ptr<native::DistributedSystem>(std::move(nativeDistributedSystem));
      }

      DistributedSystem::DistributedSystem(native::DistributedSystem* nativeDistributedSystem)
      {
        m_nativeDistributedSystem = gcnew native_conditional_unique_ptr<native::DistributedSystem>(nativeDistributedSystem);
      }

      DistributedSystem::~DistributedSystem()
      {
        m_memoryPressureHandler->Dispose(nullptr);
      }

      void DistributedSystem::registerCliCallback()
      {
        m_cliCallBackObj = gcnew CliCallbackDelegate();
        auto nativeCallback =
          gcnew cliCallback(m_cliCallBackObj,
          &CliCallbackDelegate::Callback);

        native::DistributedSystemImpl::registerCliCallback(System::Threading::Thread::GetDomainID(),
                                                                          (void (*)(apache::geode::client::Cache &cache))System::Runtime::InteropServices::
                                                                          Marshal::GetFunctionPointerForDelegate(
                                                                          nativeCallback).ToPointer());
      }

      void DistributedSystem::unregisterCliCallback()
      {
        native::DistributedSystemImpl::unregisterCliCallback(System::Threading::Thread::GetDomainID());
      }
    }  // namespace Client
  }  // namespace Geode
}  // namespace Apache
