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

#ifndef GEODE_SERIALIZATIONREGISTRY_H_
#define GEODE_SERIALIZATIONREGISTRY_H_

#include <string>
#include <functional>

#include <ace/Hash_Map_Manager.h>
#include <ace/Thread_Mutex.h>
#include <ace/Null_Mutex.h>

#include <geode/internal/geode_globals.hpp>
#include <geode/internal/DataSerializableInternal.hpp>
#include <geode/Serializable.hpp>
#include <geode/PdxSerializer.hpp>
#include <geode/GeodeTypeIds.hpp>
#include <geode/DataOutput.hpp>
#include <geode/ExceptionTypes.hpp>
#include <geode/Delta.hpp>
#include <geode/PdxSerializable.hpp>
#include <geode/DataSerializable.hpp>

#include "util/concurrent/spinlock_mutex.hpp"
#include "NonCopyable.hpp"
#include "GeodeTypeIdsImpl.hpp"
#include "MemberListForVersionStamp.hpp"
#include "config.h"

#if defined(_MACOSX)
namespace ACE_VERSIONED_NAMESPACE_NAME {
// TODO CMake check type int64_t
template <>
class ACE_Export ACE_Hash<int64_t> {
 public:
  inline unsigned long operator()(int64_t t) const {
    return static_cast<long>(t);
  }
};

}  // namespace ACE_VERSIONED_NAMESPACE_NAME
#endif

namespace apache {
namespace geode {
namespace client {

typedef ACE_Hash_Map_Manager<int64_t, TypeFactoryMethod, ACE_Null_Mutex>
    IdToFactoryMap;

typedef ACE_Hash_Map_Manager<std::string, TypeFactoryMethodPdx, ACE_Null_Mutex>
    StrToPdxFactoryMap;

class TheTypeMap : private NonCopyable {
 private:
  IdToFactoryMap* m_map;
  IdToFactoryMap* m_map2;  // to hold Fixed IDs since GFE 5.7.
  StrToPdxFactoryMap* m_pdxTypemap;
  mutable util::concurrent::spinlock_mutex m_mapLock;
  mutable util::concurrent::spinlock_mutex m_map2Lock;
  mutable util::concurrent::spinlock_mutex m_pdxTypemapLock;

 public:
  TheTypeMap() {
    m_map = new IdToFactoryMap();

    // second map to hold internal Data Serializable Fixed IDs - since GFE 5.7
    m_map2 = new IdToFactoryMap();

    // map to hold PDX types <string, funptr>.
    m_pdxTypemap = new StrToPdxFactoryMap();

    setup();
  }

  virtual ~TheTypeMap() {
    if (m_map != nullptr) {
      delete m_map;
    }

    if (m_map2 != nullptr) {
      delete m_map2;
    }

    if (m_pdxTypemap != nullptr) {
      delete m_pdxTypemap;
    }
  }

  void setup();

  void clear();

  void find(int64_t id, TypeFactoryMethod& func) const;

  void find2(int64_t id, TypeFactoryMethod& func) const;

  void bind(TypeFactoryMethod func);

  inline void rebind(int64_t compId, TypeFactoryMethod func);

  inline void unbind(int64_t compId);

  inline void bind2(TypeFactoryMethod func);

  inline void rebind2(int64_t compId, TypeFactoryMethod func);

  inline void unbind2(int64_t compId);

  inline void bindPdxType(TypeFactoryMethodPdx func);

  inline void findPdxType(const std::string& objFullName,
                          TypeFactoryMethodPdx& func) const;

  inline void unbindPdxType(const std::string& objFullName);

  void rebindPdxType(std::string objFullName, TypeFactoryMethodPdx func);
};

class Pool;

/**
 * Used to register handlers for the PDX DsCode. .NET client extends this to
 * intercept PDX (de)serialization.
 */
class PdxTypeHandler {
 public:
  virtual ~PdxTypeHandler() noexcept = default;
  virtual void serialize(const PdxSerializable& pdxSerializable,
                         DataOutput& dataOutput) const;
  virtual std::shared_ptr<PdxSerializable> deserialize(
      DataInput& dataInput) const;
};

class APACHE_GEODE_EXPORT SerializationRegistry {
 public:
  SerializationRegistry() : theTypeMap() {}

