/*
 * 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 "plan_executor.h"

#include <memory>

#include "search/executors/filter_executor.h"
#include "search/executors/full_index_scan_executor.h"
#include "search/executors/hnsw_vector_field_knn_scan_executor.h"
#include "search/executors/hnsw_vector_field_range_scan_executor.h"
#include "search/executors/limit_executor.h"
#include "search/executors/merge_executor.h"
#include "search/executors/mock_executor.h"
#include "search/executors/noop_executor.h"
#include "search/executors/numeric_field_scan_executor.h"
#include "search/executors/projection_executor.h"
#include "search/executors/sort_executor.h"
#include "search/executors/tag_field_scan_executor.h"
#include "search/executors/topn_executor.h"
#include "search/indexer.h"
#include "search/ir_plan.h"
#include "status.h"

namespace kqir {

namespace details {

struct ExecutorContextVisitor {
  ExecutorContext *ctx;

  void Transform(PlanOperator *op) {
    if (auto v = dynamic_cast<Limit *>(op)) {
      return Visit(v);
    }

    if (auto v = dynamic_cast<Noop *>(op)) {
      return Visit(v);
    }

    if (auto v = dynamic_cast<Merge *>(op)) {
      return Visit(v);
    }

    if (auto v = dynamic_cast<Sort *>(op)) {
      return Visit(v);
    }

    if (auto v = dynamic_cast<Filter *>(op)) {
      return Visit(v);
    }

    if (auto v = dynamic_cast<Projection *>(op)) {
      return Visit(v);
    }

    if (auto v = dynamic_cast<TopN *>(op)) {
      return Visit(v);
    }

    if (auto v = dynamic_cast<FullIndexScan *>(op)) {
      return Visit(v);
    }

    if (auto v = dynamic_cast<NumericFieldScan *>(op)) {
      return Visit(v);
    }

    if (auto v = dynamic_cast<TagFieldScan *>(op)) {
      return Visit(v);
    }

    if (auto v = dynamic_cast<HnswVectorFieldKnnScan *>(op)) {
      return Visit(v);
    }

    if (auto v = dynamic_cast<HnswVectorFieldRangeScan *>(op)) {
      return Visit(v);
    }

    if (auto v = dynamic_cast<Mock *>(op)) {
      return Visit(v);
    }

    UNREACHABLE();
  }

  void Visit(Limit *op) {
    ctx->nodes[op] = std::make_unique<LimitExecutor>(ctx, op);
    Transform(op->op.get());
  }

  void Visit(Sort *op) {
    ctx->nodes[op] = std::make_unique<SortExecutor>(ctx, op);
    Transform(op->op.get());
  }

  void Visit(Noop *op) { ctx->nodes[op] = std::make_unique<NoopExecutor>(ctx, op); }

  void Visit(Merge *op) {
    ctx->nodes[op] = std::make_unique<MergeExecutor>(ctx, op);
    for (const auto &child : op->ops) Transform(child.get());
  }

  void Visit(Filter *op) {
    ctx->nodes[op] = std::make_unique<FilterExecutor>(ctx, op);
    Transform(op->source.get());
  }

  void Visit(Projection *op) {
    ctx->nodes[op] = std::make_unique<ProjectionExecutor>(ctx, op);
    Transform(op->source.get());
  }

  void Visit(TopN *op) {
    ctx->nodes[op] = std::make_unique<TopNExecutor>(ctx, op);
    Transform(op->op.get());
  }

  void Visit(FullIndexScan *op) { ctx->nodes[op] = std::make_unique<FullIndexScanExecutor>(ctx, op); }

  void Visit(NumericFieldScan *op) { ctx->nodes[op] = std::make_unique<NumericFieldScanExecutor>(ctx, op); }

  void Visit(TagFieldScan *op) { ctx->nodes[op] = std::make_unique<TagFieldScanExecutor>(ctx, op); }

  void Visit(HnswVectorFieldKnnScan *op) { ctx->nodes[op] = std::make_unique<HnswVectorFieldKnnScanExecutor>(ctx, op); }

  void Visit(HnswVectorFieldRangeScan *op) {
    ctx->nodes[op] = std::make_unique<HnswVectorFieldRangeScanExecutor>(ctx, op);
  }

  void Visit(Mock *op) { ctx->nodes[op] = std::make_unique<MockExecutor>(ctx, op); }
};

}  // namespace details

ExecutorContext::ExecutorContext(PlanOperator *op) : root(op), db_ctx(engine::Context::NoTransactionContext(nullptr)) {
  details::ExecutorContextVisitor visitor{this};
  visitor.Transform(root);
}

ExecutorContext::ExecutorContext(PlanOperator *op, engine::Storage *storage)
    : root(op), storage(storage), db_ctx(storage) {
  details::ExecutorContextVisitor visitor{this};
  visitor.Transform(root);
}

auto ExecutorContext::Retrieve(engine::Context &ctx, RowType &row,
                               const FieldInfo *field) const -> StatusOr<ValueType> {  // NOLINT
  if (auto iter = row.fields.find(field); iter != row.fields.end()) {
    return iter->second;
  }

  auto s_retriever =
      redis::FieldValueRetriever::Create(field->index->metadata.on_data_type, row.key, storage, field->index->ns);

  if (s_retriever.Is<Status::NotFound>()) {
    row.fields.emplace(field, kqir::Null{});
    return kqir::Null{};
  }
  auto retriever = GET_OR_RET(std::move(s_retriever));

  auto s = retriever.Retrieve(ctx, field->name, field->metadata.get());
  if (s.Is<Status::NotFound>()) {
    row.fields.emplace(field, kqir::Null{});
    return kqir::Null{};
  }
  if (!s) return s;

  row.fields.emplace(field, *s);
  return *s;
}

}  // namespace kqir
