/*
 * 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 <CacheRegionHelper.hpp>
#include <CacheImpl.hpp>
#include "end_native.hpp"

#include "Cache.hpp"
#include "ExceptionTypes.hpp"
#include "DistributedSystem.hpp"
#include "PoolFactory.hpp"
#include "Region.hpp"
#include "RegionAttributes.hpp"
#include "QueryService.hpp"
#include "CacheFactory.hpp"
#include "impl/AuthenticatedView.hpp"
#include "impl/SafeConvert.hpp"
#include "impl/PdxTypeRegistry.hpp"
#include "impl/PdxInstanceFactoryImpl.hpp"
#include "CacheTransactionManager.hpp"
#include "PoolManager.hpp"
#include "TypeRegistry.hpp"

#pragma warning(disable:4091)

using namespace System;
using namespace msclr::interop;

namespace Apache
{
  namespace Geode
  {
    namespace Client
    {
      namespace native = apache::geode::client;

      Cache::Cache(std::shared_ptr<native::Cache> nativeptr)
      {
        m_nativeptr = gcnew native_shared_ptr<native::Cache>(nativeptr);
        m_pdxTypeRegistry = gcnew Apache::Geode::Client::Internal::PdxTypeRegistry(this);
        m_typeRegistry = gcnew Apache::Geode::Client::TypeRegistry(this);
      }

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

      bool Cache::IsClosed::get( )
      {
        try
        {
          return m_nativeptr->get()->isClosed( );
        }
        finally
        {
          GC::KeepAlive(m_nativeptr);
        }
      }

      SystemProperties^ Cache::SystemProperties::get( )
      {
        try
        {
          auto&& systemProperties = m_nativeptr->get()->getSystemProperties();
          return Apache::Geode::Client::SystemProperties::Create(&systemProperties);
        }
        finally
        {
          GC::KeepAlive(m_nativeptr);
        }
      }

      CacheTransactionManager^ Cache::CacheTransactionManager::get( )
      {
        // TODO shared_ptr this should be checking the return type for which tx mgr
        try
        {
          auto nativeptr = std::dynamic_pointer_cast<InternalCacheTransactionManager2PC>(
            m_nativeptr->get()->getCacheTransactionManager());
          return Apache::Geode::Client::CacheTransactionManager::Create(nativeptr.get());
        }
        finally
        {
          GC::KeepAlive(m_nativeptr);
        }
      }

      void Cache::Close( )
      {
        Close( false );
      }

      void Cache::Close( bool keepalive )
      {
        _GF_MG_EXCEPTION_TRY2

          m_nativeptr->get()->close( keepalive );
          Apache::Geode::Client::DistributedSystem::UnregisterBuiltinManagedTypes(this);

        _GF_MG_EXCEPTION_CATCH_ALL2
        finally
        {
					CacheRegionHelper::getCacheImpl(m_nativeptr->get())->getPdxTypeRegistry()->clear();
          m_typeRegistry->Clear();
          Apache::Geode::Client::DistributedSystem::unregisterCliCallback();
          GC::KeepAlive(m_nativeptr);
        }
      }

      void Cache::ReadyForEvents( )
      {
        _GF_MG_EXCEPTION_TRY2

          try
          {
            m_nativeptr->get()->readyForEvents( );
          }
          finally
          {
            GC::KeepAlive(m_nativeptr);
          }

        _GF_MG_EXCEPTION_CATCH_ALL2
      }

      generic<class TKey, class TValue>
      Client::IRegion<TKey,TValue>^ Cache::GetRegion( String^ path )
      {
        _GF_MG_EXCEPTION_TRY2/* due to auto replace */

          try
          {
            return Client::Region<TKey, TValue>::Create(m_nativeptr->get()->getRegion(marshal_as<std::string>(path)));
          }
          finally
          {
            GC::KeepAlive(m_nativeptr);
          }

        _GF_MG_EXCEPTION_CATCH_ALL2/* due to auto replace */
      }

      generic<class TKey, class TValue>
      array<Client::IRegion<TKey, TValue>^>^ Cache::RootRegions( )
      {
        std::vector<std::shared_ptr<apache::geode::client::Region>> vrr;
        try
        {
			vrr = m_nativeptr->get()->rootRegions( );
        }
        finally
        {
          GC::KeepAlive(m_nativeptr);
        }

        auto rootRegions = gcnew array<Client::IRegion<TKey, TValue>^>(static_cast<int>(vrr.size()));

        for( System::Int32 index = 0; index < vrr.size( ); index++ )
        {
          std::shared_ptr<apache::geode::client::Region>& nativeptr( vrr[ index ] );
          rootRegions[ index ] = Client::Region<TKey, TValue>::Create( nativeptr );
        }
        return rootRegions;
      }

      Client::QueryService^ Cache::GetQueryService( )
      {
        _GF_MG_EXCEPTION_TRY2

          try
          {
            return Client::QueryService::Create(m_nativeptr->get()->getQueryService());
          }
          finally
          {
            GC::KeepAlive(m_nativeptr);
          }

        _GF_MG_EXCEPTION_CATCH_ALL2
      }

      Client::QueryService^ Cache::GetQueryService(String^ poolName )
      {
        _GF_MG_EXCEPTION_TRY2

          try
          {
            return QueryService::Create(m_nativeptr->get()->getQueryService(marshal_as<std::string>(poolName)));
          }
          finally
          {
            GC::KeepAlive(m_nativeptr);
          }

        _GF_MG_EXCEPTION_CATCH_ALL2
      }

      RegionFactory^ Cache::CreateRegionFactory(RegionShortcut preDefinedRegionAttributes)
      {
        _GF_MG_EXCEPTION_TRY2

          auto preDefineRegionAttr = apache::geode::client::RegionShortcut(preDefinedRegionAttributes);

          try
          {
            return RegionFactory::Create(std::unique_ptr<native::RegionFactory>(
                new native::RegionFactory(
                    m_nativeptr->get()->createRegionFactory(preDefineRegionAttr))));
          }
          finally
          {
            GC::KeepAlive(m_nativeptr);
          }
          
        _GF_MG_EXCEPTION_CATCH_ALL2
      }

      IRegionService^ Cache::CreateAuthenticatedView(Properties<String^, Object^>^ credentials)
      {        
        _GF_MG_EXCEPTION_TRY2

          try
          {
            return AuthenticatedView::Create((m_nativeptr->get()->createAuthenticatedView(credentials->GetNative(), "")));
          }
          finally
          {
            GC::KeepAlive(m_nativeptr);
          }

        _GF_MG_EXCEPTION_CATCH_ALL2   
      }

			bool Cache::GetPdxIgnoreUnreadFields()
			{
				_GF_MG_EXCEPTION_TRY2

					try
					{
					  return	m_nativeptr->get()->getPdxIgnoreUnreadFields();
					}
					finally
					{
					  GC::KeepAlive(m_nativeptr);
					}

				_GF_MG_EXCEPTION_CATCH_ALL2   
			}

      bool Cache::GetPdxReadSerialized()
			{
				_GF_MG_EXCEPTION_TRY2

					try
					{
					  return	m_nativeptr->get()->getPdxReadSerialized();
					}
					finally
					{
					  GC::KeepAlive(m_nativeptr);
					}

				_GF_MG_EXCEPTION_CATCH_ALL2   
			}

      IRegionService^ Cache::CreateAuthenticatedView(Properties<String^, Object^>^ credentials, String^ poolName)
      {

        _GF_MG_EXCEPTION_TRY2

          try
          {
            return AuthenticatedView::Create( (m_nativeptr->get()->createAuthenticatedView(credentials->GetNative(), marshal_as<std::string>(poolName))));
          }
          finally
          {
            GC::KeepAlive(m_nativeptr);
          }

        _GF_MG_EXCEPTION_CATCH_ALL2   
      }

			 void Cache::InitializeDeclarativeCache( String^ cacheXml )
      {
        try
        {
          m_nativeptr->get()->initializeDeclarativeCache( marshal_as<std::string>(cacheXml));
        }
        finally
        {
          GC::KeepAlive(m_nativeptr);
        }
      }

       IPdxInstanceFactory^ Cache::CreatePdxInstanceFactory(String^ className)
       {
    
         return gcnew Internal::PdxInstanceFactoryImpl(className, this);

       }

       DataInput^ Cache::CreateDataInput(array<Byte>^ buffer, System::Int32 len)
       {
         return gcnew DataInput(buffer, len,  this);
       }

       
       DataInput^ Cache::CreateDataInput(array<Byte>^ buffer)
       {
         return gcnew DataInput(buffer, this);
       }

        DataOutput^ Cache::CreateDataOutput()
       {
         return gcnew DataOutput(this);
       }

        PoolFactory^ Cache::GetPoolFactory()
        {
          return PoolFactory::Create(std::unique_ptr<native::PoolFactory>(new native::PoolFactory(
            m_nativeptr->get_shared_ptr()->getPoolManager().createFactory())));
        }

        PoolManager^ Cache::GetPoolManager()
        {
          return gcnew PoolManager(m_nativeptr->get_shared_ptr()->getPoolManager());
        }
    }  // namespace Client
  }  // namespace Geode
}  // namespace Apache

