/*
 * 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 <framework/Cluster.h>
#include <framework/Framework.h>
#include <framework/Gfsh.h>
#include <hacks/range.h>

#include <iostream>
#include <unordered_map>

#include <gtest/gtest.h>

#include <geode/Cache.hpp>
#include <geode/PoolManager.hpp>
#include <geode/QueryService.hpp>
#include <geode/RegionFactory.hpp>
#include <geode/RegionShortcut.hpp>
#include <geode/Struct.hpp>

namespace {

using apache::geode::client::Cache;
using apache::geode::client::CacheableInt32;
using apache::geode::client::CacheableString;
using apache::geode::client::Region;
using apache::geode::client::RegionShortcut;
using apache::geode::client::Struct;

std::shared_ptr<Region> setupRegion(Cache& cache) {
  auto region = cache.createRegionFactory(RegionShortcut::PROXY)
                    .setPoolName("default")
                    .create("region");

  return region;
}

/**
 * Example test using 2 servers and waiting for async tasks to synchronize using
 * furtures.
 */
TEST(BasicIPv6Test, DISABLED_queryResultForRange) {
  Cluster cluster{InitialLocators{{{"localhost", 0}}},
                  InitialServers{{{"localhost", 0}}}, UseIpv6(true)};
  cluster.start();
  cluster.getGfsh()
      .create()
      .region()
      .withName("region")
      .withType("REPLICATE")
      .execute();

  auto cache = cluster.createCache();
  auto region = setupRegion(cache);

  std::unordered_map<int, std::string> values = {
      {1, "one"}, {2, "two"}, {3, "three"}};

  for (auto&& value : values) {
    region->put(value.first, value.second);
  }

  auto&& queryResult =
      cache.getQueryService()
          ->newQuery("SELECT e.key, e.value FROM /region.entries e")
          ->execute();
  EXPECT_EQ(3, queryResult->size());

  for (auto&& row : hacks::range(*queryResult)) {
    auto rowStruct = std::dynamic_pointer_cast<Struct>(row);
    ASSERT_NE(nullptr, rowStruct);
    EXPECT_EQ(2, rowStruct->size());

    auto key = -1;
    for (auto&& column : *rowStruct) {
      // Expect to read: key:int, value:string
      if (auto cacheableInt32ColumnValue =
              std::dynamic_pointer_cast<CacheableInt32>(column)) {
        key = cacheableInt32ColumnValue->value();
        EXPECT_NE(values.end(), values.find(key));
      } else if (auto cacheableStringColumnValue =
                     std::dynamic_pointer_cast<CacheableString>(column)) {
        auto value = cacheableStringColumnValue->value();
        EXPECT_EQ(values.find(key)->second, value);
      } else {
        FAIL() << "Column is not int or string.";
      }
    }
  }
}

}  // namespace