  /** write the length of the serialization, write the typeId of the object,
   * then write whatever the object's toData requires. The length at the
   * front is backfilled after the serialization.
   */
  inline void serialize(const Serializable* obj, DataOutput& output,
                        bool isDelta = false) const {
    if (obj == nullptr) {
      output.write(static_cast<int8_t>(GeodeTypeIds::NullObj));
    } else if (const auto dataSerializableFixedId =
                   dynamic_cast<const DataSerializableFixedId*>(obj)) {
      serialize(dataSerializableFixedId, output);
    } else if (const auto dataSerializablePrimitive =
                   dynamic_cast<const DataSerializablePrimitive*>(obj)) {
      serialize(dataSerializablePrimitive, output);
    } else if (const auto dataSerializable =
                   dynamic_cast<const DataSerializable*>(obj)) {
      serialize(dataSerializable, output, isDelta);
    } else if (const auto pdxSerializable =
                   dynamic_cast<const PdxSerializable*>(obj)) {
      serialize(pdxSerializable, output);
    } else if (const auto dataSerializableInternal =
                   dynamic_cast<const DataSerializableInternal*>(obj)) {
      serialize(dataSerializableInternal, output);
    } else {
      throw UnsupportedOperationException(
          "SerializationRegistry::serialize: Serialization type not "
          "implemented.");
    }
  }

  inline void serializeWithoutHeader(const Serializable* obj,
                                     DataOutput& output) const {
    if (const auto dataSerializableFixedId =
            dynamic_cast<const DataSerializableFixedId*>(obj)) {
      serializeWithoutHeader(dataSerializableFixedId, output);
    } else if (const auto dataSerializablePrimitive =
                   dynamic_cast<const DataSerializablePrimitive*>(obj)) {
      serializeWithoutHeader(dataSerializablePrimitive, output);
    } else if (const auto dataSerializable =
                   dynamic_cast<const DataSerializable*>(obj)) {
      serializeWithoutHeader(dataSerializable, output);
    } else if (const auto pdxSerializable =
                   dynamic_cast<const PdxSerializable*>(obj)) {
      serializeWithoutHeader(pdxSerializable, output);
    } else if (const auto dataSerializableInternal =
                   dynamic_cast<const DataSerializableInternal*>(obj)) {
      serializeWithoutHeader(dataSerializableInternal, output);
    } else {
      throw UnsupportedOperationException(
          "SerializationRegistry::serializeWithoutHeader: Serialization type "
          "not implemented.");
    }
  }

  inline void serialize(const std::shared_ptr<Serializable>& obj,
                        DataOutput& output) const {
    serialize(obj.get(), output);
  }

  /**
   * Read the length, typeid, and run the objs fromData. Returns the New
   * object.
   */
  std::shared_ptr<Serializable> deserialize(DataInput& input,
                                            int8_t typeId = -1) const;

  void addType(TypeFactoryMethod func);

  void addType(int64_t compId, TypeFactoryMethod func);

  void addPdxType(TypeFactoryMethodPdx func);

  void setPdxSerializer(std::shared_ptr<PdxSerializer> pdxSerializer);

  std::shared_ptr<PdxSerializer> getPdxSerializer();

  void removeType(int64_t compId);

  // following for internal types with Data Serializable Fixed IDs  - since GFE
  // 5.7

  void addType2(TypeFactoryMethod func);

  void addType2(int64_t compId, TypeFactoryMethod func);

  void removeType2(int64_t compId);

  int32_t GetPDXIdForType(Pool* pool,
                          std::shared_ptr<Serializable> pdxType) const;

  std::shared_ptr<Serializable> GetPDXTypeById(Pool* pool,
                                               int32_t typeId) const;

  int32_t GetEnumValue(std::shared_ptr<Pool> pool,
                       std::shared_ptr<Serializable> enumInfo) const;

  std::shared_ptr<Serializable> GetEnum(std::shared_ptr<Pool> pool,
                                        int32_t val) const;

  std::shared_ptr<PdxSerializable> getPdxType(
      const std::string& className) const;

  void setPdxTypeHandler(PdxTypeHandler* handler) {
    this->pdxTypeHandler = std::unique_ptr<PdxTypeHandler>(handler);
  }

 private:
  std::unique_ptr<PdxTypeHandler> pdxTypeHandler;
  std::shared_ptr<PdxSerializer> pdxSerializer;
  TheTypeMap theTypeMap;

