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

/// User-defined extension types. EXPERIMENTAL in 0.13.0
/// \since 0.13.0

#pragma once

#include <memory>
#include <string>

#include "arrow/array/array_base.h"
#include "arrow/array/data.h"
#include "arrow/result.h"
#include "arrow/status.h"
#include "arrow/type.h"
#include "arrow/type_fwd.h"
#include "arrow/util/checked_cast.h"
#include "arrow/util/macros.h"
#include "arrow/util/visibility.h"

namespace arrow {

/// \brief The base class for custom / user-defined types.
class ARROW_EXPORT ExtensionType : public DataType {
 public:
  static constexpr Type::type type_id = Type::EXTENSION;

  static constexpr const char* type_name() { return "extension"; }

  /// \brief The type of array used to represent this extension type's data
  std::shared_ptr<DataType> storage_type() const { return storage_type_; }

  DataTypeLayout layout() const override;

  std::string ToString() const override;

  std::string name() const override { return "extension"; }

  /// \brief Unique name of extension type used to identify type for
  /// serialization
  /// \return the string name of the extension
  virtual std::string extension_name() const = 0;

  /// \brief Determine if two instances of the same extension types are
  /// equal. Invoked from ExtensionType::Equals
  /// \param[in] other the type to compare this type with
  /// \return bool true if type instances are equal
  virtual bool ExtensionEquals(const ExtensionType& other) const = 0;

  /// \brief Wrap built-in Array type in a user-defined ExtensionArray instance
  /// \param[in] data the physical storage for the extension type
  virtual std::shared_ptr<Array> MakeArray(std::shared_ptr<ArrayData> data) const = 0;

  /// \brief Create an instance of the ExtensionType given the actual storage
  /// type and the serialized representation
  /// \param[in] storage_type the physical storage type of the extension
  /// \param[in] serialized_data the serialized representation produced by
  /// Serialize
  virtual Result<std::shared_ptr<DataType>> Deserialize(
      std::shared_ptr<DataType> storage_type,
      const std::string& serialized_data) const = 0;

  /// \brief Create a serialized representation of the extension type's
  /// metadata. The storage type will be handled automatically in IPC code
  /// paths
  /// \return the serialized representation
  virtual std::string Serialize() const = 0;

  /// \brief Wrap the given storage array as an extension array
  static std::shared_ptr<Array> WrapArray(const std::shared_ptr<DataType>& ext_type,
                                          const std::shared_ptr<Array>& storage);

  /// \brief Wrap the given chunked storage array as a chunked extension array
  static std::shared_ptr<ChunkedArray> WrapArray(
      const std::shared_ptr<DataType>& ext_type,
      const std::shared_ptr<ChunkedArray>& storage);

 protected:
  explicit ExtensionType(std::shared_ptr<DataType> storage_type)
      : DataType(Type::EXTENSION), storage_type_(storage_type) {}

  std::shared_ptr<DataType> storage_type_;
};

/// \brief Base array class for user-defined extension types
class ARROW_EXPORT ExtensionArray : public Array {
 public:
  /// \brief Construct an ExtensionArray from an ArrayData.
  ///
  /// The ArrayData must have the right ExtensionType.
  explicit ExtensionArray(const std::shared_ptr<ArrayData>& data);

  /// \brief Construct an ExtensionArray from a type and the underlying storage.
  ExtensionArray(const std::shared_ptr<DataType>& type,
                 const std::shared_ptr<Array>& storage);

  const ExtensionType* extension_type() const {
    return internal::checked_cast<const ExtensionType*>(data_->type.get());
  }

  /// \brief The physical storage for the extension array
  std::shared_ptr<Array> storage() const { return storage_; }

 protected:
  void SetData(const std::shared_ptr<ArrayData>& data);
  std::shared_ptr<Array> storage_;
};

class ARROW_EXPORT ExtensionTypeRegistry {
 public:
  /// \brief Provide access to the global registry to allow code to control for
  /// race conditions in registry teardown when some types need to be
  /// unregistered and destroyed first
  static std::shared_ptr<ExtensionTypeRegistry> GetGlobalRegistry();

  virtual ~ExtensionTypeRegistry() = default;

  virtual Status RegisterType(std::shared_ptr<ExtensionType> type) = 0;
  virtual Status UnregisterType(const std::string& type_name) = 0;
  virtual std::shared_ptr<ExtensionType> GetType(const std::string& type_name) = 0;
};

/// \brief Register an extension type globally. The name returned by the type's
/// extension_name() method should be unique. This method is thread-safe
/// \param[in] type an instance of the extension type
/// \return Status
ARROW_EXPORT
Status RegisterExtensionType(std::shared_ptr<ExtensionType> type);

/// \brief Delete an extension type from the global registry. This method is
/// thread-safe
/// \param[in] type_name the unique name of a registered extension type
/// \return Status error if the type name is unknown
ARROW_EXPORT
Status UnregisterExtensionType(const std::string& type_name);

/// \brief Retrieve an extension type from the global registry. Returns nullptr
/// if not found. This method is thread-safe
/// \return the globally-registered extension type
ARROW_EXPORT
std::shared_ptr<ExtensionType> GetExtensionType(const std::string& type_name);

ARROW_EXPORT extern const char kExtensionTypeKeyName[];
ARROW_EXPORT extern const char kExtensionMetadataKeyName[];

}  // namespace arrow
