// This is a generated file (see the discoveryapis_generator project).

// ignore_for_file: unused_import, unnecessary_cast

library googleapis.cloudshell.v1;

import 'dart:core' as core;
import 'dart:async' as async;
import 'dart:convert' as convert;

import 'package:_discoveryapis_commons/_discoveryapis_commons.dart' as commons;
import 'package:http/http.dart' as http;

export 'package:_discoveryapis_commons/_discoveryapis_commons.dart'
    show ApiRequestError, DetailedApiRequestError;

const core.String USER_AGENT = 'dart-api-client cloudshell/v1';

/// Allows users to start, configure, and connect to interactive shell sessions
/// running in the cloud.
class CloudshellApi {
  /// View and manage your data across Google Cloud Platform services
  static const CloudPlatformScope =
      "https://www.googleapis.com/auth/cloud-platform";

  final commons.ApiRequester _requester;

  OperationsResourceApi get operations => new OperationsResourceApi(_requester);

  CloudshellApi(http.Client client,
      {core.String rootUrl = "https://cloudshell.googleapis.com/",
      core.String servicePath = ""})
      : _requester =
            new commons.ApiRequester(client, rootUrl, servicePath, USER_AGENT);
}

class OperationsResourceApi {
  final commons.ApiRequester _requester;

  OperationsResourceApi(commons.ApiRequester client) : _requester = client;

  /// Starts asynchronous cancellation on a long-running operation.  The server
  /// makes a best effort to cancel the operation, but success is not
  /// guaranteed.  If the server doesn't support this method, it returns
  /// `google.rpc.Code.UNIMPLEMENTED`.  Clients can use
  /// Operations.GetOperation or
  /// other methods to check whether the cancellation succeeded or whether the
  /// operation completed despite cancellation. On successful cancellation,
  /// the operation is not deleted; instead, it becomes an operation with
  /// an Operation.error value with a google.rpc.Status.code of 1,
  /// corresponding to `Code.CANCELLED`.
  ///
  /// [request] - The metadata request object.
  ///
  /// Request parameters:
  ///
  /// [name] - The name of the operation resource to be cancelled.
  /// Value must have pattern "^operations/.*$".
  ///
  /// [$fields] - Selector specifying which fields to include in a partial
  /// response.
  ///
  /// Completes with a [Empty].
  ///
  /// Completes with a [commons.ApiRequestError] if the API endpoint returned an
  /// error.
  ///
  /// If the used [http.Client] completes with an error when making a REST call,
  /// this method will complete with the same error.
  async.Future<Empty> cancel(CancelOperationRequest request, core.String name,
      {core.String $fields}) {
    var _url;
    var _queryParams = new core.Map<core.String, core.List<core.String>>();
    var _uploadMedia;
    var _uploadOptions;
    var _downloadOptions = commons.DownloadOptions.Metadata;
    var _body;

    if (request != null) {
      _body = convert.json.encode((request).toJson());
    }
    if (name == null) {
      throw new core.ArgumentError("Parameter name is required.");
    }
    if ($fields != null) {
      _queryParams["fields"] = [$fields];
    }

    _url = 'v1/' + commons.Escaper.ecapeVariableReserved('$name') + ':cancel';

    var _response = _requester.request(_url, "POST",
        body: _body,
        queryParams: _queryParams,
        uploadOptions: _uploadOptions,
        uploadMedia: _uploadMedia,
        downloadOptions: _downloadOptions);
    return _response.then((data) => new Empty.fromJson(data));
  }

