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

// ignore_for_file: camel_case_types
// ignore_for_file: comment_references
// ignore_for_file: file_names
// ignore_for_file: library_names
// ignore_for_file: lines_longer_than_80_chars
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: prefer_expression_function_bodies
// ignore_for_file: prefer_interpolation_to_compose_strings
// ignore_for_file: unnecessary_brace_in_string_interps
// ignore_for_file: unnecessary_lambdas
// ignore_for_file: unnecessary_string_interpolations

/// Google Forms API - v1
///
/// Reads and writes Google Forms and responses.
///
/// For more information, see <https://developers.google.com/forms/api>
///
/// Create an instance of [FormsApi] to access these resources:
///
/// - [FormsResource]
///   - [FormsResponsesResource]
///   - [FormsWatchesResource]
library forms.v1;

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

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

// ignore: deprecated_member_use_from_same_package
import '../shared.dart';
import '../src/user_agent.dart';

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

/// Reads and writes Google Forms and responses.
class FormsApi {
  /// See, edit, create, and delete all of your Google Drive files
  static const driveScope = 'https://www.googleapis.com/auth/drive';

  /// See, edit, create, and delete only the specific Google Drive files you use
  /// with this app
  static const driveFileScope = 'https://www.googleapis.com/auth/drive.file';

  /// See and download all your Google Drive files
  static const driveReadonlyScope =
      'https://www.googleapis.com/auth/drive.readonly';

  /// See, edit, create, and delete all your Google Forms forms
  static const formsBodyScope = 'https://www.googleapis.com/auth/forms.body';

  /// See all your Google Forms forms
  static const formsBodyReadonlyScope =
      'https://www.googleapis.com/auth/forms.body.readonly';

  /// See all responses to your Google Forms forms
  static const formsResponsesReadonlyScope =
      'https://www.googleapis.com/auth/forms.responses.readonly';

  final commons.ApiRequester _requester;

  FormsResource get forms => FormsResource(_requester);

  FormsApi(http.Client client,
      {core.String rootUrl = 'https://forms.googleapis.com/',
      core.String servicePath = ''})
      : _requester =
            commons.ApiRequester(client, rootUrl, servicePath, requestHeaders);
}

class FormsResource {
  final commons.ApiRequester _requester;

  FormsResponsesResource get responses => FormsResponsesResource(_requester);
  FormsWatchesResource get watches => FormsWatchesResource(_requester);

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

  /// Change the form with a batch of updates.
  ///
  /// [request] - The metadata request object.
  ///
  /// Request parameters:
  ///
  /// [formId] - Required. The form ID.
  ///
  /// [$fields] - Selector specifying which fields to include in a partial
  /// response.
  ///
  /// Completes with a [BatchUpdateFormResponse].
  ///
  /// 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<BatchUpdateFormResponse> batchUpdate(
    BatchUpdateFormRequest request,
    core.String formId, {
    core.String? $fields,
  }) async {
    final body_ = convert.json.encode(request);
    final queryParams_ = <core.String, core.List<core.String>>{
      if ($fields != null) 'fields': [$fields],
    };

    final url_ =
        'v1/forms/' + commons.escapeVariable('$formId') + ':batchUpdate';

    final response_ = await _requester.request(
      url_,
      'POST',
      body: body_,
      queryParams: queryParams_,
    );
    return BatchUpdateFormResponse.fromJson(
        response_ as core.Map<core.String, core.dynamic>);
  }

  /// Create a new form using the title given in the provided form message in
  /// the request.
  ///
  /// *Important:* Only the form.info.title and form.info.document_title fields
  /// are copied to the new form. All other fields including the form
  /// description, items and settings are disallowed. To create a new form and
  /// add items, you must first call forms.create to create an empty form with a
  /// title and (optional) document title, and then call forms.update to add the
  /// items.
  ///
  /// [request] - The metadata request object.
  ///
  /// Request parameters:
  ///
  /// [$fields] - Selector specifying which fields to include in a partial
  /// response.
  ///
  /// Completes with a [Form].
  ///
  /// 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<Form> create(
    Form request, {
    core.String? $fields,
  }) async {
    final body_ = convert.json.encode(request);
    final queryParams_ = <core.String, core.List<core.String>>{
      if ($fields != null) 'fields': [$fields],
    };

    const url_ = 'v1/forms';

    final response_ = await _requester.request(
      url_,
      'POST',
      body: body_,
      queryParams: queryParams_,
    );
    return Form.fromJson(response_ as core.Map<core.String, core.dynamic>);
  }

  /// Get a form.
  ///
  /// Request parameters:
  ///
  /// [formId] - Required. The form ID.
  ///
  /// [$fields] - Selector specifying which fields to include in a partial
  /// response.
  ///
  /// Completes with a [Form].
  ///
  /// 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<Form> get(
    core.String formId, {
    core.String? $fields,
  }) async {
    final queryParams_ = <core.String, core.List<core.String>>{
      if ($fields != null) 'fields': [$fields],
    };

    final url_ = 'v1/forms/' + commons.escapeVariable('$formId');

    final response_ = await _requester.request(
      url_,
      'GET',
      queryParams: queryParams_,
    );
    return Form.fromJson(response_ as core.Map<core.String, core.dynamic>);
  }
}

class FormsResponsesResource {
  final commons.ApiRequester _requester;

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

  /// Get one response from the form.
  ///
  /// Request parameters:
  ///
  /// [formId] - Required. The form ID.
  ///
  /// [responseId] - Required. The response ID within the form.
  ///
  /// [$fields] - Selector specifying which fields to include in a partial
  /// response.
  ///
  /// Completes with a [FormResponse].
  ///
  /// 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<FormResponse> get(
    core.String formId,
    core.String responseId, {
    core.String? $fields,
  }) async {
    final queryParams_ = <core.String, core.List<core.String>>{
      if ($fields != null) 'fields': [$fields],
    };

    final url_ = 'v1/forms/' +
        commons.escapeVariable('$formId') +
        '/responses/' +
        commons.escapeVariable('$responseId');

    final response_ = await _requester.request(
      url_,
      'GET',
      queryParams: queryParams_,
    );
    return FormResponse.fromJson(
        response_ as core.Map<core.String, core.dynamic>);
  }

  /// List a form's responses.
  ///
  /// Request parameters:
  ///
  /// [formId] - Required. ID of the Form whose responses to list.
  ///
  /// [filter] - Which form responses to return. Currently, the only supported
  /// filters are: * timestamp \> *N* which means to get all form responses
  /// submitted after (but not at) timestamp *N*. * timestamp \>= *N* which
  /// means to get all form responses submitted at and after timestamp *N*. For
  /// both supported filters, timestamp must be formatted in RFC3339 UTC "Zulu"
  /// format. Examples: "2014-10-02T15:01:23Z" and
  /// "2014-10-02T15:01:23.045123456Z".
  ///
  /// [pageSize] - The maximum number of responses to return. The service may
  /// return fewer than this value. If unspecified or zero, at most 5000
  /// responses are returned.
  ///
  /// [pageToken] - A page token returned by a previous list response. If this
  /// field is set, the form and the values of the filter must be the same as
  /// for the original request.
  ///
  /// [$fields] - Selector specifying which fields to include in a partial
  /// response.
  ///
  /// Completes with a [ListFormResponsesResponse].
  ///
  /// 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<ListFormResponsesResponse> list(
    core.String formId, {
    core.String? filter,
    core.int? pageSize,
    core.String? pageToken,
    core.String? $fields,
  }) async {
    final queryParams_ = <core.String, core.List<core.String>>{
      if (filter != null) 'filter': [filter],
      if (pageSize != null) 'pageSize': ['${pageSize}'],
      if (pageToken != null) 'pageToken': [pageToken],
      if ($fields != null) 'fields': [$fields],
    };

    final url_ = 'v1/forms/' + commons.escapeVariable('$formId') + '/responses';

    final response_ = await _requester.request(
      url_,
      'GET',
      queryParams: queryParams_,
    );
    return ListFormResponsesResponse.fromJson(
        response_ as core.Map<core.String, core.dynamic>);
  }
}

class FormsWatchesResource {
  final commons.ApiRequester _requester;

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

