/**
 * 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 "cli/CommandExecutorUtil.hpp"

#include <algorithm>
#include <cstddef>
#include <iomanip>
#include <string>
#include <vector>

#include "catalog/CatalogAttribute.hpp"
#include "catalog/CatalogDatabase.hpp"
#include "catalog/CatalogRelation.hpp"
#include "catalog/IndexScheme.hpp"
#include "cli/PrintToScreen.hpp"
#include "parser/ParseString.hpp"
#include "storage/StorageBlockLayout.pb.h"
#include "types/Type.hpp"
#include "types/TypeID.hpp"
#include "types/TypedValue.hpp"
#include "utility/PtrVector.hpp"
#include "utility/SqlError.hpp"
#include "utility/StringUtil.hpp"

using std::ostringstream;
using std::setw;
using std::size_t;
using std::string;
using std::vector;

namespace quickstep {
namespace cli {

namespace {

// Adding the max column width as 6 as the default initializer
// as the length of the word Column is 6 characters.
// This is used while describing the table.

constexpr int kInitMaxColumnWidth = 6;

}  // namespace

string ExecuteDescribeDatabase(
    const PtrVector<ParseString> &arguments,
    const CatalogDatabase &catalog_database) {
  // Column width initialized to 6 to take into account the header name
  // and the column value table
  int max_column_width = kInitMaxColumnWidth;
  vector<std::size_t> num_blocks;
  const CatalogRelation *relation = nullptr;
  if (arguments.empty()) {
    for (const CatalogRelation &rel : catalog_database) {
      max_column_width =
          std::max(static_cast<int>(rel.getName().length()), max_column_width);
      num_blocks.push_back(rel.size_blocks());
    }
  } else {
    const ParseString &table_name = arguments.front();
    const std::string &table_name_val = table_name.value();
    relation = catalog_database.getRelationByName(table_name_val);

    if (relation == nullptr) {
      THROW_SQL_ERROR_AT(&(arguments.front())) << " Unrecognized relation " << table_name_val;
    }
    max_column_width = std::max(static_cast<int>(relation->getName().length()),
                                    max_column_width);
    num_blocks.push_back(relation->size_blocks());
  }

  ostringstream oss;
  // Only if we have relations work on the printing logic.
  if (!catalog_database.empty()) {
    const std::size_t max_num_blocks = *std::max_element(num_blocks.begin(), num_blocks.end());
    const int max_num_blocks_digits = std::max(PrintToScreen::GetNumberOfDigits(max_num_blocks),
                                               kInitMaxColumnWidth + 2);

    oss << "       List of relations\n\n"
        << std::left << setw(max_column_width + 1) << " Name" << " |"
        << setw(kInitMaxColumnWidth) << " Type" << " |"
        << setw(max_num_blocks_digits) << " Blocks" << '\n'
        << PrintToScreen::GenerateHBar({ max_column_width + 1, kInitMaxColumnWidth + 1, max_num_blocks_digits + 1 });

    //  If there are no argument print the entire list of tables
    //  else print the particular table only.
    vector<std::size_t>::const_iterator num_blocks_it = num_blocks.begin();
    if (arguments.empty()) {
      for (const CatalogRelation &rel : catalog_database) {
        oss << ' ' << setw(max_column_width) << rel.getName() << " |"
            << setw(kInitMaxColumnWidth) << " table" << " | "
            << setw(max_num_blocks_digits - 1) << *num_blocks_it << '\n';
        ++num_blocks_it;
      }
    } else {
      oss << ' ' << setw(max_column_width) << relation->getName() << " |"
          << setw(kInitMaxColumnWidth) << " table" << " | "
          << setw(max_num_blocks_digits - 1) << *num_blocks_it << '\n';
      ++num_blocks_it;
    }
    oss << '\n';
  }

  return oss.str();
}

string ExecuteDescribeTable(
    const PtrVector<ParseString> &arguments,
    const CatalogDatabase &catalog_database) {
  const ParseString &table_name = arguments.front();
  const std::string &table_name_val = table_name.value();
  const CatalogRelation *relation =
      catalog_database.getRelationByName(table_name_val);
  if (relation == nullptr) {
    THROW_SQL_ERROR_AT(&(arguments.front())) << " Unrecognized relation "  << table_name_val;
  }

  int max_attr_column_width = kInitMaxColumnWidth;
  int max_type_column_width = kInitMaxColumnWidth;
  for (const CatalogAttribute &attr : *relation) {
    // Printed column needs to be wide enough to print:
    //   1. The attribute name (in the printed "header").
    //   2. Any value of the attribute's Type.
    max_attr_column_width =
        std::max(max_attr_column_width,
            static_cast<int>(attr.getDisplayName().length()));
    max_type_column_width =
        std::max(max_type_column_width,
            static_cast<int>(attr.getType().getName().length()));
  }

  ostringstream oss;
  oss << setw(kInitMaxColumnWidth) << "Table" << " \"" << table_name_val << "\"\n";
  oss << std::left << setw(max_attr_column_width + 1) << " Column" << " |";
  oss << setw(max_type_column_width + 1) << " Type" << '\n';

  // Add room for one extra character to allow spacing between the column ending and the vertical bar
  oss << PrintToScreen::GenerateHBar({ max_attr_column_width + 1, max_type_column_width + 1 });

  for (const CatalogAttribute &attr : *relation) {
    oss << ' ' << setw(max_attr_column_width) << attr.getDisplayName() << " | "
        << setw(max_type_column_width) << attr.getType().getName() << '\n';
  }
  // TODO(rogers): Add handlers for partitioning information.
  if (relation->hasIndexScheme()) {
    oss << setw(kInitMaxColumnWidth + 2) << " Indexes" << '\n';
    for (const auto &index : relation->getIndexScheme()) {
      const IndexSubBlockDescription &index_description = index.second;
      oss << "  \"" << index.first << "\" "
          << index_description.IndexSubBlockType_Name(index_description.sub_block_type())
          << " ("
          << relation->getAttributeById(index_description.indexed_attribute_ids(0))->getDisplayName();
      for (int i = 1; i < index_description.indexed_attribute_ids_size(); ++i) {
        oss << ", " << relation->getAttributeById(index_description.indexed_attribute_ids(i))->getDisplayName();
      }
      oss << ")\n";
    }
  }

  return oss.str();
}

}  // namespace cli
}  // namespace quickstep