  /// Deletes a long-running operation. This method indicates that the client is
  /// no longer interested in the operation result. It does not cancel the
  /// operation. If the server doesn't support this method, it returns
  /// `google.rpc.Code.UNIMPLEMENTED`.
  ///
  /// Request parameters:
  ///
  /// [name] - The name of the operation resource to be deleted.
  /// Value must have pattern "^operations/.*$".
  ///
  /// [$fields] - Selector specifying which fields to include in a partial
  /// response.
  ///
  /// Completes with a [Empty].
  ///
  /// Completes with a [commons.ApiRequestError] if the API endpoint returned an
  /// error.
  ///
  /// If the used [http.Client] completes with an error when making a REST call,
  /// this method will complete with the same error.
  async.Future<Empty> delete(core.String name, {core.String $fields}) {
    var _url;
    var _queryParams = new core.Map<core.String, core.List<core.String>>();
    var _uploadMedia;
    var _uploadOptions;
    var _downloadOptions = commons.DownloadOptions.Metadata;
    var _body;

    if (name == null) {
      throw new core.ArgumentError("Parameter name is required.");
    }
    if ($fields != null) {
      _queryParams["fields"] = [$fields];
    }

    _url = 'v1/' + commons.Escaper.ecapeVariableReserved('$name');

    var _response = _requester.request(_url, "DELETE",
        body: _body,
        queryParams: _queryParams,
        uploadOptions: _uploadOptions,
        uploadMedia: _uploadMedia,
        downloadOptions: _downloadOptions);
    return _response.then((data) => new Empty.fromJson(data));
  }

  /// Gets the latest state of a long-running operation.  Clients can use this
  /// method to poll the operation result at intervals as recommended by the API
  /// service.
  ///
  /// Request parameters:
  ///
  /// [name] - The name of the operation resource.
  /// Value must have pattern "^operations/.*$".
  ///
  /// [$fields] - Selector specifying which fields to include in a partial
  /// response.
  ///
  /// Completes with a [Operation].
  ///
  /// Completes with a [commons.ApiRequestError] if the API endpoint returned an
  /// error.
  ///
  /// If the used [http.Client] completes with an error when making a REST call,
  /// this method will complete with the same error.
  async.Future<Operation> get(core.String name, {core.String $fields}) {
    var _url;
    var _queryParams = new core.Map<core.String, core.List<core.String>>();
    var _uploadMedia;
    var _uploadOptions;
    var _downloadOptions = commons.DownloadOptions.Metadata;
    var _body;

    if (name == null) {
      throw new core.ArgumentError("Parameter name is required.");
    }
    if ($fields != null) {
      _queryParams["fields"] = [$fields];
    }

    _url = 'v1/' + commons.Escaper.ecapeVariableReserved('$name');

    var _response = _requester.request(_url, "GET",
        body: _body,
        queryParams: _queryParams,
        uploadOptions: _uploadOptions,
        uploadMedia: _uploadMedia,
        downloadOptions: _downloadOptions);
    return _response.then((data) => new Operation.fromJson(data));
  }

  /// Lists operations that match the specified filter in the request. If the
  /// server doesn't support this method, it returns `UNIMPLEMENTED`.
  ///
  /// NOTE: the `name` binding allows API services to override the binding
  /// to use different resource name schemes, such as `users / * /operations`.
  /// To
  /// override the binding, API services can add a binding such as
  /// `"/v1/{name=users / * }/operations"` to their service configuration.
  /// For backwards compatibility, the default name includes the operations
  /// collection id, however overriding users must ensure the name binding
  /// is the parent resource, without the operations collection id.
  ///
  /// Request parameters:
  ///
  /// [name] - The name of the operation's parent resource.
  /// Value must have pattern "^operations$".
  ///
  /// [filter] - The standard list filter.
  ///
  /// [pageToken] - The standard list page token.
  ///
  /// [pageSize] - The standard list page size.
  ///
  /// [$fields] - Selector specifying which fields to include in a partial
  /// response.
  ///
  /// Completes with a [ListOperationsResponse].
  ///
  /// Completes with a [commons.ApiRequestError] if the API endpoint returned an
  /// error.
  ///
  /// If the used [http.Client] completes with an error when making a REST call,
  /// this method will complete with the same error.
  async.Future<ListOperationsResponse> list(core.String name,
      {core.String filter,
      core.String pageToken,
      core.int pageSize,
      core.String $fields}) {
    var _url;
    var _queryParams = new core.Map<core.String, core.List<core.String>>();
    var _uploadMedia;
    var _uploadOptions;
    var _downloadOptions = commons.DownloadOptions.Metadata;
    var _body;

    if (name == null) {
      throw new core.ArgumentError("Parameter name is required.");
    }
    if (filter != null) {
      _queryParams["filter"] = [filter];
    }
    if (pageToken != null) {
      _queryParams["pageToken"] = [pageToken];
    }
    if (pageSize != null) {
      _queryParams["pageSize"] = ["${pageSize}"];
    }
    if ($fields != null) {
      _queryParams["fields"] = [$fields];
    }

    _url = 'v1/' + commons.Escaper.ecapeVariableReserved('$name');

    var _response = _requester.request(_url, "GET",
        body: _body,
        queryParams: _queryParams,
        uploadOptions: _uploadOptions,
        uploadMedia: _uploadMedia,
        downloadOptions: _downloadOptions);
    return _response.then((data) => new ListOperationsResponse.fromJson(data));
  }
}