  /// Create a new watch.
  ///
  /// If a watch ID is provided, it must be unused. For each invoking project,
  /// the per form limit is one watch per Watch.EventType. A watch expires seven
  /// days after it is created (see Watch.expire_time).
  ///
  /// [request] - The metadata request object.
  ///
  /// Request parameters:
  ///
  /// [formId] - Required. ID of the Form to watch.
  ///
  /// [$fields] - Selector specifying which fields to include in a partial
  /// response.
  ///
  /// Completes with a [Watch].
  ///
  /// 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<Watch> create(
    CreateWatchRequest request,
    core.String formId, {
    core.String? $fields,
  }) async {
    final body_ = convert.json.encode(request);
    final queryParams_ = <core.String, core.List<core.String>>{
      if ($fields != null) 'fields': [$fields],
    };

    final url_ = 'v1/forms/' + commons.escapeVariable('$formId') + '/watches';

    final response_ = await _requester.request(
      url_,
      'POST',
      body: body_,
      queryParams: queryParams_,
    );
    return Watch.fromJson(response_ as core.Map<core.String, core.dynamic>);
  }

  /// Delete a watch.
  ///
  /// Request parameters:
  ///
  /// [formId] - Required. The ID of the Form.
  ///
  /// [watchId] - Required. The ID of the Watch to delete.
  ///
  /// [$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 formId,
    core.String watchId, {
    core.String? $fields,
  }) async {
    final queryParams_ = <core.String, core.List<core.String>>{
      if ($fields != null) 'fields': [$fields],
    };

    final url_ = 'v1/forms/' +
        commons.escapeVariable('$formId') +
        '/watches/' +
        commons.escapeVariable('$watchId');

    final response_ = await _requester.request(
      url_,
      'DELETE',
      queryParams: queryParams_,
    );
    return Empty.fromJson(response_ as core.Map<core.String, core.dynamic>);
  }

  /// Return a list of the watches owned by the invoking project.
  ///
  /// The maximum number of watches is two: For each invoker, the limit is one
  /// for each event type per form.
  ///
  /// Request parameters:
  ///
  /// [formId] - Required. ID of the Form whose watches to list.
  ///
  /// [$fields] - Selector specifying which fields to include in a partial
  /// response.
  ///
  /// Completes with a [ListWatchesResponse].
  ///
  /// 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<ListWatchesResponse> list(
    core.String formId, {
    core.String? $fields,
  }) async {
    final queryParams_ = <core.String, core.List<core.String>>{
      if ($fields != null) 'fields': [$fields],
    };

    final url_ = 'v1/forms/' + commons.escapeVariable('$formId') + '/watches';

    final response_ = await _requester.request(
      url_,
      'GET',
      queryParams: queryParams_,
    );
    return ListWatchesResponse.fromJson(
        response_ as core.Map<core.String, core.dynamic>);
  }

  /// Renew an existing watch for seven days.
  ///
  /// The state of the watch after renewal is `ACTIVE`, and the `expire_time` is
  /// seven days from the renewal. Renewing a watch in an error state (e.g.
  /// `SUSPENDED`) succeeds if the error is no longer present, but fail
  /// otherwise. After a watch has expired, RenewWatch returns `NOT_FOUND`.
  ///
  /// [request] - The metadata request object.
  ///
  /// Request parameters:
  ///
  /// [formId] - Required. The ID of the Form.
  ///
  /// [watchId] - Required. The ID of the Watch to renew.
  ///
  /// [$fields] - Selector specifying which fields to include in a partial
  /// response.
  ///
  /// Completes with a [Watch].
  ///
  /// 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<Watch> renew(
    RenewWatchRequest request,
    core.String formId,
    core.String watchId, {
    core.String? $fields,
  }) async {
    final body_ = convert.json.encode(request);
    final queryParams_ = <core.String, core.List<core.String>>{
      if ($fields != null) 'fields': [$fields],
    };

    final url_ = 'v1/forms/' +
        commons.escapeVariable('$formId') +
        '/watches/' +
        commons.escapeVariable('$watchId') +
        ':renew';

    final response_ = await _requester.request(
      url_,
      'POST',
      body: body_,
      queryParams: queryParams_,
    );
    return Watch.fromJson(response_ as core.Map<core.String, core.dynamic>);
  }
}

/// The submitted answer for a question.
class Answer {
  /// The answers to a file upload question.
  ///
  /// Output only.
  FileUploadAnswers? fileUploadAnswers;

  /// The grade for the answer if the form was a quiz.
  ///
  /// Output only.
  Grade? grade;

  /// The question's ID.
  ///
  /// See also Question.question_id.
  ///
  /// Output only.
  core.String? questionId;

  /// The specific answers as text.
  ///
  /// Output only.
  TextAnswers? textAnswers;

  Answer({
    this.fileUploadAnswers,
    this.grade,
    this.questionId,
    this.textAnswers,
  });

  Answer.fromJson(core.Map json_)
      : this(
          fileUploadAnswers: json_.containsKey('fileUploadAnswers')
              ? FileUploadAnswers.fromJson(json_['fileUploadAnswers']
                  as core.Map<core.String, core.dynamic>)
              : null,
          grade: json_.containsKey('grade')
              ? Grade.fromJson(
                  json_['grade'] as core.Map<core.String, core.dynamic>)
              : null,
          questionId: json_.containsKey('questionId')
              ? json_['questionId'] as core.String
              : null,
          textAnswers: json_.containsKey('textAnswers')
              ? TextAnswers.fromJson(
                  json_['textAnswers'] as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (fileUploadAnswers != null) 'fileUploadAnswers': fileUploadAnswers!,
        if (grade != null) 'grade': grade!,
        if (questionId != null) 'questionId': questionId!,
        if (textAnswers != null) 'textAnswers': textAnswers!,
      };
}

/// A batch of updates to perform on a form.
///
/// All the specified updates are made or none of them are.
class BatchUpdateFormRequest {
  /// Whether to return an updated version of the model in the response.
  core.bool? includeFormInResponse;

  /// The update requests of this batch.
  ///
  /// Required.
  core.List<Request>? requests;

  /// Provides control over how write requests are executed.
  WriteControl? writeControl;

  BatchUpdateFormRequest({
    this.includeFormInResponse,
    this.requests,
    this.writeControl,
  });

  BatchUpdateFormRequest.fromJson(core.Map json_)
      : this(
          includeFormInResponse: json_.containsKey('includeFormInResponse')
              ? json_['includeFormInResponse'] as core.bool
              : null,
          requests: json_.containsKey('requests')
              ? (json_['requests'] as core.List)
                  .map((value) => Request.fromJson(
                      value as core.Map<core.String, core.dynamic>))
                  .toList()
              : null,
          writeControl: json_.containsKey('writeControl')
              ? WriteControl.fromJson(
                  json_['writeControl'] as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (includeFormInResponse != null)
          'includeFormInResponse': includeFormInResponse!,
        if (requests != null) 'requests': requests!,
        if (writeControl != null) 'writeControl': writeControl!,
      };
}

/// Response to a BatchUpdateFormRequest.
class BatchUpdateFormResponse {
  /// Based on the bool request field `include_form_in_response`, a form with
  /// all applied mutations/updates is returned or not.
  ///
  /// This may be later than the revision ID created by these changes.
  Form? form;

  /// The reply of the updates.
  ///
  /// This maps 1:1 with the update requests, although replies to some requests
  /// may be empty.
  core.List<Response>? replies;

  /// The updated write control after applying the request.
  WriteControl? writeControl;

  BatchUpdateFormResponse({
    this.form,
    this.replies,
    this.writeControl,
  });

  BatchUpdateFormResponse.fromJson(core.Map json_)
      : this(
          form: json_.containsKey('form')
              ? Form.fromJson(
                  json_['form'] as core.Map<core.String, core.dynamic>)
              : null,
          replies: json_.containsKey('replies')
              ? (json_['replies'] as core.List)
                  .map((value) => Response.fromJson(
                      value as core.Map<core.String, core.dynamic>))
                  .toList()
              : null,
          writeControl: json_.containsKey('writeControl')
              ? WriteControl.fromJson(
                  json_['writeControl'] as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (form != null) 'form': form!,
        if (replies != null) 'replies': replies!,
        if (writeControl != null) 'writeControl': writeControl!,
      };
}

/// A radio/checkbox/dropdown question.
class ChoiceQuestion {
  /// List of options that a respondent must choose from.
  ///
  /// Required.
  core.List<Option>? options;

  /// Whether the options should be displayed in random order for different
  /// instances of the quiz.
  ///
  /// This is often used to prevent cheating by respondents who might be looking
  /// at another respondent's screen, or to address bias in a survey that might
  /// be introduced by always putting the same options first or last.
  core.bool? shuffle;

  /// The type of choice question.
  ///
  /// Required.
  /// Possible string values are:
  /// - "CHOICE_TYPE_UNSPECIFIED" : Default value. Unused.
  /// - "RADIO" : Radio buttons: All choices are shown to the user, who can only
  /// pick one of them.
  /// - "CHECKBOX" : Checkboxes: All choices are shown to the user, who can pick
  /// any number of them.
  /// - "DROP_DOWN" : Drop-down menu: The choices are only shown to the user on
  /// demand, otherwise only the current choice is shown. Only one option can be
  /// chosen.
  core.String? type;

  ChoiceQuestion({
    this.options,
    this.shuffle,
    this.type,
  });

  ChoiceQuestion.fromJson(core.Map json_)
      : this(
          options: json_.containsKey('options')
              ? (json_['options'] as core.List)
                  .map((value) => Option.fromJson(
                      value as core.Map<core.String, core.dynamic>))
                  .toList()
              : null,
          shuffle: json_.containsKey('shuffle')
              ? json_['shuffle'] as core.bool
              : null,
          type: json_.containsKey('type') ? json_['type'] as core.String : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (options != null) 'options': options!,
        if (shuffle != null) 'shuffle': shuffle!,
        if (type != null) 'type': type!,
      };
}

/// A Pub/Sub topic.
class CloudPubsubTopic {
  /// A fully qualified Pub/Sub topic name to publish the events to.
  ///
  /// This topic must be owned by the calling project and already exist in
  /// Pub/Sub.
  ///
  /// Required.
  core.String? topicName;

  CloudPubsubTopic({
    this.topicName,
  });

  CloudPubsubTopic.fromJson(core.Map json_)
      : this(
          topicName: json_.containsKey('topicName')
              ? json_['topicName'] as core.String
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (topicName != null) 'topicName': topicName!,
      };
}

/// A single correct answer for a question.
///
/// For multiple-valued (`CHECKBOX`) questions, several `CorrectAnswer`s may be
/// needed to represent a single correct response option.
class CorrectAnswer {
  /// The correct answer value.
  ///
  /// See the documentation for TextAnswer.value for details on how various
  /// value types are formatted.
  ///
  /// Required.
  core.String? value;

