// Copyright 2026 Google LLC
//
// Licensed 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
//
//    https://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.
//

#include "cbor/cbor.h"

#include <cstdint>
#include <optional>
#include <string>
#include <string_view>

#include "absl/base/attributes.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "cppbor/cppbor.h"

namespace cbor {

ItemView::Type ItemView::type() const {
  switch (item_->type()) {
    case cppbor::SIMPLE:
      switch (item_->asSimple()->simpleType()) {
        case cppbor::BOOLEAN:
          return Type::kBool;
        case cppbor::FLOAT:
          return Type::kFloat;
        case cppbor::DOUBLE:
          return Type::kDouble;
        default:
          return Type::kUnknown;
      }
    case cppbor::TSTR:
      return Type::kString;
    case cppbor::BSTR:
      return Type::kByteString;
    case cppbor::NINT:
      return Type::kInt64;
    case cppbor::UINT:
      return Type::kUint64;
    case cppbor::MAP:
      return Type::kMap;
    case cppbor::ARRAY:
      return Type::kArray;
    default:
      return Type::kUnknown;
  }
}

bool ItemView::IsNull() const {
  if (const auto* s = item_->asSimple(); s != nullptr) {
    if (const auto* v = s->asNull(); v != nullptr) {
      return true;
    }
  }
  return false;
}

absl::StatusOr<bool> ItemView::GetBool() const {
  if (const auto* s = item_->asSimple(); s != nullptr) {
    if (const auto* v = s->asBool(); v != nullptr) {
      return v->value();
    }
  }
  return absl::InvalidArgumentError(
      absl::StrCat("CBOR item is not a bool. Type: ", item_->type()));
}

absl::StatusOr<float> ItemView::GetFloat() const {
  if (const auto* s = item_->asSimple(); s != nullptr) {
    if (const auto* v = s->asFloat(); v != nullptr) {
      return v->value();
    }
  }
  return absl::InvalidArgumentError(
      absl::StrCat("CBOR item is not a float. Type: ", item_->type()));
}

absl::StatusOr<double> ItemView::GetDouble() const {
  if (const auto* s = item_->asSimple(); s != nullptr) {
    if (const auto* v = s->asDouble(); v != nullptr) {
      return v->value();
    }
  }
  return absl::InvalidArgumentError(
      absl::StrCat("CBOR item is not a double. Type: ", item_->type()));
}

absl::StatusOr<int64_t> ItemView::GetInt64() const {
  if (const auto* v = item_->asInt(); v != nullptr) {
    return v->value();
  }
  return absl::InvalidArgumentError(
      absl::StrCat("CBOR item is not an int. Type: ", item_->type()));
}

absl::StatusOr<uint64_t> ItemView::GetUint64() const {
  if (const auto* v = item_->asUint(); v != nullptr) {
    return v->value();
  }
  return absl::InvalidArgumentError(
      absl::StrCat("CBOR item is not an uint. Type: ", item_->type()));
}

absl::StatusOr<absl::string_view> ItemView::GetString() const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  if (const auto* v = item_->asTstr(); v != nullptr) {
    return v->value();
  }
  return absl::InvalidArgumentError(
      absl::StrCat("CBOR item is not a string. Type: ", item_->type()));
}

absl::StatusOr<absl::string_view> ItemView::GetByteString() const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  if (const auto* v = item_->asBstr(); v != nullptr) {
    absl::string_view str(reinterpret_cast<const char*>(v->value().data()),
                          v->value().size());
    return str;
  }
  return absl::InvalidArgumentError(
      absl::StrCat("CBOR item is not a byte string. Type: ", item_->type()));
}

absl::StatusOr<MapView> ItemView::GetMap() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
  if (const auto* v = item_->asMap(); v != nullptr) {
    return MapView(v);
  }
  return absl::InvalidArgumentError(
      absl::StrCat("CBOR item is not a map. Type: ", item_->type()));
}