/// The request message for Operations.CancelOperation.
class CancelOperationRequest {
  CancelOperationRequest();

  CancelOperationRequest.fromJson(core.Map _json) {}

  core.Map<core.String, core.Object> toJson() {
    final core.Map<core.String, core.Object> _json =
        new core.Map<core.String, core.Object>();
    return _json;
  }
}

/// A generic empty message that you can re-use to avoid defining duplicated
/// empty messages in your APIs. A typical example is to use it as the request
/// or the response type of an API method. For instance:
///
///     service Foo {
///       rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
///     }
///
/// The JSON representation for `Empty` is empty JSON object `{}`.
class Empty {
  Empty();

  Empty.fromJson(core.Map _json) {}

  core.Map<core.String, core.Object> toJson() {
    final core.Map<core.String, core.Object> _json =
        new core.Map<core.String, core.Object>();
    return _json;
  }
}

/// A Cloud Shell environment, which is defined as the combination of a Docker
/// image specifying what is installed on the environment and a home directory
/// containing the user's data that will remain across sessions. Each user has a
/// single environment with the ID "default".
class Environment {
  /// Required. Full path to the Docker image used to run this environment, e.g.
  /// "gcr.io/dev-con/cloud-devshell:latest".
  core.String dockerImage;

  /// Output only. The environment's identifier, unique among the user's
  /// environments.
  core.String id;

  /// Output only. Full name of this resource, in the format
  /// `users/{owner_email}/environments/{environment_id}`. `{owner_email}` is
  /// the
  /// email address of the user to whom this environment belongs, and
  /// `{environment_id}` is the identifier of this environment. For example,
  /// `users/someone@example.com/environments/default`.
  core.String name;

  /// Output only. Public keys associated with the environment. Clients can
  /// connect to this environment via SSH only if they possess a private key
  /// corresponding to at least one of these public keys. Keys can be added to
  /// or
  /// removed from the environment using the CreatePublicKey and DeletePublicKey
  /// methods.
  core.List<PublicKey> publicKeys;

  /// Indicates the size of the backing VM running the environment.  If set to
  /// something other than DEFAULT, it will be reverted to the default VM size
  /// after vm_size_expire_time.
  /// Possible string values are:
  /// - "VM_SIZE_UNSPECIFIED" : The VM size is unknown.
  /// - "DEFAULT" : The default VM size.
  /// - "BOOSTED" : The boosted VM size.
  core.String size;

  /// Output only. Host to which clients can connect to initiate SSH sessions
  /// with the environment.
  core.String sshHost;

  /// Output only. Port to which clients can connect to initiate SSH sessions
  /// with the environment.
  core.int sshPort;

  /// Output only. Username that clients should use when initiating SSH sessions
  /// with the environment.
  core.String sshUsername;

  /// Output only. Current execution state of this environment.
  /// Possible string values are:
  /// - "STATE_UNSPECIFIED" : The environment's states is unknown.
  /// - "DISABLED" : The environment is not running and can't be connected to.
  /// Starting the
  /// environment will transition it to the STARTING state.
  /// - "STARTING" : The environment is being started but is not yet ready to
  /// accept
  /// connections.
  /// - "RUNNING" : The environment is running and ready to accept connections.
  /// It will
  /// automatically transition back to DISABLED after a period of inactivity or
  /// if another environment is started.
  core.String state;

  /// Output only. The time when the Environment will expire back to the default
  /// VM size.
  core.String vmSizeExpireTime;

  /// Output only. Host to which clients can connect to initiate HTTPS or WSS
  /// connections with the environment.
  core.String webHost;