  inline void serialize(const DataSerializableFixedId* obj,
                        DataOutput& output) const {
    auto id = obj->getDSFID();
    if (id <= std::numeric_limits<int8_t>::max() &&
        id >= std::numeric_limits<int8_t>::min()) {
      output.write(static_cast<int8_t>(GeodeTypeIdsImpl::FixedIDByte));
      output.write(static_cast<int8_t>(id));
    } else if (id <= std::numeric_limits<int16_t>::max() &&
               id >= std::numeric_limits<int16_t>::min()) {
      output.write(static_cast<int8_t>(GeodeTypeIdsImpl::FixedIDShort));
      output.writeInt(static_cast<int16_t>(id));
    } else {
      output.write(static_cast<int8_t>(GeodeTypeIdsImpl::FixedIDInt));
      output.writeInt(static_cast<int32_t>(id));
    }

    serializeWithoutHeader(obj, output);
  }

  inline void serializeWithoutHeader(const DataSerializableFixedId* obj,
                                     DataOutput& output) const {
    obj->toData(output);
  }

  inline void serialize(const DataSerializablePrimitive* obj,
                        DataOutput& output) const {
    auto id = obj->getDsCode();
    output.write(static_cast<int8_t>(id));

    serializeWithoutHeader(obj, output);
  }

  inline void serializeWithoutHeader(const DataSerializablePrimitive* obj,
                                     DataOutput& output) const {
    obj->toData(output);
  }

  inline void serialize(const DataSerializable* obj, DataOutput& output,
                        bool isDelta) const {
    auto id = obj->getClassId();
    auto dsCode = getSerializableDataDsCode(id);

    output.write(dsCode);
    switch (dsCode) {
      case GeodeTypeIdsImpl::CacheableUserData:
        output.write(static_cast<int8_t>(id));
        break;
      case GeodeTypeIdsImpl::CacheableUserData2:
        output.writeInt(static_cast<int16_t>(id));
        break;
      case GeodeTypeIdsImpl::CacheableUserData4:
        output.writeInt(static_cast<int32_t>(id));
        break;
      default:
        IllegalStateException("Invalid DS Code.");
    }

    if (isDelta) {
      const Delta* ptr = dynamic_cast<const Delta*>(obj);
      ptr->toDelta(output);
    } else {
      serializeWithoutHeader(obj, output);
    }
  }

  inline void serializeWithoutHeader(const DataSerializable* obj,
                                     DataOutput& output) const {
    obj->toData(output);
  }

  inline void serialize(const PdxSerializable* obj, DataOutput& output) const {
    output.write(static_cast<int8_t>(GeodeTypeIdsImpl::PDX));

    serializeWithoutHeader(obj, output);
  }

  void serializeWithoutHeader(const PdxSerializable* obj,
                              DataOutput& output) const;

  inline void serialize(const DataSerializableInternal* obj,
                        DataOutput& output) const {
    serializeWithoutHeader(obj, output);
  }

  inline void serializeWithoutHeader(const DataSerializableInternal* obj,
                                     DataOutput& output) const {
    obj->toData(output);
  }

 public:
  static inline int8_t getSerializableDataDsCode(int32_t classId) {
    if (classId <= std::numeric_limits<int8_t>::max() &&
        classId >= std::numeric_limits<int8_t>::min()) {
      return static_cast<int8_t>(GeodeTypeIdsImpl::CacheableUserData);
    } else if (classId <= std::numeric_limits<int16_t>::max() &&
               classId >= std::numeric_limits<int16_t>::min()) {
      return static_cast<int8_t>(GeodeTypeIdsImpl::CacheableUserData2);
    } else {
      return static_cast<int8_t>(GeodeTypeIdsImpl::CacheableUserData4);
    }
  }

 private:
  void deserialize(DataInput& input, std::shared_ptr<Serializable> obj) const;

  void deserialize(DataInput& input,
                   std::shared_ptr<DataSerializableInternal> obj) const;

  void deserialize(DataInput& input,
                   std::shared_ptr<DataSerializableFixedId> obj) const;

  void deserialize(DataInput& input,
                   std::shared_ptr<DataSerializablePrimitive> obj) const;

  void deserialize(DataInput& input,
                   std::shared_ptr<DataSerializable> obj) const;

  [[noreturn]] void deserialize(DataInput& input,
                                std::shared_ptr<PdxSerializable> obj) const;
};

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

#endif  // GEODE_SERIALIZATIONREGISTRY_H_