absl::StatusOr<ArrayView> ItemView::GetArray() const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  if (const auto* v = item_->asArray(); v != nullptr) {
    return ArrayView(v);
  }
  return absl::InvalidArgumentError(
      absl::StrCat("CBOR item is not an array. Type: ", item_->type()));
}

std::string ItemView::ToString() const { return item_->toString(); }

absl::StatusOr<ItemView> MapView::Get(uint32_t key) const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  const auto& item = map_->get(key);
  if (!item) {
    return absl::InvalidArgumentError(absl::StrCat("Key not found: ", key));
  }
  return ItemView(item.get());
}

absl::StatusOr<ItemView> MapView::Get(absl::string_view key) const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  const auto& item = map_->get(std::string_view(key));
  if (!item) {
    return absl::InvalidArgumentError(absl::StrCat("Key not found: ", key));
  }
  return ItemView(item.get());
}

std::optional<ItemView> MapView::GetOptional(absl::string_view key) const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  const auto& item = map_->get(std::string_view(key));
  if (!item) {
    return std::nullopt;
  }
  return ItemView(item.get());
}

absl::StatusOr<bool> MapView::GetBool(absl::string_view key) const {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(key));
  return item.GetBool();
}

std::optional<bool> MapView::GetOptionalBool(absl::string_view key) const {
  if (auto item = GetOptional(key); item.has_value()) {
    if (auto value = item->GetBool(); value.ok()) {
      return *value;
    }
  }
  return std::nullopt;
}

absl::StatusOr<float> MapView::GetFloat(absl::string_view key) const {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(key));
  return item.GetFloat();
}

std::optional<float> MapView::GetOptionalFloat(absl::string_view key) const {
  if (auto item = GetOptional(key); item.has_value()) {
    if (auto value = item->GetFloat(); value.ok()) {
      return *value;
    }
  }
  return std::nullopt;
}

absl::StatusOr<double> MapView::GetDouble(absl::string_view key) const {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(key));
  return item.GetDouble();
}

std::optional<double> MapView::GetOptionalDouble(absl::string_view key) const {
  if (auto item = GetOptional(key); item.has_value()) {
    if (auto value = item->GetDouble(); value.ok()) {
      return *value;
    }
  }
  return std::nullopt;
}

absl::StatusOr<absl::string_view> MapView::GetString(
    absl::string_view key) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(key));
  ABSL_ASSIGN_OR_RETURN(auto str, item.GetString());
  return str;
}

std::optional<absl::string_view> MapView::GetOptionalString(
    absl::string_view key) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
  if (auto item = GetOptional(key); item.has_value()) {
    if (auto value = item->GetString(); value.ok()) {
      return *value;
    }
  }
  return std::nullopt;
}

absl::StatusOr<absl::string_view> MapView::GetByteString(uint32_t key) const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(key));
  ABSL_ASSIGN_OR_RETURN(auto str, item.GetByteString());
  return str;
}

absl::StatusOr<absl::string_view> MapView::GetByteString(
    absl::string_view key) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(key));
  ABSL_ASSIGN_OR_RETURN(auto str, item.GetByteString());
  return str;
}

std::optional<absl::string_view> MapView::GetOptionalByteString(
    absl::string_view key) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
  if (auto item = GetOptional(key); item.has_value()) {
    if (auto value = item->GetByteString(); value.ok()) {
      return *value;
    }
  }
  return std::nullopt;
}

std::optional<MapView> MapView::GetOptionalMap(absl::string_view key) const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  if (auto item = GetOptional(key); item.has_value()) {
    if (auto value = item->GetMap(); value.ok()) {
      return *value;
    }
  }
  return std::nullopt;
}

absl::StatusOr<int64_t> MapView::GetInt64(absl::string_view key) const {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(key));
  return item.GetInt64();
}