  /// Output only. Ports to which clients can connect to initiate HTTPS or WSS
  /// connections with the environment.
  core.List<core.int> webPorts;

  Environment();

  Environment.fromJson(core.Map _json) {
    if (_json.containsKey("dockerImage")) {
      dockerImage = _json["dockerImage"];
    }
    if (_json.containsKey("id")) {
      id = _json["id"];
    }
    if (_json.containsKey("name")) {
      name = _json["name"];
    }
    if (_json.containsKey("publicKeys")) {
      publicKeys = (_json["publicKeys"] as core.List)
          .map<PublicKey>((value) => new PublicKey.fromJson(value))
          .toList();
    }
    if (_json.containsKey("size")) {
      size = _json["size"];
    }
    if (_json.containsKey("sshHost")) {
      sshHost = _json["sshHost"];
    }
    if (_json.containsKey("sshPort")) {
      sshPort = _json["sshPort"];
    }
    if (_json.containsKey("sshUsername")) {
      sshUsername = _json["sshUsername"];
    }
    if (_json.containsKey("state")) {
      state = _json["state"];
    }
    if (_json.containsKey("vmSizeExpireTime")) {
      vmSizeExpireTime = _json["vmSizeExpireTime"];
    }
    if (_json.containsKey("webHost")) {
      webHost = _json["webHost"];
    }
    if (_json.containsKey("webPorts")) {
      webPorts = (_json["webPorts"] as core.List).cast<core.int>();
    }
  }

  core.Map<core.String, core.Object> toJson() {
    final core.Map<core.String, core.Object> _json =
        new core.Map<core.String, core.Object>();
    if (dockerImage != null) {
      _json["dockerImage"] = dockerImage;
    }
    if (id != null) {
      _json["id"] = id;
    }
    if (name != null) {
      _json["name"] = name;
    }
    if (publicKeys != null) {
      _json["publicKeys"] =
          publicKeys.map((value) => (value).toJson()).toList();
    }
    if (size != null) {
      _json["size"] = size;
    }
    if (sshHost != null) {
      _json["sshHost"] = sshHost;
    }
    if (sshPort != null) {
      _json["sshPort"] = sshPort;
    }
    if (sshUsername != null) {
      _json["sshUsername"] = sshUsername;
    }
    if (state != null) {
      _json["state"] = state;
    }
    if (vmSizeExpireTime != null) {
      _json["vmSizeExpireTime"] = vmSizeExpireTime;
    }
    if (webHost != null) {
      _json["webHost"] = webHost;
    }
    if (webPorts != null) {
      _json["webPorts"] = webPorts;
    }
    return _json;
  }
}

/// The response message for Operations.ListOperations.
class ListOperationsResponse {
  /// The standard List next-page token.
  core.String nextPageToken;

  /// A list of operations that matches the specified filter in the request.
  core.List<Operation> operations;

  ListOperationsResponse();

  ListOperationsResponse.fromJson(core.Map _json) {
    if (_json.containsKey("nextPageToken")) {
      nextPageToken = _json["nextPageToken"];
    }
    if (_json.containsKey("operations")) {
      operations = (_json["operations"] as core.List)
          .map<Operation>((value) => new Operation.fromJson(value))
          .toList();
    }
  }

  core.Map<core.String, core.Object> toJson() {
    final core.Map<core.String, core.Object> _json =
        new core.Map<core.String, core.Object>();
    if (nextPageToken != null) {
      _json["nextPageToken"] = nextPageToken;
    }
    if (operations != null) {
      _json["operations"] =
          operations.map((value) => (value).toJson()).toList();
    }
    return _json;
  }
}

/// This resource represents a long-running operation that is the result of a
/// network API call.
class Operation {
  /// If the value is `false`, it means the operation is still in progress.
  /// If `true`, the operation is completed, and either `error` or `response` is
  /// available.
  core.bool done;

  /// The error result of the operation in case of failure or cancellation.
  Status error;

  /// Service-specific metadata associated with the operation.  It typically
  /// contains progress information and common metadata such as create time.
  /// Some services might not provide such metadata.  Any method that returns a
  /// long-running operation should document the metadata type, if any.
  ///
  /// The values for Object must be JSON objects. It can consist of `num`,
  /// `String`, `bool` and `null` as well as `Map` and `List` values.
  core.Map<core.String, core.Object> metadata;