  CorrectAnswer({
    this.value,
  });

  CorrectAnswer.fromJson(core.Map json_)
      : this(
          value:
              json_.containsKey('value') ? json_['value'] as core.String : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (value != null) 'value': value!,
      };
}

/// The answer key for a question.
class CorrectAnswers {
  /// A list of correct answers.
  ///
  /// A quiz response can be automatically graded based on these answers. For
  /// single-valued questions, a response is marked correct if it matches any
  /// value in this list (in other words, multiple correct answers are
  /// possible). For multiple-valued (`CHECKBOX`) questions, a response is
  /// marked correct if it contains exactly the values in this list.
  core.List<CorrectAnswer>? answers;

  CorrectAnswers({
    this.answers,
  });

  CorrectAnswers.fromJson(core.Map json_)
      : this(
          answers: json_.containsKey('answers')
              ? (json_['answers'] as core.List)
                  .map((value) => CorrectAnswer.fromJson(
                      value as core.Map<core.String, core.dynamic>))
                  .toList()
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (answers != null) 'answers': answers!,
      };
}

/// Create an item in a form.
class CreateItemRequest {
  /// The item to create.
  ///
  /// Required.
  Item? item;

  /// Where to place the new item.
  ///
  /// Required.
  Location? location;

  CreateItemRequest({
    this.item,
    this.location,
  });

  CreateItemRequest.fromJson(core.Map json_)
      : this(
          item: json_.containsKey('item')
              ? Item.fromJson(
                  json_['item'] as core.Map<core.String, core.dynamic>)
              : null,
          location: json_.containsKey('location')
              ? Location.fromJson(
                  json_['location'] as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (item != null) 'item': item!,
        if (location != null) 'location': location!,
      };
}

/// The result of creating an item.
class CreateItemResponse {
  /// The ID of the created item.
  core.String? itemId;

  /// The ID of the question created as part of this item, for a question group
  /// it lists IDs of all the questions created for this item.
  core.List<core.String>? questionId;

  CreateItemResponse({
    this.itemId,
    this.questionId,
  });

  CreateItemResponse.fromJson(core.Map json_)
      : this(
          itemId: json_.containsKey('itemId')
              ? json_['itemId'] as core.String
              : null,
          questionId: json_.containsKey('questionId')
              ? (json_['questionId'] as core.List)
                  .map((value) => value as core.String)
                  .toList()
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (itemId != null) 'itemId': itemId!,
        if (questionId != null) 'questionId': questionId!,
      };
}

/// Create a new watch.
class CreateWatchRequest {
  /// The watch object.
  ///
  /// No ID should be set on this object; use `watch_id` instead.
  ///
  /// Required.
  Watch? watch;

  /// The ID to use for the watch.
  ///
  /// If specified, the ID must not already be in use. If not specified, an ID
  /// is generated. This value should be 4-63 characters, and valid characters
  /// are /a-z-/.
  core.String? watchId;

  CreateWatchRequest({
    this.watch,
    this.watchId,
  });

  CreateWatchRequest.fromJson(core.Map json_)
      : this(
          watch: json_.containsKey('watch')
              ? Watch.fromJson(
                  json_['watch'] as core.Map<core.String, core.dynamic>)
              : null,
          watchId: json_.containsKey('watchId')
              ? json_['watchId'] as core.String
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (watch != null) 'watch': watch!,
        if (watchId != null) 'watchId': watchId!,
      };
}

/// A date question.
///
/// Date questions default to just month + day.
class DateQuestion {
  /// Whether to include the time as part of the question.
  core.bool? includeTime;

  /// Whether to include the year as part of the question.
  core.bool? includeYear;

  DateQuestion({
    this.includeTime,
    this.includeYear,
  });

  DateQuestion.fromJson(core.Map json_)
      : this(
          includeTime: json_.containsKey('includeTime')
              ? json_['includeTime'] as core.bool
              : null,
          includeYear: json_.containsKey('includeYear')
              ? json_['includeYear'] as core.bool
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (includeTime != null) 'includeTime': includeTime!,
        if (includeYear != null) 'includeYear': includeYear!,
      };
}

/// Delete an item in a form.
class DeleteItemRequest {
  /// The location of the item to delete.
  ///
  /// Required.
  Location? location;

  DeleteItemRequest({
    this.location,
  });

  DeleteItemRequest.fromJson(core.Map json_)
      : this(
          location: json_.containsKey('location')
              ? Location.fromJson(
                  json_['location'] as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (location != null) 'location': location!,
      };
}

/// 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); }
typedef Empty = $Empty;

/// Supplementary material to the feedback.
class ExtraMaterial {
  /// Text feedback.
  TextLink? link;

  /// Video feedback.
  VideoLink? video;

  ExtraMaterial({
    this.link,
    this.video,
  });

  ExtraMaterial.fromJson(core.Map json_)
      : this(
          link: json_.containsKey('link')
              ? TextLink.fromJson(
                  json_['link'] as core.Map<core.String, core.dynamic>)
              : null,
          video: json_.containsKey('video')
              ? VideoLink.fromJson(
                  json_['video'] as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (link != null) 'link': link!,
        if (video != null) 'video': video!,
      };
}

/// Feedback for a respondent about their response to a question.
class Feedback {
  /// Additional information provided as part of the feedback, often used to
  /// point the respondent to more reading and resources.
  core.List<ExtraMaterial>? material;

  /// The main text of the feedback.
  ///
  /// Required.
  core.String? text;

  Feedback({
    this.material,
    this.text,
  });

  Feedback.fromJson(core.Map json_)
      : this(
          material: json_.containsKey('material')
              ? (json_['material'] as core.List)
                  .map((value) => ExtraMaterial.fromJson(
                      value as core.Map<core.String, core.dynamic>))
                  .toList()
              : null,
          text: json_.containsKey('text') ? json_['text'] as core.String : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (material != null) 'material': material!,
        if (text != null) 'text': text!,
      };
}

/// Info for a single file submitted to a file upload question.
class FileUploadAnswer {
  /// The ID of the Google Drive file.
  ///
  /// Output only.
  core.String? fileId;

  /// The file name, as stored in Google Drive on upload.
  ///
  /// Output only.
  core.String? fileName;

  /// The MIME type of the file, as stored in Google Drive on upload.
  ///
  /// Output only.
  core.String? mimeType;

  FileUploadAnswer({
    this.fileId,
    this.fileName,
    this.mimeType,
  });

  FileUploadAnswer.fromJson(core.Map json_)
      : this(
          fileId: json_.containsKey('fileId')
              ? json_['fileId'] as core.String
              : null,
          fileName: json_.containsKey('fileName')
              ? json_['fileName'] as core.String
              : null,
          mimeType: json_.containsKey('mimeType')
              ? json_['mimeType'] as core.String
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (fileId != null) 'fileId': fileId!,
        if (fileName != null) 'fileName': fileName!,
        if (mimeType != null) 'mimeType': mimeType!,
      };
}

/// All submitted files for a FileUpload question.
class FileUploadAnswers {
  /// All submitted files for a FileUpload question.
  ///
  /// Output only.
  core.List<FileUploadAnswer>? answers;

  FileUploadAnswers({
    this.answers,
  });

  FileUploadAnswers.fromJson(core.Map json_)
      : this(
          answers: json_.containsKey('answers')
              ? (json_['answers'] as core.List)
                  .map((value) => FileUploadAnswer.fromJson(
                      value as core.Map<core.String, core.dynamic>))
                  .toList()
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (answers != null) 'answers': answers!,
      };
}

/// A file upload question.
///
/// The API currently does not support creating file upload questions.
class FileUploadQuestion {
  /// The ID of the Drive folder where uploaded files are stored.
  ///
  /// Required.
  core.String? folderId;

  /// Maximum number of bytes allowed for any single file uploaded to this
  /// question.
  core.String? maxFileSize;

  /// Maximum number of files that can be uploaded for this question in a single
  /// response.
  core.int? maxFiles;

  /// File types accepted by this question.
  core.List<core.String>? types;

  FileUploadQuestion({
    this.folderId,
    this.maxFileSize,
    this.maxFiles,
    this.types,
  });

  FileUploadQuestion.fromJson(core.Map json_)
      : this(
          folderId: json_.containsKey('folderId')
              ? json_['folderId'] as core.String
              : null,
          maxFileSize: json_.containsKey('maxFileSize')
              ? json_['maxFileSize'] as core.String
              : null,
          maxFiles: json_.containsKey('maxFiles')
              ? json_['maxFiles'] as core.int
              : null,
          types: json_.containsKey('types')
              ? (json_['types'] as core.List)
                  .map((value) => value as core.String)
                  .toList()
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (folderId != null) 'folderId': folderId!,
        if (maxFileSize != null) 'maxFileSize': maxFileSize!,
        if (maxFiles != null) 'maxFiles': maxFiles!,
        if (types != null) 'types': types!,
      };
}

/// A Google Forms document.
///
/// A form is created in Drive, and deleting a form or changing its access
/// protections is done via the
/// [Drive API](https://developers.google.com/drive/api/v3/about-sdk).
class Form {
  /// The form ID.
  ///
  /// Output only.
  core.String? formId;

  /// The title and description of the form.
  ///
  /// Required.
  Info? info;

