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

#include "core/flow/Node.h"
#include "rapidjson/document.h"
#include "utils/gsl.h"
#include "utils/ValueCaster.h"

namespace org::apache::nifi::minifi::core {

class JsonNode : public flow::Node::NodeImpl {
 public:
  explicit JsonNode(const rapidjson::Value* node): node_(node) {}

  explicit operator bool() const override {
    return node_ != nullptr;
  }
  bool isSequence() const override {
    return node_ ? node_->IsArray() : false;
  }
  bool isMap() const override {
    return node_ ? node_->IsObject() : false;
  }
  bool isNull() const override {
    return node_ ? node_->IsNull() : false;
  }

  flow::Node createEmpty() const override {
    return flow::Node{std::make_shared<JsonNode>(nullptr)};
  }

  nonstd::expected<std::string, std::exception_ptr> getString() const override {
    try {
      if (!node_) {
        throw std::runtime_error(fmt::format("Cannot get string of invalid json value at '{}'", path_));
      }
      if (!node_->IsString()) {
        throw std::runtime_error(fmt::format("Cannot get string of non-string json value at '{}'", path_));
      }
      return std::string{node_->GetString(), node_->GetStringLength()};
    } catch (...) {
      return nonstd::make_unexpected(std::current_exception());
    }
  }

  nonstd::expected<int64_t, std::exception_ptr> getInt64() const override {
    try {
      if (!node_) {
        throw std::runtime_error(fmt::format("Cannot get int64 of invalid json value at '{}'", path_));
      }
      if (!node_->IsInt64()) {
        throw std::runtime_error(fmt::format("Cannot get int64 of non-int64 json value at '{}'", path_));
      }
      return node_->GetInt64();
    } catch (...) {
      return nonstd::make_unexpected(std::current_exception());
    }
  }

  nonstd::expected<bool, std::exception_ptr> getBool() const override {
    try {
      if (!node_) {
        throw std::runtime_error(fmt::format("Cannot get bool of invalid json value at '{}'", path_));
      }
      if (!node_->IsBool()) {
        throw std::runtime_error(fmt::format("Cannot get bool of non-bool json value at '{}'", path_));
      }
      return node_->GetBool();
    } catch (...) {
      return nonstd::make_unexpected(std::current_exception());
    }
  }

  nonstd::expected<std::string, std::exception_ptr> getIntegerAsString() const override {
    try {
      if (!node_) throw std::runtime_error(fmt::format("Cannot get string from invalid json value at '{}'", path_));
      if (node_->IsInt64()) return std::to_string(node_->GetInt64());
      if (node_->IsUint64()) return std::to_string(node_->GetUint64());
      if (node_->IsString()) return std::string(node_->GetString(), node_->GetStringLength());
      throw std::runtime_error(fmt::format("Cannot get string from non-integer json value at '{}'", path_));
    } catch (...) {
      return nonstd::make_unexpected(std::current_exception());
    }
  }

  nonstd::expected<std::string, std::exception_ptr> getScalarAsString() const override {
    try {
      if (!node_) throw std::runtime_error(fmt::format("Cannot get string from invalid json value at '{}'", path_));
      if (node_->IsBool()) return node_->GetBool() ? "true" : "false";
      if (node_->IsInt64()) return std::to_string(node_->GetInt64());
      if (node_->IsUint64()) return std::to_string(node_->GetUint64());
      if (node_->IsString()) return std::string(node_->GetString(), node_->GetStringLength());
      if (node_->IsDouble()) return std::to_string(node_->GetDouble());
      throw std::runtime_error(fmt::format("Cannot convert non-scalar json value to string at '{}'", path_));
    } catch (...) {
      return nonstd::make_unexpected(std::current_exception());
    }
  }

  std::string getDebugString() const override {
    if (!node_) return "<invalid>";
    if (node_->IsObject()) return "<Map>";
    if (node_->IsArray()) return "<Array>";
    if (node_->IsNull()) return "null";
    if (auto int_str = getIntegerAsString()) {
      return int_str.value();
    }
    if (node_->IsTrue()) return "true";
    if (node_->IsFalse()) return "false";
    if (node_->IsDouble()) return std::to_string(node_->GetDouble());
    if (node_->IsString()) return '"' + std::string(node_->GetString(), node_->GetStringLength()) + '"';
    return "<unknown>";
  }

