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

#pragma once


#include "geode_defs.hpp"
#include "IGeodeCache.hpp"
#include "native_shared_ptr.hpp"

using namespace System;

namespace Apache
{
  namespace Geode
  {
    namespace Client
    {
      namespace Internal {
        ref class PdxTypeRegistry;
      } // namespace Internal

      namespace native = apache::geode::client;

      ref class QueryService;

      ref class RegionFactory;
      
      enum class ExpirationAction;

      enum class RegionShortcut;
            
      ref class CacheTransactionManager2PC;
      
      generic<class TPropKey, class TPropValue>
      ref class Properties;

      ref class PoolFactory;

      ref class PoolManager;

      ref class DataInput;

      ref class DataOutput;

      ref class TypeRegistry;

      /// <summary>
      /// Provides a distributed cache.
      /// </summary>
      /// <remarks>
      /// Caches are obtained from Create methods on the
      /// <see cref="CacheFactory.Create"/> class.
      /// <para>
      /// When a cache will no longer be used, call <see cref="Cache.Close" />.
      /// Once it <see cref="Cache.IsClosed" /> any attempt to use it
      /// will cause a <c>CacheClosedException</c> to be thrown.
      /// </para><para>
      /// A cache can have multiple root regions, each with a different name.
      /// </para>
      /// </remarks>
      public ref class Cache sealed
        : public IGeodeCache
      {
      public:

        /// <summary>
        /// Initializes the cache from an XML file.
        /// </summary>
        /// <param name="cacheXml">pathname of a <c>cache.xml</c> file</param>
        virtual void InitializeDeclarativeCache(String^ cacheXml);

        /// <summary>
        /// Returns the name of this cache.
        /// </summary>
        /// <remarks>
        /// This method does not throw
        /// <c>CacheClosedException</c> if the cache is closed.
        /// </remarks>
        /// <returns>the string name of this cache</returns>
        virtual property String^ Name
        {
          String^ get();
        }

        /// <summary>
        /// True if this cache has been closed.
        /// </summary>
        /// <remarks>
        /// After a new cache object is created, this method returns false.
        /// After <see cref="Close" /> is called on this cache object, this method
        /// returns true.
        /// </remarks>
        /// <returns>true if this cache is closed, otherwise false</returns>
        virtual property bool IsClosed
        {
          bool get();
        }

        virtual property SystemProperties^ SystemProperties
        {
          Apache::Geode::Client::SystemProperties^ get();
        }

        /// <summary>
        /// Returns the cache transaction manager of
        /// <see cref="CacheFactory.Create" /> this cache.
        /// </summary>
        virtual property Apache::Geode::Client::CacheTransactionManager^ CacheTransactionManager
        {
          Apache::Geode::Client::CacheTransactionManager^ get();
        }

        /// <summary>
        /// Terminates this object cache and releases all the local resources.
        /// </summary>
        /// <remarks>
        /// After this cache is closed, any further
        /// method call on this cache or any region object will throw
        /// <c>CacheClosedException</c>, unless otherwise noted.
        /// </remarks>
        /// <exception cref="CacheClosedException">
        /// if the cache is already closed.
        /// </exception>
        virtual void Close();

        /// <summary>
        /// Terminates this object cache and releases all the local resources.
        /// </summary>
        /// <remarks>
        /// After this cache is closed, any further
        /// method call on this cache or any region object will throw
        /// <c>CacheClosedException</c>, unless otherwise noted.
        /// </remarks>
        /// <param name="keepalive">whether to keep a durable client's queue alive</param>
        /// <exception cref="CacheClosedException">
        /// if the cache is already closed.
        /// </exception>
        virtual void Close(bool keepalive);

        /// <summary>
        /// Send the client-ready message to the server for a durable client.        
        /// </summary>
        /// <remarks>
        /// This method should only be called for durable clients and
        /// with a cache server version 5.5 onwards.
        /// </remarks>
        /// <exception cref="IllegalStateException">
        /// if there was a problem sending the message to the server.
        /// </exception>
        virtual void ReadyForEvents();

        /// <summary>
        /// Returns an existing region given the full path from root, or null 
        /// if no such region exists.
        /// </summary>
        /// <remarks>
        /// If Pool attached with Region is in multiusersecure mode then don't use return instance of region as no credential are attached with this instance.
        /// Get region from RegionService instance of Cache.<see cref="Cache.CreateAuthenticatedView(std::shared_ptr<PropertiesPtr>)" />.
        /// </remarks>
        /// <param name="path">the pathname of the region</param>
        /// <returns>the region</returns>
        generic<class TKey, class TValue>
        virtual IRegion<TKey, TValue>^ GetRegion(String^ path);

        /// <summary>
        /// Returns an array of root regions in the cache. This set is a
        /// snapshot and is not backed by the cache.
        /// </summary>
        /// <remarks>
        /// It is not supported when Cache is created from Pool.
        /// </remarks>
        /// <returns>array of regions</returns>
        generic<class TKey, class TValue>
        virtual array<IRegion<TKey, TValue>^>^ RootRegions();

        /// <summary>
        /// Get a query service object to be able to query the cache.
        /// Supported only when cache is created from Pool(pool is in multiuserSecure mode)
        /// </summary>
        /// <remarks>
        /// Currently only works against the java server in native mode, and
        /// at least some endpoints must have been defined in some regions
        /// before actually firing a query.
        /// </remarks>
        virtual Client::QueryService^ GetQueryService();

        /// <summary>
        /// Get a query service object to be able to query the cache.
        /// Use only when Cache has more than one Pool.
        /// </summary>
        /// <remarks>
        /// Currently only works against the java server in native mode, and
        /// at least some endpoints must have been defined in some regions
        /// before actually firing a query.
        /// </remarks>
        virtual Client::QueryService^ GetQueryService(String^ poolName);

        /// <summary>
        /// Returns the instance of <see cref="RegionFactory" /> to create the region
        /// </summary>
        /// <remarks>
        /// Pass the <see cref="RegionShortcut" /> to set the deafult region attributes
        /// </remarks>
        /// <param name="regionShortcut">the regionShortcut to set the default region attributes</param>
        /// <returns>Instance of RegionFactory</returns>
        RegionFactory^ CreateRegionFactory(RegionShortcut regionShortcut);

        /// <summary>
        /// Returns the instance of <see cref="IRegionService" /> to do the operation on Cache with different Credential.
        /// </summary>
        /// <remarks>
        /// Deafault pool should be in multiuser mode <see cref="CacheFactory.SetMultiuserAuthentication" />
        /// </remarks>
        /// <param name="credentials">the user Credentials.</param>
        /// <returns>Instance of IRegionService</returns>
        IRegionService^ CreateAuthenticatedView(Properties<String^, Object^>^ credentials);

        /// <summary>
        /// Returns the instance of <see cref="IRegionService" /> to do the operation on Cache with different Credential.
        /// </summary>
        /// <remarks>
        /// Deafault pool should be in multiuser mode <see cref="CacheFactory.SetMultiuserAuthentication" />
        /// </remarks>
        /// <param name="credentials">the user Credentials.</param>
        /// <param name="poolName">Pool, which is in multiuser mode.</param>
        /// <returns>Instance of IRegionService</returns>
        IRegionService^ CreateAuthenticatedView(Properties<String^, Object^>^ credentials, String^ poolName);

        ///<summary>
        /// Returns whether Cache saves unread fields for Pdx types.
        ///</summary>
        virtual bool GetPdxIgnoreUnreadFields();

        ///<summary>
        /// Returns whether { @link PdxInstance} is preferred for PDX types instead of .NET object.
        ///</summary>
        virtual bool GetPdxReadSerialized();

        /// <summary>
        /// Returns a factory that can create a {@link PdxInstance}.
        /// @param className the fully qualified class name that the PdxInstance will become
        ///   when it is fully deserialized.
        /// @return the factory
        /// </summary>
        virtual IPdxInstanceFactory^ CreatePdxInstanceFactory(String^ className);

        virtual DataInput^ CreateDataInput(array<Byte>^ buffer, System::Int32 len);
        virtual DataInput^ CreateDataInput(array<Byte>^ buffer);
        
        virtual DataOutput^ Cache::CreateDataOutput();

        virtual PoolFactory^ GetPoolFactory();

        virtual PoolManager^ GetPoolManager();

        property Apache::Geode::Client::TypeRegistry^ TypeRegistry
        {
          Apache::Geode::Client::TypeRegistry^ get() { return m_typeRegistry; }
        }

      internal:

        /// <summary>
        /// Internal factory function to wrap a native object pointer inside
        /// this managed class with null pointer check.
        /// </summary>
        /// <param name="nativeptr">The native object pointer</param>
        /// <returns>
        /// The managed wrapper object; null if the native pointer is null.
        /// </returns>
        inline static Cache^ Create(std::shared_ptr<native::Cache> nativeptr)
        {
          return __nullptr == nativeptr ? nullptr :
            gcnew Cache( nativeptr );
        }

        std::shared_ptr<native::Cache> GetNative()
        {
          return m_nativeptr->get_shared_ptr();
        }

        Apache::Geode::Client::Internal::PdxTypeRegistry^ GetPdxTypeRegistry()
        {
          return m_pdxTypeRegistry;
        }
		        
		Apache::Geode::Client::TypeRegistry^ GetTypeRegistry()
        {
          return m_typeRegistry;
        }
      private:

        /// <summary>
        /// Private constructor to wrap a native object pointer
        /// </summary>
        /// <param name="nativeptr">The native object pointer</param>
        Cache(std::shared_ptr<native::Cache> nativeptr);

        native_shared_ptr<native::Cache>^ m_nativeptr;

        Apache::Geode::Client::Internal::PdxTypeRegistry^ m_pdxTypeRegistry;
        Apache::Geode::Client::TypeRegistry^ m_typeRegistry;
      };
    }  // namespace Client
  }  // namespace Geode
}  // namespace Apache

