// Copyright 2021 Google LLC
//
// 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
//
//      https://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.

// Generated by the Codegen C++ plugin.
// If you make any local changes, they will be lost.
// source: google/iam/admin/v1/iam.proto

#include "google/cloud/iam/admin/v1/internal/iam_connection_impl.h"
#include "google/cloud/iam/admin/v1/internal/iam_option_defaults.h"
#include "google/cloud/background_threads.h"
#include "google/cloud/common_options.h"
#include "google/cloud/grpc_options.h"
#include "google/cloud/internal/pagination_range.h"
#include "google/cloud/internal/retry_loop.h"
#include <memory>
#include <utility>

namespace google {
namespace cloud {
namespace iam_admin_v1_internal {
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
namespace {

std::unique_ptr<iam_admin_v1::IAMRetryPolicy> retry_policy(
    Options const& options) {
  return options.get<iam_admin_v1::IAMRetryPolicyOption>()->clone();
}

std::unique_ptr<BackoffPolicy> backoff_policy(Options const& options) {
  return options.get<iam_admin_v1::IAMBackoffPolicyOption>()->clone();
}

std::unique_ptr<iam_admin_v1::IAMConnectionIdempotencyPolicy>
idempotency_policy(Options const& options) {
  return options.get<iam_admin_v1::IAMConnectionIdempotencyPolicyOption>()
      ->clone();
}

}  // namespace

IAMConnectionImpl::IAMConnectionImpl(
    std::unique_ptr<google::cloud::BackgroundThreads> background,
    std::shared_ptr<iam_admin_v1_internal::IAMStub> stub, Options options)
    : background_(std::move(background)),
      stub_(std::move(stub)),
      options_(internal::MergeOptions(std::move(options),
                                      IAMConnection::options())) {}

StreamRange<google::iam::admin::v1::ServiceAccount>
IAMConnectionImpl::ListServiceAccounts(
    google::iam::admin::v1::ListServiceAccountsRequest request) {
  request.clear_page_token();
  auto current = google::cloud::internal::SaveCurrentOptions();
  auto idempotency = idempotency_policy(*current)->ListServiceAccounts(request);
  char const* function_name = __func__;
  return google::cloud::internal::MakePaginationRange<
      StreamRange<google::iam::admin::v1::ServiceAccount>>(
      current, std::move(request),
      [idempotency, function_name, stub = stub_,
       retry = std::shared_ptr<iam_admin_v1::IAMRetryPolicy>(
           retry_policy(*current)),
       backoff = std::shared_ptr<BackoffPolicy>(backoff_policy(*current))](
          Options const& options,
          google::iam::admin::v1::ListServiceAccountsRequest const& r) {
        return google::cloud::internal::RetryLoop(
            retry->clone(), backoff->clone(), idempotency,
            [stub](grpc::ClientContext& context, Options const& options,
                   google::iam::admin::v1::ListServiceAccountsRequest const&
                       request) {
              return stub->ListServiceAccounts(context, options, request);
            },
            options, r, function_name);
      },
      [](google::iam::admin::v1::ListServiceAccountsResponse r) {
        std::vector<google::iam::admin::v1::ServiceAccount> result(
            r.accounts().size());
        auto& messages = *r.mutable_accounts();
        std::move(messages.begin(), messages.end(), result.begin());
        return result;
      });
}

StatusOr<google::iam::admin::v1::ServiceAccount>
IAMConnectionImpl::GetServiceAccount(
    google::iam::admin::v1::GetServiceAccountRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->GetServiceAccount(request),
      [this](grpc::ClientContext& context, Options const& options,
             google::iam::admin::v1::GetServiceAccountRequest const& request) {
        return stub_->GetServiceAccount(context, options, request);
      },
      *current, request, __func__);
}

StatusOr<google::iam::admin::v1::ServiceAccount>
IAMConnectionImpl::CreateServiceAccount(
    google::iam::admin::v1::CreateServiceAccountRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->CreateServiceAccount(request),
      [this](
          grpc::ClientContext& context, Options const& options,
          google::iam::admin::v1::CreateServiceAccountRequest const& request) {
        return stub_->CreateServiceAccount(context, options, request);
      },
      *current, request, __func__);
}

StatusOr<google::iam::admin::v1::ServiceAccount>
IAMConnectionImpl::PatchServiceAccount(
    google::iam::admin::v1::PatchServiceAccountRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->PatchServiceAccount(request),
      [this](
          grpc::ClientContext& context, Options const& options,
          google::iam::admin::v1::PatchServiceAccountRequest const& request) {
        return stub_->PatchServiceAccount(context, options, request);
      },
      *current, request, __func__);
}