  /// The server-assigned name, which is only unique within the same service
  /// that
  /// originally returns it. If you use the default HTTP mapping, the
  /// `name` should be a resource name ending with `operations/{unique_id}`.
  core.String name;

  /// The normal response of the operation in case of success.  If the original
  /// method returns no data on success, such as `Delete`, the response is
  /// `google.protobuf.Empty`.  If the original method is standard
  /// `Get`/`Create`/`Update`, the response should be the resource.  For other
  /// methods, the response should have the type `XxxResponse`, where `Xxx`
  /// is the original method name.  For example, if the original method name
  /// is `TakeSnapshot()`, the inferred response type is
  /// `TakeSnapshotResponse`.
  ///
  /// The values for Object must be JSON objects. It can consist of `num`,
  /// `String`, `bool` and `null` as well as `Map` and `List` values.
  core.Map<core.String, core.Object> response;

  Operation();

  Operation.fromJson(core.Map _json) {
    if (_json.containsKey("done")) {
      done = _json["done"];
    }
    if (_json.containsKey("error")) {
      error = new Status.fromJson(_json["error"]);
    }
    if (_json.containsKey("metadata")) {
      metadata =
          (_json["metadata"] as core.Map).cast<core.String, core.Object>();
    }
    if (_json.containsKey("name")) {
      name = _json["name"];
    }
    if (_json.containsKey("response")) {
      response =
          (_json["response"] as core.Map).cast<core.String, core.Object>();
    }
  }

  core.Map<core.String, core.Object> toJson() {
    final core.Map<core.String, core.Object> _json =
        new core.Map<core.String, core.Object>();
    if (done != null) {
      _json["done"] = done;
    }
    if (error != null) {
      _json["error"] = (error).toJson();
    }
    if (metadata != null) {
      _json["metadata"] = metadata;
    }
    if (name != null) {
      _json["name"] = name;
    }
    if (response != null) {
      _json["response"] = response;
    }
    return _json;
  }
}

/// A public SSH key, corresponding to a private SSH key held by the client.
class PublicKey {
  /// Required. Format of this key's content.
  /// Possible string values are:
  /// - "FORMAT_UNSPECIFIED" : Unknown format. Do not use.
  /// - "SSH_DSS" : `ssh-dss` key format (see RFC4253).
  /// - "SSH_RSA" : `ssh-rsa` key format (see RFC4253).
  /// - "ECDSA_SHA2_NISTP256" : `ecdsa-sha2-nistp256` key format (see RFC5656).
  /// - "ECDSA_SHA2_NISTP384" : `ecdsa-sha2-nistp384` key format (see RFC5656).
  /// - "ECDSA_SHA2_NISTP521" : `ecdsa-sha2-nistp521` key format (see RFC5656).
  core.String format;

  /// Required. Content of this key.
  core.String key;
  core.List<core.int> get keyAsBytes {
    return convert.base64.decode(key);
  }

  set keyAsBytes(core.List<core.int> _bytes) {
    key =
        convert.base64.encode(_bytes).replaceAll("/", "_").replaceAll("+", "-");
  }

  /// Output only. Full name of this resource, in the format
  /// `users/{owner_email}/environments/{environment_id}/publicKeys/{key_id}`.
  /// `{owner_email}` is the email address of the user to whom the key belongs.
  /// `{environment_id}` is the identifier of the environment to which the key
  /// grants access. `{key_id}` is the unique identifier of the key. For
  /// example,
  /// `users/someone@example.com/environments/default/publicKeys/myKey`.
  core.String name;

  PublicKey();

  PublicKey.fromJson(core.Map _json) {
    if (_json.containsKey("format")) {
      format = _json["format"];
    }
    if (_json.containsKey("key")) {
      key = _json["key"];
    }
    if (_json.containsKey("name")) {
      name = _json["name"];
    }
  }

  core.Map<core.String, core.Object> toJson() {
    final core.Map<core.String, core.Object> _json =
        new core.Map<core.String, core.Object>();
    if (format != null) {
      _json["format"] = format;
    }
    if (key != null) {
      _json["key"] = key;
    }
    if (name != null) {
      _json["name"] = name;
    }
    return _json;
  }
}

