// 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.
#pragma once

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "kudu/clock/hybrid_clock.h"
#include "kudu/clock/logical_clock.h"
#include "kudu/common/partial_row.h"
#include "kudu/common/schema.h"
#include "kudu/consensus/log_anchor_registry.h"
#include "kudu/consensus/metadata.pb.h"
#include "kudu/fs/fs_manager.h"
#include "kudu/tablet/tablet.h"
#include "kudu/util/env.h"
#include "kudu/util/mem_tracker.h"
#include "kudu/util/metrics.h"
#include "kudu/util/status.h"

METRIC_DECLARE_entity(server);

namespace kudu {
namespace tablet {

// Creates a default partition schema and partition for a table.
//
// The provided schema must include column IDs.
//
// The partition schema will have no hash components, and a single range
// component over the primary key columns. The partition will cover the
// entire partition-key space.
static std::pair<PartitionSchema, Partition> CreateDefaultPartition(const Schema& schema) {
  // Create a default partition schema.
  PartitionSchema partition_schema;
  CHECK_OK(PartitionSchema::FromPB(PartitionSchemaPB(), schema, &partition_schema));

  // Create the tablet partitions.
  std::vector<Partition> partitions;
  CHECK_OK(partition_schema.CreatePartitions({}, {}, schema, &partitions));
  CHECK_EQ(1, partitions.size());
  return std::make_pair(partition_schema, partitions[0]);
}

class TabletHarness {
 public:
  struct Options {
    enum ClockType {
      HYBRID_CLOCK,
      LOGICAL_CLOCK
    };
    explicit Options(std::string root_dir)
        : env(Env::Default()),
          tablet_id("test_tablet_id"),
          root_dir(std::move(root_dir)),
          clock_type(LOGICAL_CLOCK) {}

    Env* env;
    std::string tablet_id;
    std::string root_dir;
    ClockType clock_type;
  };

  TabletHarness(const Schema& schema, Options options)
      : options_(std::move(options)), schema_(schema) {}

  Status Create(bool first_time) {
    std::pair<PartitionSchema, Partition> partition(CreateDefaultPartition(schema_));

    // Build the Tablet
    fs_manager_.reset(new FsManager(options_.env, FsManagerOpts(options_.root_dir)));
    if (first_time) {
      RETURN_NOT_OK(fs_manager_->CreateInitialFileSystemLayout());
    }
    RETURN_NOT_OK(fs_manager_->Open());

    scoped_refptr<TabletMetadata> metadata;
    RETURN_NOT_OK(TabletMetadata::LoadOrCreate(
        fs_manager_.get(),
        options_.tablet_id,
        "KuduTableTest",
        "KuduTableTestId",
        schema_,
        partition.first,
        partition.second,
        TABLET_DATA_READY,
        /*tombstone_last_logged_opid=*/ std::nullopt,
        /*extra_config=*/ std::nullopt,
        /*dimension_label=*/ std::nullopt,
        /*table_type=*/ std::nullopt,
        &metadata));
    metrics_registry_.reset(new MetricRegistry);
    metric_entity_ = METRIC_ENTITY_server.Instantiate(metrics_registry_.get(),
                                                      "tablet-harness");

    switch (options_.clock_type) {
      case Options::HYBRID_CLOCK:
        clock_.reset(new clock::HybridClock(metric_entity_));
        break;
      case Options::LOGICAL_CLOCK:
        clock_.reset(new clock::LogicalClock(Timestamp::kInitialTimestamp,
                                             metric_entity_));
        break;
    }
    RETURN_NOT_OK(clock_->Init());
    tablet_.reset(new Tablet(metadata,
                             clock_.get(),
                             {},
                             metrics_registry_.get(),
                             make_scoped_refptr(new log::LogAnchorRegistry)));
    return Status::OK();
  }

  Status Open() {
    RETURN_NOT_OK(tablet_->Open());
    return tablet_->MarkFinishedBootstrapping();
  }

  clock::Clock* clock() const {
    return clock_.get();
  }

  const std::shared_ptr<Tablet>& tablet() {
    return tablet_;
  }

  Tablet* mutable_tablet() {
    return tablet_.get();
  }

  FsManager* fs_manager() {
    return fs_manager_.get();
  }

  MetricRegistry* metrics_registry() {
    return metrics_registry_.get();
  }

 private:
  Options options_;

  std::unique_ptr<MetricRegistry> metrics_registry_;
  scoped_refptr<MetricEntity> metric_entity_;

  std::unique_ptr<clock::Clock> clock_;
  Schema schema_;
  std::unique_ptr<FsManager> fs_manager_;
  std::shared_ptr<Tablet> tablet_;
};

} // namespace tablet
} // namespace kudu