Status IAMConnectionImpl::DeleteServiceAccount(
    google::iam::admin::v1::DeleteServiceAccountRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->DeleteServiceAccount(request),
      [this](
          grpc::ClientContext& context, Options const& options,
          google::iam::admin::v1::DeleteServiceAccountRequest const& request) {
        return stub_->DeleteServiceAccount(context, options, request);
      },
      *current, request, __func__);
}

StatusOr<google::iam::admin::v1::UndeleteServiceAccountResponse>
IAMConnectionImpl::UndeleteServiceAccount(
    google::iam::admin::v1::UndeleteServiceAccountRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->UndeleteServiceAccount(request),
      [this](grpc::ClientContext& context, Options const& options,
             google::iam::admin::v1::UndeleteServiceAccountRequest const&
                 request) {
        return stub_->UndeleteServiceAccount(context, options, request);
      },
      *current, request, __func__);
}

Status IAMConnectionImpl::EnableServiceAccount(
    google::iam::admin::v1::EnableServiceAccountRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->EnableServiceAccount(request),
      [this](
          grpc::ClientContext& context, Options const& options,
          google::iam::admin::v1::EnableServiceAccountRequest const& request) {
        return stub_->EnableServiceAccount(context, options, request);
      },
      *current, request, __func__);
}

Status IAMConnectionImpl::DisableServiceAccount(
    google::iam::admin::v1::DisableServiceAccountRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->DisableServiceAccount(request),
      [this](
          grpc::ClientContext& context, Options const& options,
          google::iam::admin::v1::DisableServiceAccountRequest const& request) {
        return stub_->DisableServiceAccount(context, options, request);
      },
      *current, request, __func__);
}

StatusOr<google::iam::admin::v1::ListServiceAccountKeysResponse>
IAMConnectionImpl::ListServiceAccountKeys(
    google::iam::admin::v1::ListServiceAccountKeysRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->ListServiceAccountKeys(request),
      [this](grpc::ClientContext& context, Options const& options,
             google::iam::admin::v1::ListServiceAccountKeysRequest const&
                 request) {
        return stub_->ListServiceAccountKeys(context, options, request);
      },
      *current, request, __func__);
}

StatusOr<google::iam::admin::v1::ServiceAccountKey>
IAMConnectionImpl::GetServiceAccountKey(
    google::iam::admin::v1::GetServiceAccountKeyRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->GetServiceAccountKey(request),
      [this](
          grpc::ClientContext& context, Options const& options,
          google::iam::admin::v1::GetServiceAccountKeyRequest const& request) {
        return stub_->GetServiceAccountKey(context, options, request);
      },
      *current, request, __func__);
}

StatusOr<google::iam::admin::v1::ServiceAccountKey>
IAMConnectionImpl::CreateServiceAccountKey(
    google::iam::admin::v1::CreateServiceAccountKeyRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->CreateServiceAccountKey(request),
      [this](grpc::ClientContext& context, Options const& options,
             google::iam::admin::v1::CreateServiceAccountKeyRequest const&
                 request) {
        return stub_->CreateServiceAccountKey(context, options, request);
      },
      *current, request, __func__);
}

StatusOr<google::iam::admin::v1::ServiceAccountKey>
IAMConnectionImpl::UploadServiceAccountKey(
    google::iam::admin::v1::UploadServiceAccountKeyRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->UploadServiceAccountKey(request),
      [this](grpc::ClientContext& context, Options const& options,
             google::iam::admin::v1::UploadServiceAccountKeyRequest const&
                 request) {
        return stub_->UploadServiceAccountKey(context, options, request);
      },
      *current, request, __func__);
}

Status IAMConnectionImpl::DeleteServiceAccountKey(
    google::iam::admin::v1::DeleteServiceAccountKeyRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->DeleteServiceAccountKey(request),
      [this](grpc::ClientContext& context, Options const& options,
             google::iam::admin::v1::DeleteServiceAccountKeyRequest const&
                 request) {
        return stub_->DeleteServiceAccountKey(context, options, request);
      },
      *current, request, __func__);
}

Status IAMConnectionImpl::DisableServiceAccountKey(
    google::iam::admin::v1::DisableServiceAccountKeyRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->DisableServiceAccountKey(request),
      [this](grpc::ClientContext& context, Options const& options,
             google::iam::admin::v1::DisableServiceAccountKeyRequest const&
                 request) {
        return stub_->DisableServiceAccountKey(context, options, request);
      },
      *current, request, __func__);
}

