// Copyright 2017 The Fuchsia Authors
//
// Licensed 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 "analyzer/store/bigtable_admin.h"

#include <glog/logging.h>
#include <google/bigtable/admin/v2/bigtable_table_admin.grpc.pb.h>

#include <utility>

#include "analyzer/store/bigtable_flags.h"
#include "analyzer/store/bigtable_names.h"

namespace cobalt {
namespace analyzer {
namespace store {

using google::bigtable::admin::v2::BigtableTableAdmin;
using google::bigtable::admin::v2::ColumnFamily;
using google::bigtable::admin::v2::CreateTableRequest;
using google::bigtable::admin::v2::GetTableRequest;
using grpc::ClientContext;

typedef google::bigtable::admin::v2::Table BtTable;

std::shared_ptr<BigtableAdmin> BigtableAdmin::CreateFromFlagsOrDie() {
  // See https://developers.google.com/identity/protocols/ \
  //         application-default-credentials
  // for an explanation of grpc::GoogleDefaultCredentials(). When running
  // on GKE this should cause the service account to be used. When running
  // on a developer's machine this might either use the user's oauth credentials
  // or a service account if the user has installed one. To use a service
  // account the library looks for a key file located at the path specified in
  // the environment variable GOOGLE_APPLICATION_CREDENTIALS.
  CHECK_NE("", FLAGS_bigtable_project_name);
  CHECK_NE("", FLAGS_bigtable_instance_id);
  auto creds = grpc::GoogleDefaultCredentials();
  CHECK(creds);
  LOG(INFO) << "Connecting to CloudBigtable admin API at "
            << kCloudBigtableAdminUri;
  return std::shared_ptr<BigtableAdmin>(new BigtableAdmin(
      kCloudBigtableAdminUri, creds, FLAGS_bigtable_project_name,
      FLAGS_bigtable_instance_id));
}

BigtableAdmin::BigtableAdmin(
    const std::string& uri,
    std::shared_ptr<grpc::ChannelCredentials> credentials,
    std::string project_name, std::string instance_id)
    : channel_(grpc::CreateChannel(uri, credentials)),
      stub_(BigtableTableAdmin::NewStub(channel_)),
      project_name_(std::move(project_name)),
      instance_id_(std::move(instance_id)) {}

bool BigtableAdmin::WaitForConnected(
    std::chrono::system_clock::time_point deadline) {
  return channel_->WaitForConnected(deadline);
}

bool BigtableAdmin::CreateTablesIfNecessary() {
  return CreateTableIfNecessary(kObservationsTableId) &&
         CreateTableIfNecessary(kReportMetadataTableId) &&
         CreateTableIfNecessary(kReportRowsTableId);
}

bool BigtableAdmin::CreateTableIfNecessary(std::string table_id) {
  ClientContext get_ctx;

  GetTableRequest get_req;
  BtTable get_resp;
  get_req.set_name(
      BigtableNames::FullTableName(project_name_, instance_id_, table_id));

  // If the table exists, do nothing.
  grpc::Status get_s = stub_->GetTable(&get_ctx, get_req, &get_resp);
  if (get_s.ok()) {
    return true;
  }

  // Otherwise, create the table.
  CreateTableRequest create_req;
  BtTable create_resp;

  create_req.set_parent(
      BigtableNames::TableParentName(project_name_, instance_id_));
  create_req.set_table_id(std::move(table_id));

  // Set up columns.
  BtTable* create_req_tab = create_req.mutable_table();
  (*create_req_tab->mutable_column_families())[kDataColumnFamilyName] =
      ColumnFamily();

  // Do the request.
  ClientContext create_ctx;
  grpc::Status create_s =
      stub_->CreateTable(&create_ctx, create_req, &create_resp);

  if (!create_s.ok() && create_s.error_code() != grpc::ALREADY_EXISTS) {
    std::string error_message = create_s.error_message();
    // In practice it appears that the Bigtable Emulator does not in fact
    // return the appropriate error code, ALREADY_EXISTS, but rather returns
    // UNKNOWN. We found that we are able to detect the problem in this case
    // by looking for the text 'already exists'.
    if (error_message.find("already exists") == std::string::npos) {
      LOG(ERROR) << "Can't create table: " << create_s.error_message()
                 << " error code=" << create_s.error_code();
      return false;
    }
  }
  return true;
}

}  // namespace store
}  // namespace analyzer
}  // namespace cobalt