/// Message included in the metadata field of operations returned from
/// StartEnvironment.
class StartEnvironmentMetadata {
  /// Current state of the environment being started.
  /// Possible string values are:
  /// - "STATE_UNSPECIFIED" : The environment's start state is unknown.
  /// - "STARTING" : The environment is in the process of being started, but no
  /// additional
  /// details are available.
  /// - "UNARCHIVING_DISK" : Startup is waiting for the user's disk to be
  /// unarchived. This can happen
  /// when the user returns to Cloud Shell after not having used it for a
  /// while, and suggests that startup will take longer than normal.
  /// - "AWAITING_VM" : Startup is waiting for a VM to be assigned to the
  /// environment. This
  /// should normally happen very quickly, but an environment might stay in
  /// this state for an extended period of time if the system is experiencing
  /// heavy load.
  /// - "AWAITING_COMPUTE_RESOURCES" : Startup is waiting for compute resources
  /// to be assigned to the
  /// environment. This should normally happen very quickly, but an environment
  /// might stay in this state for an extended period of time if the system is
  /// experiencing heavy load.
  /// - "FINISHED" : Startup has completed. If the start operation was
  /// successful, the user
  /// should be able to establish an SSH connection to their environment.
  /// Otherwise, the operation will contain details of the failure.
  core.String state;

  StartEnvironmentMetadata();

  StartEnvironmentMetadata.fromJson(core.Map _json) {
    if (_json.containsKey("state")) {
      state = _json["state"];
    }
  }

  core.Map<core.String, core.Object> toJson() {
    final core.Map<core.String, core.Object> _json =
        new core.Map<core.String, core.Object>();
    if (state != null) {
      _json["state"] = state;
    }
    return _json;
  }
}

/// Message included in the response field of operations returned from
/// StartEnvironment once the
/// operation is complete.
class StartEnvironmentResponse {
  /// Environment that was started.
  Environment environment;

  StartEnvironmentResponse();

  StartEnvironmentResponse.fromJson(core.Map _json) {
    if (_json.containsKey("environment")) {
      environment = new Environment.fromJson(_json["environment"]);
    }
  }

  core.Map<core.String, core.Object> toJson() {
    final core.Map<core.String, core.Object> _json =
        new core.Map<core.String, core.Object>();
    if (environment != null) {
      _json["environment"] = (environment).toJson();
    }
    return _json;
  }
}

/// The `Status` type defines a logical error model that is suitable for
/// different programming environments, including REST APIs and RPC APIs. It is
/// used by [gRPC](https://github.com/grpc). Each `Status` message contains
/// three pieces of data: error code, error message, and error details.
///
/// You can find out more about this error model and how to work with it in the
/// [API Design Guide](https://cloud.google.com/apis/design/errors).
class Status {
  /// The status code, which should be an enum value of google.rpc.Code.
  core.int code;

  /// A list of messages that carry the error details.  There is a common set of
  /// message types for APIs to use.
  ///
  /// The values for Object must be JSON objects. It can consist of `num`,
  /// `String`, `bool` and `null` as well as `Map` and `List` values.
  core.List<core.Map<core.String, core.Object>> details;

  /// A developer-facing error message, which should be in English. Any
  /// user-facing error message should be localized and sent in the
  /// google.rpc.Status.details field, or localized by the client.
  core.String message;

  Status();

  Status.fromJson(core.Map _json) {
    if (_json.containsKey("code")) {
      code = _json["code"];
    }
    if (_json.containsKey("details")) {
      details = (_json["details"] as core.List)
          .map<core.Map<core.String, core.Object>>(
              (value) => (value as core.Map).cast<core.String, core.Object>())
          .toList();
    }
    if (_json.containsKey("message")) {
      message = _json["message"];
    }
  }

  core.Map<core.String, core.Object> toJson() {
    final core.Map<core.String, core.Object> _json =
        new core.Map<core.String, core.Object>();
    if (code != null) {
      _json["code"] = code;
    }
    if (details != null) {
      _json["details"] = details;
    }
    if (message != null) {
      _json["message"] = message;
    }
    return _json;
  }
}