Status IAMConnectionImpl::EnableServiceAccountKey(
    google::iam::admin::v1::EnableServiceAccountKeyRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->EnableServiceAccountKey(request),
      [this](grpc::ClientContext& context, Options const& options,
             google::iam::admin::v1::EnableServiceAccountKeyRequest const&
                 request) {
        return stub_->EnableServiceAccountKey(context, options, request);
      },
      *current, request, __func__);
}

StatusOr<google::iam::v1::Policy> IAMConnectionImpl::GetIamPolicy(
    google::iam::v1::GetIamPolicyRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->GetIamPolicy(request),
      [this](grpc::ClientContext& context, Options const& options,
             google::iam::v1::GetIamPolicyRequest const& request) {
        return stub_->GetIamPolicy(context, options, request);
      },
      *current, request, __func__);
}

StatusOr<google::iam::v1::Policy> IAMConnectionImpl::SetIamPolicy(
    google::iam::v1::SetIamPolicyRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->SetIamPolicy(request),
      [this](grpc::ClientContext& context, Options const& options,
             google::iam::v1::SetIamPolicyRequest const& request) {
        return stub_->SetIamPolicy(context, options, request);
      },
      *current, request, __func__);
}

StatusOr<google::iam::v1::TestIamPermissionsResponse>
IAMConnectionImpl::TestIamPermissions(
    google::iam::v1::TestIamPermissionsRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->TestIamPermissions(request),
      [this](grpc::ClientContext& context, Options const& options,
             google::iam::v1::TestIamPermissionsRequest const& request) {
        return stub_->TestIamPermissions(context, options, request);
      },
      *current, request, __func__);
}

StreamRange<google::iam::admin::v1::Role>
IAMConnectionImpl::QueryGrantableRoles(
    google::iam::admin::v1::QueryGrantableRolesRequest request) {
  request.clear_page_token();
  auto current = google::cloud::internal::SaveCurrentOptions();
  auto idempotency = idempotency_policy(*current)->QueryGrantableRoles(request);
  char const* function_name = __func__;
  return google::cloud::internal::MakePaginationRange<
      StreamRange<google::iam::admin::v1::Role>>(
      current, std::move(request),
      [idempotency, function_name, stub = stub_,
       retry = std::shared_ptr<iam_admin_v1::IAMRetryPolicy>(
           retry_policy(*current)),
       backoff = std::shared_ptr<BackoffPolicy>(backoff_policy(*current))](
          Options const& options,
          google::iam::admin::v1::QueryGrantableRolesRequest const& r) {
        return google::cloud::internal::RetryLoop(
            retry->clone(), backoff->clone(), idempotency,
            [stub](grpc::ClientContext& context, Options const& options,
                   google::iam::admin::v1::QueryGrantableRolesRequest const&
                       request) {
              return stub->QueryGrantableRoles(context, options, request);
            },
            options, r, function_name);
      },
      [](google::iam::admin::v1::QueryGrantableRolesResponse r) {
        std::vector<google::iam::admin::v1::Role> result(r.roles().size());
        auto& messages = *r.mutable_roles();
        std::move(messages.begin(), messages.end(), result.begin());
        return result;
      });
}

StreamRange<google::iam::admin::v1::Role> IAMConnectionImpl::ListRoles(
    google::iam::admin::v1::ListRolesRequest request) {
  request.clear_page_token();
  auto current = google::cloud::internal::SaveCurrentOptions();
  auto idempotency = idempotency_policy(*current)->ListRoles(request);
  char const* function_name = __func__;
  return google::cloud::internal::MakePaginationRange<
      StreamRange<google::iam::admin::v1::Role>>(
      current, std::move(request),
      [idempotency, function_name, stub = stub_,
       retry = std::shared_ptr<iam_admin_v1::IAMRetryPolicy>(
           retry_policy(*current)),
       backoff = std::shared_ptr<BackoffPolicy>(backoff_policy(*current))](
          Options const& options,
          google::iam::admin::v1::ListRolesRequest const& r) {
        return google::cloud::internal::RetryLoop(
            retry->clone(), backoff->clone(), idempotency,
            [stub](grpc::ClientContext& context, Options const& options,
                   google::iam::admin::v1::ListRolesRequest const& request) {
              return stub->ListRoles(context, options, request);
            },
            options, r, function_name);
      },
      [](google::iam::admin::v1::ListRolesResponse r) {
        std::vector<google::iam::admin::v1::Role> result(r.roles().size());
        auto& messages = *r.mutable_roles();
        std::move(messages.begin(), messages.end(), result.begin());
        return result;
      });
}

