#include "create_view.hpp"

#include <memory>
#include <string>
#include <unordered_map>

#include "all_type_variant.hpp"
#include "hyrise.hpp"
#include "operators/abstract_operator.hpp"
#include "operators/abstract_read_only_operator.hpp"
#include "storage/lqp_view.hpp"
#include "storage/table.hpp"
#include "types.hpp"

namespace hyrise {

CreateView::CreateView(const std::string& view_name, const std::shared_ptr<LQPView>& view, const bool if_not_exists)
    : AbstractReadOnlyOperator(OperatorType::CreateView),
      _view_name(view_name),
      _view(view),
      _if_not_exists(if_not_exists) {}

const std::string& CreateView::name() const {
  static const auto name = std::string{"CreateView"};
  return name;
}

const std::string& CreateView::view_name() const {
  return _view_name;
}

bool CreateView::if_not_exists() const {
  return _if_not_exists;
}

std::shared_ptr<AbstractOperator> CreateView::_on_deep_copy(
    const std::shared_ptr<AbstractOperator>& /*copied_left_input*/,
    const std::shared_ptr<AbstractOperator>& /*copied_right_input*/,
    std::unordered_map<const AbstractOperator*, std::shared_ptr<AbstractOperator>>& /*copied_ops*/) const {
  return std::make_shared<CreateView>(_view_name, _view->deep_copy(), _if_not_exists);
}

void CreateView::_on_set_parameters(const std::unordered_map<ParameterID, AllTypeVariant>& parameters) {}

std::shared_ptr<const Table> CreateView::_on_execute() {
  // If IF NOT EXISTS is not set and the view already exists, StorageManager throws an exception.
  if (!_if_not_exists || !Hyrise::get().storage_manager.has_view(_view_name)) {
    Hyrise::get().storage_manager.add_view(_view_name, _view);
  }
  return nullptr;
}

}  // namespace hyrise