  /// A list of the form's items, which can include section headers, questions,
  /// embedded media, etc.
  ///
  /// Required.
  core.List<Item>? items;

  /// The ID of the linked Google Sheet which is accumulating responses from
  /// this Form (if such a Sheet exists).
  ///
  /// Output only.
  core.String? linkedSheetId;

  /// The form URI to share with responders.
  ///
  /// This opens a page that allows the user to submit responses but not edit
  /// the questions.
  ///
  /// Output only.
  core.String? responderUri;

  /// The revision ID of the form.
  ///
  /// Used in the WriteControl in update requests to identify the revision on
  /// which the changes are based. The format of the revision ID may change over
  /// time, so it should be treated opaquely. A returned revision ID is only
  /// guaranteed to be valid for 24 hours after it has been returned and cannot
  /// be shared across users. If the revision ID is unchanged between calls,
  /// then the form has not changed. Conversely, a changed ID (for the same form
  /// and user) usually means the form has been updated; however, a changed ID
  /// can also be due to internal factors such as ID format changes.
  ///
  /// Output only.
  core.String? revisionId;

  /// The form's settings.
  ///
  /// This must be updated with UpdateSettingsRequest; it is ignored during
  /// `forms.create` and UpdateFormInfoRequest.
  FormSettings? settings;

  Form({
    this.formId,
    this.info,
    this.items,
    this.linkedSheetId,
    this.responderUri,
    this.revisionId,
    this.settings,
  });

  Form.fromJson(core.Map json_)
      : this(
          formId: json_.containsKey('formId')
              ? json_['formId'] as core.String
              : null,
          info: json_.containsKey('info')
              ? Info.fromJson(
                  json_['info'] as core.Map<core.String, core.dynamic>)
              : null,
          items: json_.containsKey('items')
              ? (json_['items'] as core.List)
                  .map((value) => Item.fromJson(
                      value as core.Map<core.String, core.dynamic>))
                  .toList()
              : null,
          linkedSheetId: json_.containsKey('linkedSheetId')
              ? json_['linkedSheetId'] as core.String
              : null,
          responderUri: json_.containsKey('responderUri')
              ? json_['responderUri'] as core.String
              : null,
          revisionId: json_.containsKey('revisionId')
              ? json_['revisionId'] as core.String
              : null,
          settings: json_.containsKey('settings')
              ? FormSettings.fromJson(
                  json_['settings'] as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (formId != null) 'formId': formId!,
        if (info != null) 'info': info!,
        if (items != null) 'items': items!,
        if (linkedSheetId != null) 'linkedSheetId': linkedSheetId!,
        if (responderUri != null) 'responderUri': responderUri!,
        if (revisionId != null) 'revisionId': revisionId!,
        if (settings != null) 'settings': settings!,
      };
}

/// A form response.
class FormResponse {
  /// The actual answers to the questions, keyed by question_id.
  ///
  /// Output only.
  core.Map<core.String, Answer>? answers;

  /// Timestamp for the first time the response was submitted.
  ///
  /// Output only.
  core.String? createTime;

  /// The form ID.
  ///
  /// Output only.
  core.String? formId;

  /// Timestamp for the most recent time the response was submitted.
  ///
  /// Does not track changes to grades.
  ///
  /// Output only.
  core.String? lastSubmittedTime;

  /// The email address (if collected) for the respondent.
  ///
  /// Output only.
  core.String? respondentEmail;

  /// The response ID.
  ///
  /// Output only.
  core.String? responseId;

  /// The total number of points the respondent received for their submission
  /// Only set if the form was a quiz and the response was graded.
  ///
  /// This includes points automatically awarded via autograding adjusted by any
  /// manual corrections entered by the form owner.
  ///
  /// Output only.
  core.double? totalScore;

  FormResponse({
    this.answers,
    this.createTime,
    this.formId,
    this.lastSubmittedTime,
    this.respondentEmail,
    this.responseId,
    this.totalScore,
  });

  FormResponse.fromJson(core.Map json_)
      : this(
          answers: json_.containsKey('answers')
              ? (json_['answers'] as core.Map<core.String, core.dynamic>).map(
                  (key, item) => core.MapEntry(
                    key,
                    Answer.fromJson(
                        item as core.Map<core.String, core.dynamic>),
                  ),
                )
              : null,
          createTime: json_.containsKey('createTime')
              ? json_['createTime'] as core.String
              : null,
          formId: json_.containsKey('formId')
              ? json_['formId'] as core.String
              : null,
          lastSubmittedTime: json_.containsKey('lastSubmittedTime')
              ? json_['lastSubmittedTime'] as core.String
              : null,
          respondentEmail: json_.containsKey('respondentEmail')
              ? json_['respondentEmail'] as core.String
              : null,
          responseId: json_.containsKey('responseId')
              ? json_['responseId'] as core.String
              : null,
          totalScore: json_.containsKey('totalScore')
              ? (json_['totalScore'] as core.num).toDouble()
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (answers != null) 'answers': answers!,
        if (createTime != null) 'createTime': createTime!,
        if (formId != null) 'formId': formId!,
        if (lastSubmittedTime != null) 'lastSubmittedTime': lastSubmittedTime!,
        if (respondentEmail != null) 'respondentEmail': respondentEmail!,
        if (responseId != null) 'responseId': responseId!,
        if (totalScore != null) 'totalScore': totalScore!,
      };
}

/// A form's settings.
class FormSettings {
  /// Settings related to quiz forms and grading.
  QuizSettings? quizSettings;

  FormSettings({
    this.quizSettings,
  });

  FormSettings.fromJson(core.Map json_)
      : this(
          quizSettings: json_.containsKey('quizSettings')
              ? QuizSettings.fromJson(
                  json_['quizSettings'] as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (quizSettings != null) 'quizSettings': quizSettings!,
      };
}

/// Grade information associated with a respondent's answer to a question.
class Grade {
  /// Whether the question was answered correctly or not.
  ///
  /// A zero-point score is not enough to infer incorrectness, since a correctly
  /// answered question could be worth zero points.
  ///
  /// Output only.
  core.bool? correct;

  /// Additional feedback given for an answer.
  ///
  /// Output only.
  Feedback? feedback;

  /// The numeric score awarded for the answer.
  ///
  /// Output only.
  core.double? score;

  Grade({
    this.correct,
    this.feedback,
    this.score,
  });

  Grade.fromJson(core.Map json_)
      : this(
          correct: json_.containsKey('correct')
              ? json_['correct'] as core.bool
              : null,
          feedback: json_.containsKey('feedback')
              ? Feedback.fromJson(
                  json_['feedback'] as core.Map<core.String, core.dynamic>)
              : null,
          score: json_.containsKey('score')
              ? (json_['score'] as core.num).toDouble()
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (correct != null) 'correct': correct!,
        if (feedback != null) 'feedback': feedback!,
        if (score != null) 'score': score!,
      };
}

/// Grading for a single question
class Grading {
  /// The answer key for the question.
  ///
  /// Responses are automatically graded based on this field.
  ///
  /// Required.
  CorrectAnswers? correctAnswers;

  /// The feedback displayed for all answers.
  ///
  /// This is commonly used for short answer questions when a quiz owner wants
  /// to quickly give respondents some sense of whether they answered the
  /// question correctly before they've had a chance to officially grade the
  /// response. General feedback cannot be set for automatically graded multiple
  /// choice questions.
  Feedback? generalFeedback;

  /// The maximum number of points a respondent can automatically get for a
  /// correct answer.
  ///
  /// This must not be negative.
  ///
  /// Required.
  core.int? pointValue;

  /// The feedback displayed for correct responses.
  ///
  /// This feedback can only be set for multiple choice questions that have
  /// correct answers provided.
  Feedback? whenRight;

  /// The feedback displayed for incorrect responses.
  ///
  /// This feedback can only be set for multiple choice questions that have
  /// correct answers provided.
  Feedback? whenWrong;

  Grading({
    this.correctAnswers,
    this.generalFeedback,
    this.pointValue,
    this.whenRight,
    this.whenWrong,
  });

  Grading.fromJson(core.Map json_)
      : this(
          correctAnswers: json_.containsKey('correctAnswers')
              ? CorrectAnswers.fromJson(json_['correctAnswers']
                  as core.Map<core.String, core.dynamic>)
              : null,
          generalFeedback: json_.containsKey('generalFeedback')
              ? Feedback.fromJson(json_['generalFeedback']
                  as core.Map<core.String, core.dynamic>)
              : null,
          pointValue: json_.containsKey('pointValue')
              ? json_['pointValue'] as core.int
              : null,
          whenRight: json_.containsKey('whenRight')
              ? Feedback.fromJson(
                  json_['whenRight'] as core.Map<core.String, core.dynamic>)
              : null,
          whenWrong: json_.containsKey('whenWrong')
              ? Feedback.fromJson(
                  json_['whenWrong'] as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (correctAnswers != null) 'correctAnswers': correctAnswers!,
        if (generalFeedback != null) 'generalFeedback': generalFeedback!,
        if (pointValue != null) 'pointValue': pointValue!,
        if (whenRight != null) 'whenRight': whenRight!,
        if (whenWrong != null) 'whenWrong': whenWrong!,
      };
}

/// A grid of choices (radio or check boxes) with each row constituting a
/// separate question.
///
/// Each row has the same choices, which are shown as the columns.
class Grid {
  /// The choices shared by each question in the grid.
  ///
  /// In other words, the values of the columns. Only `CHECK_BOX` and `RADIO`
  /// choices are allowed.
  ///
  /// Required.
  ChoiceQuestion? columns;

