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

#include "storage/tests/CSBTreePrettyPrinter.hpp"

#include <cstdint>
#include <iostream>
#include <vector>

#include "catalog/CatalogAttribute.hpp"
#include "catalog/CatalogRelation.hpp"
#include "storage/CSBTreeIndexSubBlock.hpp"
#include "types/Type.hpp"
#include "types/TypedValue.hpp"

using std::uint16_t;

namespace quickstep {

std::ostream& operator<<(std::ostream &out, const CSBTreePrettyPrinter &printer) {
  printer.putToStream(&out);
  return out;
}

void CSBTreePrettyPrinter::putToStream(std::ostream *stream) const {
  printNode(csbtree_index_.getRootNodeGroupNumber(), 0, 0, stream);
}

void CSBTreePrettyPrinter::printNode(const int node_group_number,
                                     const uint16_t node_number,
                                     const int node_depth,
                                     std::ostream *stream) const {
  advanceLine(node_depth, stream);
  const char *node_ptr = static_cast<const char*>(csbtree_index_.getNode(node_group_number, node_number));
  const CSBTreeIndexSubBlock::NodeHeader *node_header
      = reinterpret_cast<const CSBTreeIndexSubBlock::NodeHeader*>(node_ptr);
  *stream << "Node ";
  if (node_header->is_leaf) {
    *stream << "(leaf, ";
    *stream << "num_keys: " << node_header->num_keys;
    *stream << ", right_sibling: ";
    if (node_header->node_group_reference == CSBTreeIndexSubBlock::kNodeGroupNextLeaf) {
      *stream << "next in group";
    } else if (node_header->node_group_reference == CSBTreeIndexSubBlock::kNodeGroupNone) {
      *stream << "none";
    } else {
      *stream << node_header->node_group_reference;
    }
    *stream << ")\n";

    for (uint16_t key_num = 0;
         key_num < node_header->num_keys;
         ++key_num) {
      advanceLine(node_depth, stream);
      printKey(node_ptr
                   + sizeof(CSBTreeIndexSubBlock::NodeHeader)
                   + key_num * csbtree_index_.key_tuple_id_pair_length_bytes_,
               stream);
      *stream << " -> ";
      *stream << *reinterpret_cast<const tuple_id*>(node_ptr
                                                    + sizeof(CSBTreeIndexSubBlock::NodeHeader)
                                                    + key_num * csbtree_index_.key_tuple_id_pair_length_bytes_
                                                    + csbtree_index_.key_length_bytes_);
      *stream << "\n";
    }
  } else {
    *stream << "(internal, ";
    *stream << "num_keys: " << node_header->num_keys;
    *stream << ", child: " << node_header->node_group_reference;
    *stream << ")\n";

    printNode(node_header->node_group_reference,
              0,
              node_depth + 1,
              stream);
    for (uint16_t key_num = 0;
         key_num < node_header->num_keys;
         ++key_num) {
      advanceLine(node_depth, stream);
      *stream << "<";
      printKey(node_ptr
                   + sizeof(CSBTreeIndexSubBlock::NodeHeader)
                   + key_num * csbtree_index_.key_length_bytes_,
               stream);
      *stream << ">\n";
      printNode(node_header->node_group_reference,
                key_num + 1,
                node_depth + 1,
                stream);
    }
  }
}

void CSBTreePrettyPrinter::printKey(const void* key, std::ostream *stream) const {
  const char *key_ptr = static_cast<const char*>(key);
  for (std::vector<attribute_id>::const_iterator subkey_it = csbtree_index_.indexed_attribute_ids_.begin();
       subkey_it != csbtree_index_.indexed_attribute_ids_.end();
       ++subkey_it) {
    const Type &subkey_type = csbtree_index_.relation_.getAttributeById(*subkey_it)->getType();
    TypedValue typed_key = subkey_type.makeValue(key_ptr, csbtree_index_.key_length_bytes_);
    *stream << subkey_type.printValueToString(typed_key);
    if (subkey_it != csbtree_index_.indexed_attribute_ids_.end() - 1) {
      *stream << ", ";
    }
    key_ptr += subkey_type.maximumByteLength();
  }
}

void CSBTreePrettyPrinter::advanceLine(const int depth, std::ostream *stream) {
  for (int print_depth = 0; print_depth < depth; ++print_depth) {
    *stream << "    ";
  }
}

}  // namespace quickstep
