/*
 * 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 <cstdint>
#include <string>

#include "Python.h"
#include "fory/type/type.h"
#include "fory/util/buffer.h"
#include "fory/util/stream.h"

namespace fory {
inline constexpr bool Fory_IsInternalTypeId(uint8_t type_id) {
  switch (static_cast<TypeId>(type_id)) {
  case TypeId::ENUM:
  case TypeId::NAMED_ENUM:
  case TypeId::STRUCT:
  case TypeId::COMPATIBLE_STRUCT:
  case TypeId::NAMED_STRUCT:
  case TypeId::NAMED_COMPATIBLE_STRUCT:
  case TypeId::EXT:
  case TypeId::NAMED_EXT:
  case TypeId::TYPED_UNION:
  case TypeId::NAMED_UNION:
    return false;
  default:
    return true;
  }
}

inline constexpr bool Fory_CanUsePrimitiveCollectionFastpath(uint8_t type_id) {
  switch (static_cast<TypeId>(type_id)) {
  case TypeId::STRING:
  case TypeId::VARINT64:
  case TypeId::INT64:
  case TypeId::TAGGED_INT64:
  case TypeId::VARINT32:
  case TypeId::INT32:
  case TypeId::VAR_UINT64:
  case TypeId::UINT64:
  case TypeId::TAGGED_UINT64:
  case TypeId::VAR_UINT32:
  case TypeId::UINT32:
  case TypeId::BOOL:
  case TypeId::FLOAT32:
  case TypeId::FLOAT64:
  case TypeId::UINT8:
  case TypeId::INT8:
  case TypeId::UINT16:
  case TypeId::INT16:
    return true;
  default:
    return false;
  }
}

int Fory_PyPrimitiveCollectionWriteToBuffer(PyObject *collection,
                                            Buffer *buffer, uint8_t type_id);
int Fory_PyPrimitiveCollectionReadFromBuffer(PyObject *collection,
                                             Buffer *buffer, Py_ssize_t size,
                                             uint8_t type_id);
int Fory_PyWriteBasicFieldToBuffer(PyObject *value, Buffer *buffer,
                                   uint8_t type_id);
PyObject *Fory_PyReadBasicFieldFromBuffer(Buffer *buffer, uint8_t type_id);
int Fory_PyCreateBufferFromStream(PyObject *stream, uint32_t buffer_size,
                                  Buffer **out, std::string *error_message);
int Fory_PyCreateOutputStream(PyObject *stream, OutputStream **out,
                              std::string *error_message);
int Fory_PyBindBufferToOutputStream(Buffer *buffer, OutputStream *output_stream,
                                    std::string *error_message);
int Fory_PyClearBufferOutputStream(Buffer *buffer, std::string *error_message);
} // namespace fory