  /// If `true`, the questions are randomly ordered.
  ///
  /// In other words, the rows appear in a different order for every respondent.
  core.bool? shuffleQuestions;

  Grid({
    this.columns,
    this.shuffleQuestions,
  });

  Grid.fromJson(core.Map json_)
      : this(
          columns: json_.containsKey('columns')
              ? ChoiceQuestion.fromJson(
                  json_['columns'] as core.Map<core.String, core.dynamic>)
              : null,
          shuffleQuestions: json_.containsKey('shuffleQuestions')
              ? json_['shuffleQuestions'] as core.bool
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (columns != null) 'columns': columns!,
        if (shuffleQuestions != null) 'shuffleQuestions': shuffleQuestions!,
      };
}

/// Data representing an image.
class Image {
  /// A description of the image that is shown on hover and read by
  /// screenreaders.
  core.String? altText;

  /// A URI from which you can download the image; this is valid only for a
  /// limited time.
  ///
  /// Output only.
  core.String? contentUri;

  /// Properties of an image.
  MediaProperties? properties;

  /// Input only.
  ///
  /// The source URI is the URI used to insert the image. The source URI can be
  /// empty when fetched.
  core.String? sourceUri;

  Image({
    this.altText,
    this.contentUri,
    this.properties,
    this.sourceUri,
  });

  Image.fromJson(core.Map json_)
      : this(
          altText: json_.containsKey('altText')
              ? json_['altText'] as core.String
              : null,
          contentUri: json_.containsKey('contentUri')
              ? json_['contentUri'] as core.String
              : null,
          properties: json_.containsKey('properties')
              ? MediaProperties.fromJson(
                  json_['properties'] as core.Map<core.String, core.dynamic>)
              : null,
          sourceUri: json_.containsKey('sourceUri')
              ? json_['sourceUri'] as core.String
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (altText != null) 'altText': altText!,
        if (contentUri != null) 'contentUri': contentUri!,
        if (properties != null) 'properties': properties!,
        if (sourceUri != null) 'sourceUri': sourceUri!,
      };
}

/// An item containing an image.
class ImageItem {
  /// The image displayed in the item.
  ///
  /// Required.
  Image? image;

  ImageItem({
    this.image,
  });

  ImageItem.fromJson(core.Map json_)
      : this(
          image: json_.containsKey('image')
              ? Image.fromJson(
                  json_['image'] as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (image != null) 'image': image!,
      };
}

/// The general information for a form.
class Info {
  /// The description of the form.
  core.String? description;

  /// The title of the document which is visible in Drive.
  ///
  /// If `Info.title` is empty, `document_title` may appear in its place in the
  /// Google Forms UI and be visible to responders. `document_title` can be set
  /// on create, but cannot be modified by a batchUpdate request. Please use the
  /// [Google Drive API](https://developers.google.com/drive/api/v3/reference/files/update)
  /// if you need to programmatically update `document_title`.
  ///
  /// Output only.
  core.String? documentTitle;

  /// The title of the form which is visible to responders.
  ///
  /// Required.
  core.String? title;

  Info({
    this.description,
    this.documentTitle,
    this.title,
  });

  Info.fromJson(core.Map json_)
      : this(
          description: json_.containsKey('description')
              ? json_['description'] as core.String
              : null,
          documentTitle: json_.containsKey('documentTitle')
              ? json_['documentTitle'] as core.String
              : null,
          title:
              json_.containsKey('title') ? json_['title'] as core.String : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (description != null) 'description': description!,
        if (documentTitle != null) 'documentTitle': documentTitle!,
        if (title != null) 'title': title!,
      };
}

/// A single item of the form.
///
/// `kind` defines which kind of item it is.
class Item {
  /// The description of the item.
  core.String? description;

  /// Displays an image on the page.
  ImageItem? imageItem;

  /// The item ID.
  ///
  /// On creation, it can be provided but the ID must not be already used in the
  /// form. If not provided, a new ID is assigned.
  core.String? itemId;

  /// Starts a new page with a title.
  PageBreakItem? pageBreakItem;

  /// Poses one or more questions to the user with a single major prompt.
  QuestionGroupItem? questionGroupItem;

  /// Poses a question to the user.
  QuestionItem? questionItem;

  /// Displays a title and description on the page.
  TextItem? textItem;

  /// The title of the item.
  core.String? title;

  /// Displays a video on the page.
  VideoItem? videoItem;

  Item({
    this.description,
    this.imageItem,
    this.itemId,
    this.pageBreakItem,
    this.questionGroupItem,
    this.questionItem,
    this.textItem,
    this.title,
    this.videoItem,
  });

  Item.fromJson(core.Map json_)
      : this(
          description: json_.containsKey('description')
              ? json_['description'] as core.String
              : null,
          imageItem: json_.containsKey('imageItem')
              ? ImageItem.fromJson(
                  json_['imageItem'] as core.Map<core.String, core.dynamic>)
              : null,
          itemId: json_.containsKey('itemId')
              ? json_['itemId'] as core.String
              : null,
          pageBreakItem: json_.containsKey('pageBreakItem')
              ? PageBreakItem.fromJson(
                  json_['pageBreakItem'] as core.Map<core.String, core.dynamic>)
              : null,
          questionGroupItem: json_.containsKey('questionGroupItem')
              ? QuestionGroupItem.fromJson(json_['questionGroupItem']
                  as core.Map<core.String, core.dynamic>)
              : null,
          questionItem: json_.containsKey('questionItem')
              ? QuestionItem.fromJson(
                  json_['questionItem'] as core.Map<core.String, core.dynamic>)
              : null,
          textItem: json_.containsKey('textItem')
              ? TextItem.fromJson(
                  json_['textItem'] as core.Map<core.String, core.dynamic>)
              : null,
          title:
              json_.containsKey('title') ? json_['title'] as core.String : null,
          videoItem: json_.containsKey('videoItem')
              ? VideoItem.fromJson(
                  json_['videoItem'] as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (description != null) 'description': description!,
        if (imageItem != null) 'imageItem': imageItem!,
        if (itemId != null) 'itemId': itemId!,
        if (pageBreakItem != null) 'pageBreakItem': pageBreakItem!,
        if (questionGroupItem != null) 'questionGroupItem': questionGroupItem!,
        if (questionItem != null) 'questionItem': questionItem!,
        if (textItem != null) 'textItem': textItem!,
        if (title != null) 'title': title!,
        if (videoItem != null) 'videoItem': videoItem!,
      };
}

/// Response to a ListFormResponsesRequest.
class ListFormResponsesResponse {
  /// If set, there are more responses.
  ///
  /// To get the next page of responses, provide this as `page_token` in a
  /// future request.
  core.String? nextPageToken;

  /// The returned form responses.
  ///
  /// Note: The `formId` field is not returned in the `FormResponse` object for
  /// list requests.
  core.List<FormResponse>? responses;

  ListFormResponsesResponse({
    this.nextPageToken,
    this.responses,
  });

  ListFormResponsesResponse.fromJson(core.Map json_)
      : this(
          nextPageToken: json_.containsKey('nextPageToken')
              ? json_['nextPageToken'] as core.String
              : null,
          responses: json_.containsKey('responses')
              ? (json_['responses'] as core.List)
                  .map((value) => FormResponse.fromJson(
                      value as core.Map<core.String, core.dynamic>))
                  .toList()
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (nextPageToken != null) 'nextPageToken': nextPageToken!,
        if (responses != null) 'responses': responses!,
      };
}

/// The response of a ListWatchesRequest.
class ListWatchesResponse {
  /// The returned watches.
  core.List<Watch>? watches;

  ListWatchesResponse({
    this.watches,
  });

  ListWatchesResponse.fromJson(core.Map json_)
      : this(
          watches: json_.containsKey('watches')
              ? (json_['watches'] as core.List)
                  .map((value) => Watch.fromJson(
                      value as core.Map<core.String, core.dynamic>))
                  .toList()
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (watches != null) 'watches': watches!,
      };
}

/// A specific location in a form.
class Location {
  /// The index of an item in the form.
  ///
  /// This must be in the range \[0..*N*), where *N* is the number of items in
  /// the form.
  core.int? index;

  Location({
    this.index,
  });

  Location.fromJson(core.Map json_)
      : this(
          index: json_.containsKey('index') ? json_['index'] as core.int : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (index != null) 'index': index!,
      };
}

/// Properties of the media.
class MediaProperties {
  /// Position of the media.
  /// Possible string values are:
  /// - "ALIGNMENT_UNSPECIFIED" : Default value. Unused.
  /// - "LEFT" : Left align.
  /// - "RIGHT" : Right align.
  /// - "CENTER" : Center.
  core.String? alignment;

  /// The width of the media in pixels.
  ///
  /// When the media is displayed, it is scaled to the smaller of this value or
  /// the width of the displayed form. The original aspect ratio of the media is
  /// preserved. If a width is not specified when the media is added to the
  /// form, it is set to the width of the media source. Width must be between 0
  /// and 740, inclusive. Setting width to 0 or unspecified is only permitted
  /// when updating the media source.
  core.int? width;

  MediaProperties({
    this.alignment,
    this.width,
  });

