#>cpp
#pragma once

#include "communication/rpc/messages.hpp"
#include "query/frontend/ast/ast.hpp"
#include "query/frontend/semantic/symbol_table.hpp"
#include "query/plan/distributed_ops.hpp"

#include "distributed/plan_rpc_messages.capnp.h"
cpp<#

(lcp:namespace distributed)

(lcp:capnp-namespace "distributed")

(lcp:capnp-import 'utils "/rpc/serialization.capnp")
(lcp:capnp-import 'plan "/query/plan/distributed_ops.capnp")
(lcp:capnp-import 'query "/query/serialization.capnp")

(defun load-plan (reader member capnp-name)
  (declare (ignore capnp-name))
  #>cpp
  query::plan::LogicalOperator::LoadHelper helper;
  ${member} = utils::LoadSharedPtr<query::plan::capnp::LogicalOperator, query::plan::LogicalOperator>(
      ${reader}, [&helper](const auto &reader) {
                   std::unique_ptr<query::plan::LogicalOperator> op;
                   query::plan::Load(&op, reader, &helper);
                   return op.release();
                 }, &helper.loaded_ops);
  self->storage = std::move(helper.ast_storage);
  cpp<#)

(defun slk-save-plan (member)
  #>cpp
  query::plan::LogicalOperator::SaveHelper helper;
  slk::Save<query::plan::LogicalOperator>(
      self.${member}, builder, &helper.saved_ops,
      [&helper](const auto &val, auto *builder) {
        slk::Save(val, builder, &helper);
      });
  cpp<#)

(defun slk-load-plan (member)
  #>cpp
  query::plan::LogicalOperator::SlkLoadHelper helper;
  slk::Load<query::plan::LogicalOperator>(&self->${member}, reader, &helper.loaded_ops,
      [&helper](auto *op, auto *reader) {
        slk::ConstructAndLoad(op, reader, &helper);
      });
  self->storage = std::move(helper.ast_storage);
  cpp<#)

(defun save-plan (builder member capnp-name)
  (declare (ignore capnp-name))
  #>cpp
  query::plan::LogicalOperator::SaveHelper helper;
  utils::SaveSharedPtr<query::plan::capnp::LogicalOperator, query::plan::LogicalOperator>(
      ${member}, &${builder},
      [&helper](auto *builder, const auto &val) {
        Save(val, builder, &helper);
      }, &helper.saved_ops);
  cpp<#)

(lcp:define-rpc dispatch-plan
    (:request
     ((plan-id :int64_t)
      (plan "std::shared_ptr<query::plan::LogicalOperator>"
            :capnp-type "Utils.SharedPtr(Plan.LogicalOperator)"
            :slk-save #'slk-save-plan
            :slk-load #'slk-load-plan
            :capnp-save #'save-plan :capnp-load #'load-plan)
      (symbol-table "query::SymbolTable" :capnp-type "Query.SymbolTable")
      (storage "query::AstStorage" :initarg nil :dont-save t)))
  (:response ()))

(lcp:define-rpc remove-plan
    (:request ((member :int64_t)))
  (:response ()))

(lcp:pop-namespace) ;; distributed
