/*
 * 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::VARINT32:
  case TypeId::BOOL:
  case TypeId::FLOAT64:
  case TypeId::INT8:
  case TypeId::INT16:
  case TypeId::INT32:
    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