  MediaProperties.fromJson(core.Map json_)
      : this(
          alignment: json_.containsKey('alignment')
              ? json_['alignment'] as core.String
              : null,
          width: json_.containsKey('width') ? json_['width'] as core.int : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (alignment != null) 'alignment': alignment!,
        if (width != null) 'width': width!,
      };
}

/// Move an item in a form.
class MoveItemRequest {
  /// The new location for the item.
  ///
  /// Required.
  Location? newLocation;

  /// The location of the item to move.
  ///
  /// Required.
  Location? originalLocation;

  MoveItemRequest({
    this.newLocation,
    this.originalLocation,
  });

  MoveItemRequest.fromJson(core.Map json_)
      : this(
          newLocation: json_.containsKey('newLocation')
              ? Location.fromJson(
                  json_['newLocation'] as core.Map<core.String, core.dynamic>)
              : null,
          originalLocation: json_.containsKey('originalLocation')
              ? Location.fromJson(json_['originalLocation']
                  as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (newLocation != null) 'newLocation': newLocation!,
        if (originalLocation != null) 'originalLocation': originalLocation!,
      };
}

/// An option for a Choice question.
class Option {
  /// Section navigation type.
  /// Possible string values are:
  /// - "GO_TO_ACTION_UNSPECIFIED" : Default value. Unused.
  /// - "NEXT_SECTION" : Go to the next section.
  /// - "RESTART_FORM" : Go back to the beginning of the form.
  /// - "SUBMIT_FORM" : Submit form immediately.
  core.String? goToAction;

  /// Item ID of section header to go to.
  core.String? goToSectionId;

  /// Display image as an option.
  Image? image;

  /// Whether the option is "other".
  ///
  /// Currently only applies to `RADIO` and `CHECKBOX` choice types, but is not
  /// allowed in a QuestionGroupItem.
  core.bool? isOther;

  /// The choice as presented to the user.
  ///
  /// Required.
  core.String? value;

  Option({
    this.goToAction,
    this.goToSectionId,
    this.image,
    this.isOther,
    this.value,
  });

  Option.fromJson(core.Map json_)
      : this(
          goToAction: json_.containsKey('goToAction')
              ? json_['goToAction'] as core.String
              : null,
          goToSectionId: json_.containsKey('goToSectionId')
              ? json_['goToSectionId'] as core.String
              : null,
          image: json_.containsKey('image')
              ? Image.fromJson(
                  json_['image'] as core.Map<core.String, core.dynamic>)
              : null,
          isOther: json_.containsKey('isOther')
              ? json_['isOther'] as core.bool
              : null,
          value:
              json_.containsKey('value') ? json_['value'] as core.String : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (goToAction != null) 'goToAction': goToAction!,
        if (goToSectionId != null) 'goToSectionId': goToSectionId!,
        if (image != null) 'image': image!,
        if (isOther != null) 'isOther': isOther!,
        if (value != null) 'value': value!,
      };
}

/// A page break.
///
/// The title and description of this item are shown at the top of the new page.
typedef PageBreakItem = $Empty;

/// Any question.
///
/// The specific type of question is known by its `kind`.
class Question {
  /// A respondent can choose from a pre-defined set of options.
  ChoiceQuestion? choiceQuestion;

  /// A respondent can enter a date.
  DateQuestion? dateQuestion;

  /// A respondent can upload one or more files.
  FileUploadQuestion? fileUploadQuestion;

  /// Grading setup for the question.
  Grading? grading;

  /// Read only.
  ///
  /// The question ID. On creation, it can be provided but the ID must not be
  /// already used in the form. If not provided, a new ID is assigned.
  core.String? questionId;

  /// Whether the question must be answered in order for a respondent to submit
  /// their response.
  core.bool? required;

  /// A row of a QuestionGroupItem.
  RowQuestion? rowQuestion;

  /// A respondent can choose a number from a range.
  ScaleQuestion? scaleQuestion;

  /// A respondent can enter a free text response.
  TextQuestion? textQuestion;

  /// A respondent can enter a time.
  TimeQuestion? timeQuestion;

  Question({
    this.choiceQuestion,
    this.dateQuestion,
    this.fileUploadQuestion,
    this.grading,
    this.questionId,
    this.required,
    this.rowQuestion,
    this.scaleQuestion,
    this.textQuestion,
    this.timeQuestion,
  });

  Question.fromJson(core.Map json_)
      : this(
          choiceQuestion: json_.containsKey('choiceQuestion')
              ? ChoiceQuestion.fromJson(json_['choiceQuestion']
                  as core.Map<core.String, core.dynamic>)
              : null,
          dateQuestion: json_.containsKey('dateQuestion')
              ? DateQuestion.fromJson(
                  json_['dateQuestion'] as core.Map<core.String, core.dynamic>)
              : null,
          fileUploadQuestion: json_.containsKey('fileUploadQuestion')
              ? FileUploadQuestion.fromJson(json_['fileUploadQuestion']
                  as core.Map<core.String, core.dynamic>)
              : null,
          grading: json_.containsKey('grading')
              ? Grading.fromJson(
                  json_['grading'] as core.Map<core.String, core.dynamic>)
              : null,
          questionId: json_.containsKey('questionId')
              ? json_['questionId'] as core.String
              : null,
          required: json_.containsKey('required')
              ? json_['required'] as core.bool
              : null,
          rowQuestion: json_.containsKey('rowQuestion')
              ? RowQuestion.fromJson(
                  json_['rowQuestion'] as core.Map<core.String, core.dynamic>)
              : null,
          scaleQuestion: json_.containsKey('scaleQuestion')
              ? ScaleQuestion.fromJson(
                  json_['scaleQuestion'] as core.Map<core.String, core.dynamic>)
              : null,
          textQuestion: json_.containsKey('textQuestion')
              ? TextQuestion.fromJson(
                  json_['textQuestion'] as core.Map<core.String, core.dynamic>)
              : null,
          timeQuestion: json_.containsKey('timeQuestion')
              ? TimeQuestion.fromJson(
                  json_['timeQuestion'] as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (choiceQuestion != null) 'choiceQuestion': choiceQuestion!,
        if (dateQuestion != null) 'dateQuestion': dateQuestion!,
        if (fileUploadQuestion != null)
          'fileUploadQuestion': fileUploadQuestion!,
        if (grading != null) 'grading': grading!,
        if (questionId != null) 'questionId': questionId!,
        if (required != null) 'required': required!,
        if (rowQuestion != null) 'rowQuestion': rowQuestion!,
        if (scaleQuestion != null) 'scaleQuestion': scaleQuestion!,
        if (textQuestion != null) 'textQuestion': textQuestion!,
        if (timeQuestion != null) 'timeQuestion': timeQuestion!,
      };
}

/// Defines a question that comprises multiple questions grouped together.
class QuestionGroupItem {
  /// The question group is a grid with rows of multiple choice questions that
  /// share the same options.
  ///
  /// When `grid` is set, all questions in the group must be of kind `row`.
  Grid? grid;

  /// The image displayed within the question group above the specific
  /// questions.
  Image? image;

  /// A list of questions that belong in this question group.
  ///
  /// A question must only belong to one group. The `kind` of the group may
  /// affect what types of questions are allowed.
  ///
  /// Required.
  core.List<Question>? questions;

  QuestionGroupItem({
    this.grid,
    this.image,
    this.questions,
  });

  QuestionGroupItem.fromJson(core.Map json_)
      : this(
          grid: json_.containsKey('grid')
              ? Grid.fromJson(
                  json_['grid'] as core.Map<core.String, core.dynamic>)
              : null,
          image: json_.containsKey('image')
              ? Image.fromJson(
                  json_['image'] as core.Map<core.String, core.dynamic>)
              : null,
          questions: json_.containsKey('questions')
              ? (json_['questions'] as core.List)
                  .map((value) => Question.fromJson(
                      value as core.Map<core.String, core.dynamic>))
                  .toList()
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (grid != null) 'grid': grid!,
        if (image != null) 'image': image!,
        if (questions != null) 'questions': questions!,
      };
}

/// A form item containing a single question.
class QuestionItem {
  /// The image displayed within the question.
  Image? image;

  /// The displayed question.
  ///
  /// Required.
  Question? question;

  QuestionItem({
    this.image,
    this.question,
  });

  QuestionItem.fromJson(core.Map json_)
      : this(
          image: json_.containsKey('image')
              ? Image.fromJson(
                  json_['image'] as core.Map<core.String, core.dynamic>)
              : null,
          question: json_.containsKey('question')
              ? Question.fromJson(
                  json_['question'] as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (image != null) 'image': image!,
        if (question != null) 'question': question!,
      };
}

/// Settings related to quiz forms and grading.
///
/// These must be updated with the UpdateSettingsRequest.
class QuizSettings {
  /// Whether this form is a quiz or not.
  ///
  /// When true, responses are graded based on question Grading. Upon setting to
  /// false, all question Grading is deleted.
  core.bool? isQuiz;

  QuizSettings({
    this.isQuiz,
  });

  QuizSettings.fromJson(core.Map json_)
      : this(
          isQuiz:
              json_.containsKey('isQuiz') ? json_['isQuiz'] as core.bool : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (isQuiz != null) 'isQuiz': isQuiz!,
      };
}

/// Renew an existing Watch for seven days.
typedef RenewWatchRequest = $Empty;

/// The kinds of update requests that can be made.
class Request {
  /// Create a new item.
  CreateItemRequest? createItem;

  /// Delete an item.
  DeleteItemRequest? deleteItem;