StatusOr<google::iam::admin::v1::Role> IAMConnectionImpl::GetRole(
    google::iam::admin::v1::GetRoleRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->GetRole(request),
      [this](grpc::ClientContext& context, Options const& options,
             google::iam::admin::v1::GetRoleRequest const& request) {
        return stub_->GetRole(context, options, request);
      },
      *current, request, __func__);
}

StatusOr<google::iam::admin::v1::Role> IAMConnectionImpl::CreateRole(
    google::iam::admin::v1::CreateRoleRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->CreateRole(request),
      [this](grpc::ClientContext& context, Options const& options,
             google::iam::admin::v1::CreateRoleRequest const& request) {
        return stub_->CreateRole(context, options, request);
      },
      *current, request, __func__);
}

StatusOr<google::iam::admin::v1::Role> IAMConnectionImpl::UpdateRole(
    google::iam::admin::v1::UpdateRoleRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->UpdateRole(request),
      [this](grpc::ClientContext& context, Options const& options,
             google::iam::admin::v1::UpdateRoleRequest const& request) {
        return stub_->UpdateRole(context, options, request);
      },
      *current, request, __func__);
}

StatusOr<google::iam::admin::v1::Role> IAMConnectionImpl::DeleteRole(
    google::iam::admin::v1::DeleteRoleRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->DeleteRole(request),
      [this](grpc::ClientContext& context, Options const& options,
             google::iam::admin::v1::DeleteRoleRequest const& request) {
        return stub_->DeleteRole(context, options, request);
      },
      *current, request, __func__);
}

StatusOr<google::iam::admin::v1::Role> IAMConnectionImpl::UndeleteRole(
    google::iam::admin::v1::UndeleteRoleRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->UndeleteRole(request),
      [this](grpc::ClientContext& context, Options const& options,
             google::iam::admin::v1::UndeleteRoleRequest const& request) {
        return stub_->UndeleteRole(context, options, request);
      },
      *current, request, __func__);
}

StreamRange<google::iam::admin::v1::Permission>
IAMConnectionImpl::QueryTestablePermissions(
    google::iam::admin::v1::QueryTestablePermissionsRequest request) {
  request.clear_page_token();
  auto current = google::cloud::internal::SaveCurrentOptions();
  auto idempotency =
      idempotency_policy(*current)->QueryTestablePermissions(request);
  char const* function_name = __func__;
  return google::cloud::internal::MakePaginationRange<
      StreamRange<google::iam::admin::v1::Permission>>(
      current, std::move(request),
      [idempotency, function_name, stub = stub_,
       retry = std::shared_ptr<iam_admin_v1::IAMRetryPolicy>(
           retry_policy(*current)),
       backoff = std::shared_ptr<BackoffPolicy>(backoff_policy(*current))](
          Options const& options,
          google::iam::admin::v1::QueryTestablePermissionsRequest const& r) {
        return google::cloud::internal::RetryLoop(
            retry->clone(), backoff->clone(), idempotency,
            [stub](
                grpc::ClientContext& context, Options const& options,
                google::iam::admin::v1::QueryTestablePermissionsRequest const&
                    request) {
              return stub->QueryTestablePermissions(context, options, request);
            },
            options, r, function_name);
      },
      [](google::iam::admin::v1::QueryTestablePermissionsResponse r) {
        std::vector<google::iam::admin::v1::Permission> result(
            r.permissions().size());
        auto& messages = *r.mutable_permissions();
        std::move(messages.begin(), messages.end(), result.begin());
        return result;
      });
}

StatusOr<google::iam::admin::v1::QueryAuditableServicesResponse>
IAMConnectionImpl::QueryAuditableServices(
    google::iam::admin::v1::QueryAuditableServicesRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->QueryAuditableServices(request),
      [this](grpc::ClientContext& context, Options const& options,
             google::iam::admin::v1::QueryAuditableServicesRequest const&
                 request) {
        return stub_->QueryAuditableServices(context, options, request);
      },
      *current, request, __func__);
}

StatusOr<google::iam::admin::v1::LintPolicyResponse>
IAMConnectionImpl::LintPolicy(
    google::iam::admin::v1::LintPolicyRequest const& request) {
  auto current = google::cloud::internal::SaveCurrentOptions();
  return google::cloud::internal::RetryLoop(
      retry_policy(*current), backoff_policy(*current),
      idempotency_policy(*current)->LintPolicy(request),
      [this](grpc::ClientContext& context, Options const& options,
             google::iam::admin::v1::LintPolicyRequest const& request) {
        return stub_->LintPolicy(context, options, request);
      },
      *current, request, __func__);
}

GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
}  // namespace iam_admin_v1_internal
}  // namespace cloud
}  // namespace google