  size_t size() const override {
    if (!node_) {
      throw std::runtime_error(fmt::format("Cannot get size of invalid json value at '{}'", path_));
    }
    if (!node_->IsArray()) {
      throw std::runtime_error(fmt::format("Cannot get size of non-array json value at '{}'", path_));
    }
    return node_->Size();
  }
  flow::Node::Iterator begin() const override;
  flow::Node::Iterator end() const override;

  flow::Node operator[](std::string_view key) const override {
    if (!node_ || node_->IsArray() || node_->IsNull()) {
      return flow::Node{std::make_shared<JsonNode>(nullptr)};
    }
    if (!node_->IsObject()) {
      throw std::runtime_error(fmt::format("Cannot get member '{}' of scalar json value at '{}'", key, path_));
    }
    auto it = node_->FindMember(rapidjson::Value(rapidjson::StringRef(key.data(), key.length())));
    if (it == node_->MemberEnd()) {
      return flow::Node{std::make_shared<JsonNode>(nullptr)};
    }
    return flow::Node{std::make_shared<JsonNode>(&it->value)};
  }

  std::optional<flow::Node::Cursor> getCursor() const override {
    return std::nullopt;
  }

 private:
  const rapidjson::Value* node_;
};

class JsonValueIterator : public flow::Node::Iterator::IteratorImpl {
 public:
  explicit JsonValueIterator(rapidjson::Value::ConstValueIterator it): it_(std::move(it)) {}

  IteratorImpl& operator++() override {
    ++it_;
    return *this;
  }
  bool operator==(const IteratorImpl& other) const override {
    const auto* ptr = dynamic_cast<const JsonValueIterator*>(&other);
    gsl_Expects(ptr);
    return it_ == ptr->it_;
  }
  flow::Node::Iterator::Value operator*() const override {
    auto node = flow::Node{std::make_shared<JsonNode>(&*it_)};
    auto first = flow::Node{std::make_shared<JsonNode>(nullptr)};
    auto second = flow::Node{std::make_shared<JsonNode>(nullptr)};
    return {std::move(node), std::move(first), std::move(second)};
  }

  std::unique_ptr<IteratorImpl> clone() const override {
    return std::make_unique<JsonValueIterator>(it_);
  }

 private:
  rapidjson::Value::ConstValueIterator it_;
};

class JsonMemberIterator : public flow::Node::Iterator::IteratorImpl {
 public:
  explicit JsonMemberIterator(rapidjson::Value::ConstMemberIterator it): it_(std::move(it)) {}

  IteratorImpl& operator++() override {
    ++it_;
    return *this;
  }
  bool operator==(const IteratorImpl& other) const override {
    const auto* ptr = dynamic_cast<const JsonMemberIterator*>(&other);
    gsl_Expects(ptr);
    return it_ == ptr->it_;
  }
  flow::Node::Iterator::Value operator*() const override {
    auto node = flow::Node{std::make_shared<JsonNode>(nullptr)};
    auto first = flow::Node{std::make_shared<JsonNode>(&it_->name)};
    auto second = flow::Node{std::make_shared<JsonNode>(&it_->value)};
    return flow::Node::Iterator::Value(node, first, second);
  }

  std::unique_ptr<IteratorImpl> clone() const override {
    return std::make_unique<JsonMemberIterator>(it_);
  }

 private:
  rapidjson::Value::ConstMemberIterator it_;
};

inline flow::Node::Iterator JsonNode::begin() const {
  if (!node_) {
    throw std::runtime_error(fmt::format("Cannot get begin of invalid json value at '{}'", path_));
  }
  if (node_->IsArray()) {
    return flow::Node::Iterator{std::make_unique<JsonValueIterator>(node_->Begin())};
  } else if (node_->IsObject()) {
    return flow::Node::Iterator{std::make_unique<JsonMemberIterator>(node_->MemberBegin())};
  } else {
    throw std::runtime_error(fmt::format("Json node is not iterable, neither array nor object at '{}'", path_));
  }
}

inline flow::Node::Iterator JsonNode::end() const {
  if (!node_) {
    throw std::runtime_error(fmt::format("Cannot get end of invalid json value at '{}'", path_));
  }
  if (node_->IsArray()) {
    return flow::Node::Iterator{std::make_unique<JsonValueIterator>(node_->End())};
  } else if (node_->IsObject()) {
    return flow::Node::Iterator{std::make_unique<JsonMemberIterator>(node_->MemberEnd())};
  } else {
    throw std::runtime_error(fmt::format("Json node is not iterable, neither array nor object at '{}'", path_));
  }
}

}  // namespace org::apache::nifi::minifi::core