  /// Move an item to a specified location.
  MoveItemRequest? moveItem;

  /// Update Form's Info.
  UpdateFormInfoRequest? updateFormInfo;

  /// Update an item.
  UpdateItemRequest? updateItem;

  /// Updates the Form's settings.
  UpdateSettingsRequest? updateSettings;

  Request({
    this.createItem,
    this.deleteItem,
    this.moveItem,
    this.updateFormInfo,
    this.updateItem,
    this.updateSettings,
  });

  Request.fromJson(core.Map json_)
      : this(
          createItem: json_.containsKey('createItem')
              ? CreateItemRequest.fromJson(
                  json_['createItem'] as core.Map<core.String, core.dynamic>)
              : null,
          deleteItem: json_.containsKey('deleteItem')
              ? DeleteItemRequest.fromJson(
                  json_['deleteItem'] as core.Map<core.String, core.dynamic>)
              : null,
          moveItem: json_.containsKey('moveItem')
              ? MoveItemRequest.fromJson(
                  json_['moveItem'] as core.Map<core.String, core.dynamic>)
              : null,
          updateFormInfo: json_.containsKey('updateFormInfo')
              ? UpdateFormInfoRequest.fromJson(json_['updateFormInfo']
                  as core.Map<core.String, core.dynamic>)
              : null,
          updateItem: json_.containsKey('updateItem')
              ? UpdateItemRequest.fromJson(
                  json_['updateItem'] as core.Map<core.String, core.dynamic>)
              : null,
          updateSettings: json_.containsKey('updateSettings')
              ? UpdateSettingsRequest.fromJson(json_['updateSettings']
                  as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (createItem != null) 'createItem': createItem!,
        if (deleteItem != null) 'deleteItem': deleteItem!,
        if (moveItem != null) 'moveItem': moveItem!,
        if (updateFormInfo != null) 'updateFormInfo': updateFormInfo!,
        if (updateItem != null) 'updateItem': updateItem!,
        if (updateSettings != null) 'updateSettings': updateSettings!,
      };
}

/// A single response from an update.
class Response {
  /// The result of creating an item.
  CreateItemResponse? createItem;

  Response({
    this.createItem,
  });

  Response.fromJson(core.Map json_)
      : this(
          createItem: json_.containsKey('createItem')
              ? CreateItemResponse.fromJson(
                  json_['createItem'] as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (createItem != null) 'createItem': createItem!,
      };
}

/// Configuration for a question that is part of a question group.
class RowQuestion {
  /// The title for the single row in the QuestionGroupItem.
  ///
  /// Required.
  core.String? title;

  RowQuestion({
    this.title,
  });

  RowQuestion.fromJson(core.Map json_)
      : this(
          title:
              json_.containsKey('title') ? json_['title'] as core.String : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (title != null) 'title': title!,
      };
}

/// A scale question.
///
/// The user has a range of numeric values to choose from.
class ScaleQuestion {
  /// The highest possible value for the scale.
  ///
  /// Required.
  core.int? high;

  /// The label to display describing the highest point on the scale.
  core.String? highLabel;

  /// The lowest possible value for the scale.
  ///
  /// Required.
  core.int? low;

  /// The label to display describing the lowest point on the scale.
  core.String? lowLabel;

  ScaleQuestion({
    this.high,
    this.highLabel,
    this.low,
    this.lowLabel,
  });

  ScaleQuestion.fromJson(core.Map json_)
      : this(
          high: json_.containsKey('high') ? json_['high'] as core.int : null,
          highLabel: json_.containsKey('highLabel')
              ? json_['highLabel'] as core.String
              : null,
          low: json_.containsKey('low') ? json_['low'] as core.int : null,
          lowLabel: json_.containsKey('lowLabel')
              ? json_['lowLabel'] as core.String
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (high != null) 'high': high!,
        if (highLabel != null) 'highLabel': highLabel!,
        if (low != null) 'low': low!,
        if (lowLabel != null) 'lowLabel': lowLabel!,
      };
}

/// An answer to a question represented as text.
class TextAnswer {
  /// The answer value.
  ///
  /// Formatting used for different kinds of question: * ChoiceQuestion *
  /// `RADIO` or `DROP_DOWN`: A single string corresponding to the option that
  /// was selected. * `CHECKBOX`: Multiple strings corresponding to each option
  /// that was selected. * TextQuestion: The text that the user entered. *
  /// ScaleQuestion: A string containing the number that was selected. *
  /// DateQuestion * Without time or year: MM-DD e.g. "05-19" * With year:
  /// YYYY-MM-DD e.g. "1986-05-19" * With time: MM-DD HH:MM e.g. "05-19 14:51" *
  /// With year and time: YYYY-MM-DD HH:MM e.g. "1986-05-19 14:51" *
  /// TimeQuestion: String with time or duration in HH:MM format e.g. "14:51" *
  /// RowQuestion within QuestionGroupItem: The answer for each row of a
  /// QuestionGroupItem is represented as a separate Answer. Each will contain
  /// one string for `RADIO`-type choices or multiple strings for `CHECKBOX`
  /// choices.
  ///
  /// Output only.
  core.String? value;

  TextAnswer({
    this.value,
  });

  TextAnswer.fromJson(core.Map json_)
      : this(
          value:
              json_.containsKey('value') ? json_['value'] as core.String : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (value != null) 'value': value!,
      };
}

/// A question's answers as text.
class TextAnswers {
  /// Answers to a question.
  ///
  /// For multiple-value ChoiceQuestions, each answer is a separate value.
  ///
  /// Output only.
  core.List<TextAnswer>? answers;

  TextAnswers({
    this.answers,
  });

  TextAnswers.fromJson(core.Map json_)
      : this(
          answers: json_.containsKey('answers')
              ? (json_['answers'] as core.List)
                  .map((value) => TextAnswer.fromJson(
                      value as core.Map<core.String, core.dynamic>))
                  .toList()
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (answers != null) 'answers': answers!,
      };
}

/// A text item.
typedef TextItem = $Empty;

/// Link for text.
class TextLink {
  /// Display text for the URI.
  ///
  /// Required.
  core.String? displayText;

  /// The URI.
  ///
  /// Required.
  core.String? uri;

  TextLink({
    this.displayText,
    this.uri,
  });

  TextLink.fromJson(core.Map json_)
      : this(
          displayText: json_.containsKey('displayText')
              ? json_['displayText'] as core.String
              : null,
          uri: json_.containsKey('uri') ? json_['uri'] as core.String : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (displayText != null) 'displayText': displayText!,
        if (uri != null) 'uri': uri!,
      };
}

/// A text-based question.
class TextQuestion {
  /// Whether the question is a paragraph question or not.
  ///
  /// If not, the question is a short text question.
  core.bool? paragraph;

  TextQuestion({
    this.paragraph,
  });

  TextQuestion.fromJson(core.Map json_)
      : this(
          paragraph: json_.containsKey('paragraph')
              ? json_['paragraph'] as core.bool
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (paragraph != null) 'paragraph': paragraph!,
      };
}

/// A time question.
class TimeQuestion {
  /// `true` if the question is about an elapsed time.
  ///
  /// Otherwise it is about a time of day.
  core.bool? duration;

  TimeQuestion({
    this.duration,
  });

  TimeQuestion.fromJson(core.Map json_)
      : this(
          duration: json_.containsKey('duration')
              ? json_['duration'] as core.bool
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (duration != null) 'duration': duration!,
      };
}

/// Update Form's Info.
class UpdateFormInfoRequest {
  /// The info to update.
  Info? info;

  /// Only values named in this mask are changed.
  ///
  /// At least one field must be specified. The root `info` is implied and
  /// should not be specified. A single `"*"` can be used as short-hand for
  /// updating every field.
  ///
  /// Required.
  core.String? updateMask;

  UpdateFormInfoRequest({
    this.info,
    this.updateMask,
  });

  UpdateFormInfoRequest.fromJson(core.Map json_)
      : this(
          info: json_.containsKey('info')
              ? Info.fromJson(
                  json_['info'] as core.Map<core.String, core.dynamic>)
              : null,
          updateMask: json_.containsKey('updateMask')
              ? json_['updateMask'] as core.String
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (info != null) 'info': info!,
        if (updateMask != null) 'updateMask': updateMask!,
      };
}

/// Update an item in a form.
class UpdateItemRequest {
  /// New values for the item.
  ///
  /// Note that item and question IDs are used if they are provided (and are in
  /// the field mask). If an ID is blank (and in the field mask) a new ID is
  /// generated. This means you can modify an item by getting the form via
  /// forms.get, modifying your local copy of that item to be how you want it,
  /// and using UpdateItemRequest to write it back, with the IDs being the same
  /// (or not in the field mask).
  ///
  /// Required.
  Item? item;

  /// The location identifying the item to update.
  ///
  /// Required.
  Location? location;

  /// Only values named in this mask are changed.
  ///
  /// Required.
  core.String? updateMask;

  UpdateItemRequest({
    this.item,
    this.location,
    this.updateMask,
  });

  UpdateItemRequest.fromJson(core.Map json_)
      : this(
          item: json_.containsKey('item')
              ? Item.fromJson(
                  json_['item'] as core.Map<core.String, core.dynamic>)
              : null,
          location: json_.containsKey('location')
              ? Location.fromJson(
                  json_['location'] as core.Map<core.String, core.dynamic>)
              : null,
          updateMask: json_.containsKey('updateMask')
              ? json_['updateMask'] as core.String
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (item != null) 'item': item!,
        if (location != null) 'location': location!,
        if (updateMask != null) 'updateMask': updateMask!,
      };
}

/// Update Form's FormSettings.
class UpdateSettingsRequest {
  /// The settings to update with.
  ///
  /// Required.
  FormSettings? settings;