std::optional<int64_t> MapView::GetOptionalInt64(absl::string_view key) const {
  if (auto item = GetOptional(key); item.has_value()) {
    if (auto value = item->GetInt64(); value.ok()) {
      return *value;
    }
  }
  return std::nullopt;
}

absl::StatusOr<int64_t> MapView::GetInt64(uint32_t key) const {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(key));
  return item.GetInt64();
}

absl::StatusOr<uint64_t> MapView::GetUint64(absl::string_view key) const {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(key));
  return item.GetUint64();
}

std::optional<int64_t> MapView::GetOptionalUint64(absl::string_view key) const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  if (auto item = GetOptional(key); item.has_value()) {
    if (auto value = item->GetUint64(); value.ok()) {
      return *value;
    }
  }
  return std::nullopt;
}

absl::StatusOr<MapView> MapView::GetMap(absl::string_view key) const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(key));
  ABSL_ASSIGN_OR_RETURN(auto map, item.GetMap());
  return map;
}

absl::StatusOr<ArrayView> MapView::GetArray(uint32_t key) const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(key));
  ABSL_ASSIGN_OR_RETURN(auto array, item.GetArray());
  return array;
}

absl::StatusOr<ArrayView> MapView::GetArray(absl::string_view key) const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(key));
  ABSL_ASSIGN_OR_RETURN(auto array, item.GetArray());
  return array;
}

std::optional<ArrayView> MapView::GetOptionalArray(absl::string_view key) const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  if (auto item = GetOptional(key); item.has_value()) {
    if (auto value = item->GetArray(); value.ok()) {
      return *value;
    }
  }
  return std::nullopt;
}

uint32_t ArrayView::size() const { return array_->size(); }

ItemView::Type ArrayView::value_type(uint32_t index) const {
  if (index >= size()) {
    return ItemView::Type::kUnknown;
  }
  ItemView item(array_->get(index).get());
  return item.type();
}

absl::StatusOr<ItemView> ArrayView::Get(uint32_t index) const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  if (index >= array_->size()) {
    return absl::InvalidArgumentError(
        absl::StrCat("Index out of range: ", index, " >= ", array_->size()));
  }
  return ItemView(array_->get(index).get());
}

absl::StatusOr<bool> ArrayView::GetBool(uint32_t index) const {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(index));
  return item.GetBool();
}

absl::StatusOr<float> ArrayView::GetFloat(uint32_t index) const {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(index));
  return item.GetFloat();
}

absl::StatusOr<double> ArrayView::GetDouble(uint32_t index) const {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(index));
  return item.GetDouble();
}

absl::StatusOr<absl::string_view> ArrayView::GetString(uint32_t index) const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(index));
  ABSL_ASSIGN_OR_RETURN(auto str, item.GetString());
  return str;
}

absl::StatusOr<absl::string_view> ArrayView::GetByteString(uint32_t index) const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(index));
  ABSL_ASSIGN_OR_RETURN(auto str, item.GetByteString());
  return str;
}

absl::StatusOr<int64_t> ArrayView::GetInt64(uint32_t index) const {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(index));
  return item.GetInt64();
}

absl::StatusOr<uint64_t> ArrayView::GetUint64(uint32_t index) const {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(index));
  return item.GetUint64();
}

absl::StatusOr<MapView> ArrayView::GetMap(uint32_t index) const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(index));
  ABSL_ASSIGN_OR_RETURN(auto map, item.GetMap());
  return map;
}

absl::StatusOr<ArrayView> ArrayView::GetArray(uint32_t index) const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(index));
  ABSL_ASSIGN_OR_RETURN(auto array, item.GetArray());
  return array;
}

absl::StatusOr<bool> ArrayView::IsNull(uint32_t index) const
    ABSL_ATTRIBUTE_LIFETIME_BOUND {
  ABSL_ASSIGN_OR_RETURN(auto item, Get(index));
  return item.IsNull();
}
}  // namespace cbor
