/*
 * 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_CACHEABLEENUM_H_
#define GEODE_CACHEABLEENUM_H_

#include <iosfwd>
#include <memory>
#include <string>

#include "CacheableKey.hpp"
#include "CacheableString.hpp"
#include "internal/geode_base.hpp"

namespace apache {
namespace geode {
namespace client {

/**
 * Since C++ enums cannot be directly passed as a parameter to PdxWriter's
 * writeObject and PdxReader's readObject api
 * wrap C++ enum in to a immutable wrapper CacheableEnum class type by
 * specifying enum class name, enum value name and its ordinal. C++ enum allows
 * explicit setting of ordinal number, but it is up to the user to map java
 * enumName with that of C++ enumName. Currently this wrapper only works as part
 * of PdxSerializable member object and cannot be directly used in Region
 * operations.
 *
 * @see PdxWriter#writeObject
 * @see PdxReader#readObject
 */

class DataInput;
class DataOutput;
class Serializable;

class APACHE_GEODE_EXPORT CacheableEnum
    : public internal::DataSerializablePrimitive,
      public CacheableKey {
 private:
  std::string m_enumClassName;
  std::string m_enumName;
  int32_t m_ordinal;
  int32_t m_hashcode;

 public:
  inline CacheableEnum()
      : m_enumClassName(nullptr),
        m_enumName(nullptr),
        m_ordinal(-1),
        m_hashcode(0) {}
  inline CacheableEnum(std::string enumClassName, std::string enumName,
                       int32_t ordinal)
      : m_enumClassName(std::move(enumClassName)),
        m_enumName(std::move(enumName)),
        m_ordinal(ordinal),
        m_hashcode(0) {}
  ~CacheableEnum() noexcept override = default;
  void operator=(const CacheableEnum& other) = delete;
  CacheableEnum(const CacheableEnum& other) = delete;

  /**
   * @brief creation function for enum.
   */
  static std::shared_ptr<Serializable> createDeserializable() {
    return std::make_shared<CacheableEnum>();
  }

  void toData(DataOutput& output) const override;

  virtual void fromData(DataInput& input) override;

  virtual size_t objectSize() const override {
    auto size = sizeof(CacheableEnum);
    size += m_enumClassName.length();
    size += m_enumName.length();
    return size;
  }

  virtual DSCode getDsCode() const override { return DSCode::CacheableEnum; }

  /**
   * Display this object as c string.
   */
  virtual std::string toString() const override { return "CacheableEnum"; }

  /**
   * Factory method for creating an instance of CacheableEnum.
   * @param className the name of the enum class that maps to the java enum
   * type.
   * @param enumName the name of the enum constant that maps to the java enum
   * type.
   * @param ordinal the ordinal value of the enum constant that maps to the java
   * enum type.
   * @return a {@link CacheableEnum} representing C++ enum.
   */
  static std::shared_ptr<CacheableEnum> create(std::string enumClassName,
                                               std::string enumName,
                                               int32_t ordinal) {
    return std::make_shared<CacheableEnum>(enumClassName, enumName, ordinal);
  }

  /**@return enum class name. */
  const std::string& getEnumClassName() const { return m_enumClassName; }

  /**@return enum name. */
  const std::string& getEnumName() const { return m_enumName; }

  /**@return enum ordinal. */
  int32_t getEnumOrdinal() const { return m_ordinal; }

  /** @return the hashcode for this key. */
  virtual int32_t hashcode() const override { return m_hashcode; }

  /** @return true if this key matches other. */
  virtual bool operator==(const CacheableKey& other) const override;

 protected:
  void calculateHashcode();
};

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

#endif  // GEODE_CACHEABLEENUM_H_