  /// Only values named in this mask are changed.
  ///
  /// At least one field must be specified. The root `settings` is implied and
  /// should not be specified. A single `"*"` can be used as short-hand for
  /// updating every field.
  ///
  /// Required.
  core.String? updateMask;

  UpdateSettingsRequest({
    this.settings,
    this.updateMask,
  });

  UpdateSettingsRequest.fromJson(core.Map json_)
      : this(
          settings: json_.containsKey('settings')
              ? FormSettings.fromJson(
                  json_['settings'] as core.Map<core.String, core.dynamic>)
              : null,
          updateMask: json_.containsKey('updateMask')
              ? json_['updateMask'] as core.String
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (settings != null) 'settings': settings!,
        if (updateMask != null) 'updateMask': updateMask!,
      };
}

/// Data representing a video.
class Video {
  /// Properties of a video.
  MediaProperties? properties;

  /// A YouTube URI.
  ///
  /// Required.
  core.String? youtubeUri;

  Video({
    this.properties,
    this.youtubeUri,
  });

  Video.fromJson(core.Map json_)
      : this(
          properties: json_.containsKey('properties')
              ? MediaProperties.fromJson(
                  json_['properties'] as core.Map<core.String, core.dynamic>)
              : null,
          youtubeUri: json_.containsKey('youtubeUri')
              ? json_['youtubeUri'] as core.String
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (properties != null) 'properties': properties!,
        if (youtubeUri != null) 'youtubeUri': youtubeUri!,
      };
}

/// An item containing a video.
class VideoItem {
  /// The text displayed below the video.
  core.String? caption;

  /// The video displayed in the item.
  ///
  /// Required.
  Video? video;

  VideoItem({
    this.caption,
    this.video,
  });

  VideoItem.fromJson(core.Map json_)
      : this(
          caption: json_.containsKey('caption')
              ? json_['caption'] as core.String
              : null,
          video: json_.containsKey('video')
              ? Video.fromJson(
                  json_['video'] as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (caption != null) 'caption': caption!,
        if (video != null) 'video': video!,
      };
}

/// Link to a video.
class VideoLink {
  /// The display text for the link.
  ///
  /// Required.
  core.String? displayText;

  /// The URI of a YouTube video.
  core.String? youtubeUri;

  VideoLink({
    this.displayText,
    this.youtubeUri,
  });

  VideoLink.fromJson(core.Map json_)
      : this(
          displayText: json_.containsKey('displayText')
              ? json_['displayText'] as core.String
              : null,
          youtubeUri: json_.containsKey('youtubeUri')
              ? json_['youtubeUri'] as core.String
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (displayText != null) 'displayText': displayText!,
        if (youtubeUri != null) 'youtubeUri': youtubeUri!,
      };
}

/// A watch for events for a form.
///
/// When the designated event happens, a notification will be published to the
/// specified target. The notification's attributes will include a `formId` key
/// that has the ID of the watched form and an `eventType` key that has the
/// string of the type. Messages are sent with at-least-once delivery and are
/// only dropped in extraordinary circumstances. Typically all notifications
/// should be reliably delivered within a few seconds; however, in some
/// situations notifications may be delayed. A watch expires seven days after it
/// is created unless it is renewed with watches.renew
class Watch {
  /// Timestamp of when this was created.
  ///
  /// Output only.
  core.String? createTime;

  /// The most recent error type for an attempted delivery.
  ///
  /// To begin watching the form again a call can be made to watches.renew which
  /// also clears this error information.
  ///
  /// Output only.
  /// Possible string values are:
  /// - "ERROR_TYPE_UNSPECIFIED" : Unspecified error type.
  /// - "PROJECT_NOT_AUTHORIZED" : The cloud project does not have access to the
  /// form being watched. This occurs if the user has revoked the authorization
  /// for your project to access their form(s). Watches with this error will not
  /// be retried. To attempt to begin watching the form again a call can be made
  /// to watches.renew
  /// - "NO_USER_ACCESS" : The user that granted access no longer has access to
  /// the form being watched. Watches with this error will not be retried. To
  /// attempt to begin watching the form again a call can be made to
  /// watches.renew
  /// - "OTHER_ERRORS" : Another type of error has occurred. Whether
  /// notifications will continue depends on the watch state.
  core.String? errorType;

  /// Which event type to watch for.
  ///
  /// Required.
  /// Possible string values are:
  /// - "EVENT_TYPE_UNSPECIFIED" : Unspecified event type. This value should not
  /// be used.
  /// - "SCHEMA" : The schema event type. A watch with this event type will be
  /// notified about changes to form content and settings.
  /// - "RESPONSES" : The responses event type. A watch with this event type
  /// will be notified when form responses are submitted.
  core.String? eventType;

  /// Timestamp for when this will expire.
  ///
  /// Each watches.renew call resets this to seven days in the future.
  ///
  /// Output only.
  core.String? expireTime;

  /// The ID of this watch.
  ///
  /// See notes on CreateWatchRequest.watch_id.
  ///
  /// Output only.
  core.String? id;

  /// The current state of the watch.
  ///
  /// Additional details about suspended watches can be found by checking the
  /// `error_type`.
  ///
  /// Output only.
  /// Possible string values are:
  /// - "STATE_UNSPECIFIED" : Unspecified state.
  /// - "ACTIVE" : Watch is active.
  /// - "SUSPENDED" : The watch is suspended due to an error that may be
  /// resolved. The watch will continue to exist until it expires. To attempt to
  /// reactivate the watch a call can be made to watches.renew
  core.String? state;

  /// Where to send the notification.
  ///
  /// Required.
  WatchTarget? target;

  Watch({
    this.createTime,
    this.errorType,
    this.eventType,
    this.expireTime,
    this.id,
    this.state,
    this.target,
  });

  Watch.fromJson(core.Map json_)
      : this(
          createTime: json_.containsKey('createTime')
              ? json_['createTime'] as core.String
              : null,
          errorType: json_.containsKey('errorType')
              ? json_['errorType'] as core.String
              : null,
          eventType: json_.containsKey('eventType')
              ? json_['eventType'] as core.String
              : null,
          expireTime: json_.containsKey('expireTime')
              ? json_['expireTime'] as core.String
              : null,
          id: json_.containsKey('id') ? json_['id'] as core.String : null,
          state:
              json_.containsKey('state') ? json_['state'] as core.String : null,
          target: json_.containsKey('target')
              ? WatchTarget.fromJson(
                  json_['target'] as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (createTime != null) 'createTime': createTime!,
        if (errorType != null) 'errorType': errorType!,
        if (eventType != null) 'eventType': eventType!,
        if (expireTime != null) 'expireTime': expireTime!,
        if (id != null) 'id': id!,
        if (state != null) 'state': state!,
        if (target != null) 'target': target!,
      };
}

/// The target for notification delivery.
class WatchTarget {
  /// A Pub/Sub topic.
  ///
  /// To receive notifications, the topic must grant publish privileges to the
  /// Forms service account
  /// `serviceAccount:forms-notifications@system.gserviceaccount.com`. Only the
  /// project that owns a topic may create a watch with it. Pub/Sub delivery
  /// guarantees should be considered.
  CloudPubsubTopic? topic;

  WatchTarget({
    this.topic,
  });

  WatchTarget.fromJson(core.Map json_)
      : this(
          topic: json_.containsKey('topic')
              ? CloudPubsubTopic.fromJson(
                  json_['topic'] as core.Map<core.String, core.dynamic>)
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (topic != null) 'topic': topic!,
      };
}

/// Provides control over how write requests are executed.
class WriteControl {
  /// The revision ID of the form that the write request is applied to.
  ///
  /// If this is not the latest revision of the form, the request is not
  /// processed and returns a 400 bad request error.
  core.String? requiredRevisionId;

  /// The target revision ID of the form that the write request is applied to.
  ///
  /// If changes have occurred after this revision, the changes in this update
  /// request are transformed against those changes. This results in a new
  /// revision of the form that incorporates both the changes in the request and
  /// the intervening changes, with the server resolving conflicting changes.
  /// The target revision ID may only be used to write to recent versions of a
  /// form. If the target revision is too far behind the latest revision, the
  /// request is not processed and returns a 400 (Bad Request Error). The
  /// request may be retried after reading the latest version of the form. In
  /// most cases a target revision ID remains valid for several minutes after it
  /// is read, but for frequently-edited forms this window may be shorter.
  core.String? targetRevisionId;

  WriteControl({
    this.requiredRevisionId,
    this.targetRevisionId,
  });

  WriteControl.fromJson(core.Map json_)
      : this(
          requiredRevisionId: json_.containsKey('requiredRevisionId')
              ? json_['requiredRevisionId'] as core.String
              : null,
          targetRevisionId: json_.containsKey('targetRevisionId')
              ? json_['targetRevisionId'] as core.String
              : null,
        );

  core.Map<core.String, core.dynamic> toJson() => {
        if (requiredRevisionId != null)
          'requiredRevisionId': requiredRevisionId!,
        if (targetRevisionId != null) 'targetRevisionId': targetRevisionId!,
      };
}
