text:
# This file is auto-generated by AWSMetadata.jl
using AWS
using AWS.AWSServices: nimble
using AWS.Compat
using AWS.UUIDs

"""
    accept_eulas(studio_id)
    accept_eulas(studio_id, params::Dict{String,<:Any})

Accept EULAs.

# Arguments
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
- `"eulaIds"`: The EULA ID.
"""
accept_eulas(studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/studios/$(studioId)/eula-acceptances", Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
accept_eulas(studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/studios/$(studioId)/eula-acceptances", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    create_launch_profile(ec2_subnet_ids, launch_profile_protocol_versions, name, stream_configuration, studio_component_ids, studio_id)
    create_launch_profile(ec2_subnet_ids, launch_profile_protocol_versions, name, stream_configuration, studio_component_ids, studio_id, params::Dict{String,<:Any})

Create a launch profile.

# Arguments
- `ec2_subnet_ids`:
- `launch_profile_protocol_versions`: The version number of the protocol that is used by
  the launch profile. The only valid version is \"2021-03-31\".
- `name`: The name for the launch profile.
- `stream_configuration`: A configuration for a streaming session.
- `studio_component_ids`: Unique identifiers for a collection of studio components that can
  be used with this launch profile.
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
- `"description"`: The description.
- `"tags"`: A collection of labels, in the form of key:value pairs, that apply to this
  resource.
"""
create_launch_profile(ec2SubnetIds, launchProfileProtocolVersions, name, streamConfiguration, studioComponentIds, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/studios/$(studioId)/launch-profiles", Dict{String, Any}("ec2SubnetIds"=>ec2SubnetIds, "launchProfileProtocolVersions"=>launchProfileProtocolVersions, "name"=>name, "streamConfiguration"=>streamConfiguration, "studioComponentIds"=>studioComponentIds, "X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
create_launch_profile(ec2SubnetIds, launchProfileProtocolVersions, name, streamConfiguration, studioComponentIds, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/studios/$(studioId)/launch-profiles", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("ec2SubnetIds"=>ec2SubnetIds, "launchProfileProtocolVersions"=>launchProfileProtocolVersions, "name"=>name, "streamConfiguration"=>streamConfiguration, "studioComponentIds"=>studioComponentIds, "X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    create_streaming_image(ec2_image_id, name, studio_id)
    create_streaming_image(ec2_image_id, name, studio_id, params::Dict{String,<:Any})

Creates a streaming image resource in a studio.

# Arguments
- `ec2_image_id`: The ID of an EC2 machine image with which to create this streaming image.
- `name`: A friendly name for a streaming image resource.
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
- `"description"`: A human-readable description of the streaming image.
- `"tags"`: A collection of labels, in the form of key:value pairs, that apply to this
  resource.
"""
create_streaming_image(ec2ImageId, name, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/studios/$(studioId)/streaming-images", Dict{String, Any}("ec2ImageId"=>ec2ImageId, "name"=>name, "X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
create_streaming_image(ec2ImageId, name, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/studios/$(studioId)/streaming-images", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("ec2ImageId"=>ec2ImageId, "name"=>name, "X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    create_streaming_session(studio_id)
    create_streaming_session(studio_id, params::Dict{String,<:Any})

Creates a streaming session in a studio. After invoking this operation, you must poll
GetStreamingSession until the streaming session is in state READY.

# Arguments
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
- `"ec2InstanceType"`: The EC2 Instance type used for the streaming session.
- `"launchProfileId"`: The launch profile ID.
- `"streamingImageId"`: The ID of the streaming image.
- `"tags"`: A collection of labels, in the form of key:value pairs, that apply to this
  resource.
"""
create_streaming_session(studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/studios/$(studioId)/streaming-sessions", Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
create_streaming_session(studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/studios/$(studioId)/streaming-sessions", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    create_streaming_session_stream(session_id, studio_id)
    create_streaming_session_stream(session_id, studio_id, params::Dict{String,<:Any})

Creates a streaming session stream for a streaming session. After invoking this API, invoke
GetStreamingSessionStream with the returned streamId to poll the resource until it is in
state READY.

# Arguments
- `session_id`: The session ID.
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
- `"expirationInSeconds"`: The expiration time in seconds.
"""
create_streaming_session_stream(sessionId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/studios/$(studioId)/streaming-sessions/$(sessionId)/streams", Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
create_streaming_session_stream(sessionId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/studios/$(studioId)/streaming-sessions/$(sessionId)/streams", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    create_studio(admin_role_arn, display_name, studio_name, user_role_arn)
    create_studio(admin_role_arn, display_name, studio_name, user_role_arn, params::Dict{String,<:Any})

Create a new Studio. When creating a Studio, two IAM roles must be provided: the admin role
and the user Role. These roles are assumed by your users when they log in to the Nimble
Studio portal. The user role must have the AmazonNimbleStudio-StudioUser managed policy
attached for the portal to function properly. The Admin Role must have the
AmazonNimbleStudio-StudioAdmin managed policy attached for the portal to function properly.
You may optionally specify a KMS key in the StudioEncryptionConfiguration. In Nimble
Studio, resource names, descriptions, initialization scripts, and other data you provide
are always encrypted at rest using an AWS KMS key. By default, this key is owned by AWS and
managed on your behalf. You may provide your own AWS KMS key when calling CreateStudio to
encrypt this data using a key you own and manage. When providing an AWS KMS key during
studio creation, Nimble Studio creates KMS grants in your account to provide your studio
user and admin roles access to these KMS keys. If you delete this grant, the studio will no
longer be accessible to your portal users. If you delete the studio KMS key, your studio
will no longer be accessible.

# Arguments
- `admin_role_arn`: The IAM role that Studio Admins will assume when logging in to the
  Nimble Studio portal.
- `display_name`: A friendly name for the studio.
- `studio_name`: The studio name that is used in the URL of the Nimble Studio portal when
  accessed by Nimble Studio users.
- `user_role_arn`: The IAM role that Studio Users will assume when logging in to the Nimble
  Studio portal.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
- `"studioEncryptionConfiguration"`: The studio encryption configuration.
- `"tags"`: A collection of labels, in the form of key:value pairs, that apply to this
  resource.
"""
create_studio(adminRoleArn, displayName, studioName, userRoleArn; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/studios", Dict{String, Any}("adminRoleArn"=>adminRoleArn, "displayName"=>displayName, "studioName"=>studioName, "userRoleArn"=>userRoleArn, "X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
create_studio(adminRoleArn, displayName, studioName, userRoleArn, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/studios", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("adminRoleArn"=>adminRoleArn, "displayName"=>displayName, "studioName"=>studioName, "userRoleArn"=>userRoleArn, "X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    create_studio_component(name, studio_id, type)
    create_studio_component(name, studio_id, type, params::Dict{String,<:Any})

Creates a studio component resource.

# Arguments
- `name`: The name for the studio component.
- `studio_id`: The studio ID.
- `type`: The type of the studio component.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
- `"configuration"`: The configuration of the studio component, based on component type.
- `"description"`: The description.
- `"ec2SecurityGroupIds"`: The EC2 security groups that control access to the studio
  component.
- `"initializationScripts"`: Initialization scripts for studio components.
- `"scriptParameters"`: Parameters for the studio component scripts.
- `"subtype"`: The specific subtype of a studio component.
- `"tags"`: A collection of labels, in the form of key:value pairs, that apply to this
  resource.
"""
create_studio_component(name, studioId, type; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/studios/$(studioId)/studio-components", Dict{String, Any}("name"=>name, "type"=>type, "X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
create_studio_component(name, studioId, type, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/studios/$(studioId)/studio-components", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name, "type"=>type, "X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    delete_launch_profile(launch_profile_id, studio_id)
    delete_launch_profile(launch_profile_id, studio_id, params::Dict{String,<:Any})

Permanently delete a launch profile.

# Arguments
- `launch_profile_id`: The launch profile ID.
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
"""
delete_launch_profile(launchProfileId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("DELETE", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)", Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
delete_launch_profile(launchProfileId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("DELETE", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    delete_launch_profile_member(launch_profile_id, principal_id, studio_id)
    delete_launch_profile_member(launch_profile_id, principal_id, studio_id, params::Dict{String,<:Any})

Delete a user from launch profile membership.

# Arguments
- `launch_profile_id`: The launch profile ID.
- `principal_id`: The principal ID.
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
"""
delete_launch_profile_member(launchProfileId, principalId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("DELETE", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)/membership/$(principalId)", Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
delete_launch_profile_member(launchProfileId, principalId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("DELETE", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)/membership/$(principalId)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    delete_streaming_image(streaming_image_id, studio_id)
    delete_streaming_image(streaming_image_id, studio_id, params::Dict{String,<:Any})

Delete streaming image.

# Arguments
- `streaming_image_id`: The streaming image ID.
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
"""
delete_streaming_image(streamingImageId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("DELETE", "/2020-08-01/studios/$(studioId)/streaming-images/$(streamingImageId)", Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
delete_streaming_image(streamingImageId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("DELETE", "/2020-08-01/studios/$(studioId)/streaming-images/$(streamingImageId)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    delete_streaming_session(session_id, studio_id)
    delete_streaming_session(session_id, studio_id, params::Dict{String,<:Any})

Deletes streaming session resource. After invoking this operation, use GetStreamingSession
to poll the resource until it transitions to a DELETED state. A streaming session will
count against your streaming session quota until it is marked DELETED.

# Arguments
- `session_id`: The session ID.
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
"""
delete_streaming_session(sessionId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("DELETE", "/2020-08-01/studios/$(studioId)/streaming-sessions/$(sessionId)", Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
delete_streaming_session(sessionId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("DELETE", "/2020-08-01/studios/$(studioId)/streaming-sessions/$(sessionId)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    delete_studio(studio_id)
    delete_studio(studio_id, params::Dict{String,<:Any})

Delete a studio resource.

# Arguments
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
"""
delete_studio(studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("DELETE", "/2020-08-01/studios/$(studioId)", Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
delete_studio(studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("DELETE", "/2020-08-01/studios/$(studioId)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    delete_studio_component(studio_component_id, studio_id)
    delete_studio_component(studio_component_id, studio_id, params::Dict{String,<:Any})

Deletes a studio component resource.

# Arguments
- `studio_component_id`: The studio component ID.
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
"""
delete_studio_component(studioComponentId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("DELETE", "/2020-08-01/studios/$(studioId)/studio-components/$(studioComponentId)", Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
delete_studio_component(studioComponentId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("DELETE", "/2020-08-01/studios/$(studioId)/studio-components/$(studioComponentId)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    delete_studio_member(principal_id, studio_id)
    delete_studio_member(principal_id, studio_id, params::Dict{String,<:Any})

Delete a user from studio membership.

# Arguments
- `principal_id`: The principal ID.
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
"""
delete_studio_member(principalId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("DELETE", "/2020-08-01/studios/$(studioId)/membership/$(principalId)", Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
delete_studio_member(principalId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("DELETE", "/2020-08-01/studios/$(studioId)/membership/$(principalId)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    get_eula(eula_id)
    get_eula(eula_id, params::Dict{String,<:Any})

Get Eula.

# Arguments
- `eula_id`: The EULA ID.

"""
get_eula(eulaId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/eulas/$(eulaId)"; aws_config=aws_config)
get_eula(eulaId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/eulas/$(eulaId)", params; aws_config=aws_config)

"""
    get_launch_profile(launch_profile_id, studio_id)
    get_launch_profile(launch_profile_id, studio_id, params::Dict{String,<:Any})

Get a launch profile.

# Arguments
- `launch_profile_id`: The launch profile ID.
- `studio_id`: The studio ID.

"""
get_launch_profile(launchProfileId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)"; aws_config=aws_config)
get_launch_profile(launchProfileId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)", params; aws_config=aws_config)

"""
    get_launch_profile_details(launch_profile_id, studio_id)
    get_launch_profile_details(launch_profile_id, studio_id, params::Dict{String,<:Any})

Launch profile details include the launch profile resource and summary information of
resources that are used by, or available to, the launch profile. This includes the name and
description of all studio components used by the launch profiles, and the name and
description of streaming images that can be used with this launch profile.

# Arguments
- `launch_profile_id`: The launch profile ID.
- `studio_id`: The studio ID.

"""
get_launch_profile_details(launchProfileId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)/details"; aws_config=aws_config)
get_launch_profile_details(launchProfileId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)/details", params; aws_config=aws_config)

"""
    get_launch_profile_initialization(launch_profile_id, launch_profile_protocol_versions, launch_purpose, platform, studio_id)
    get_launch_profile_initialization(launch_profile_id, launch_profile_protocol_versions, launch_purpose, platform, studio_id, params::Dict{String,<:Any})

Get a launch profile initialization.

# Arguments
- `launch_profile_id`: The launch profile ID.
- `launch_profile_protocol_versions`: A collection of launch profile protocol versions.
- `launch_purpose`: The launch purpose.
- `platform`: The platform.
- `studio_id`: The studio ID.

"""
get_launch_profile_initialization(launchProfileId, launchProfileProtocolVersions, launchPurpose, platform, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)/init", Dict{String, Any}("launchProfileProtocolVersions"=>launchProfileProtocolVersions, "launchPurpose"=>launchPurpose, "platform"=>platform); aws_config=aws_config)
get_launch_profile_initialization(launchProfileId, launchProfileProtocolVersions, launchPurpose, platform, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)/init", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("launchProfileProtocolVersions"=>launchProfileProtocolVersions, "launchPurpose"=>launchPurpose, "platform"=>platform), params)); aws_config=aws_config)

"""
    get_launch_profile_member(launch_profile_id, principal_id, studio_id)
    get_launch_profile_member(launch_profile_id, principal_id, studio_id, params::Dict{String,<:Any})

Get a user persona in launch profile membership.

# Arguments
- `launch_profile_id`: The launch profile ID.
- `principal_id`: The principal ID.
- `studio_id`: The studio ID.

"""
get_launch_profile_member(launchProfileId, principalId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)/membership/$(principalId)"; aws_config=aws_config)
get_launch_profile_member(launchProfileId, principalId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)/membership/$(principalId)", params; aws_config=aws_config)

"""
    get_streaming_image(streaming_image_id, studio_id)
    get_streaming_image(streaming_image_id, studio_id, params::Dict{String,<:Any})

Get streaming image.

# Arguments
- `streaming_image_id`: The streaming image ID.
- `studio_id`: The studio ID.

"""
get_streaming_image(streamingImageId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/streaming-images/$(streamingImageId)"; aws_config=aws_config)
get_streaming_image(streamingImageId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/streaming-images/$(streamingImageId)", params; aws_config=aws_config)

"""
    get_streaming_session(session_id, studio_id)
    get_streaming_session(session_id, studio_id, params::Dict{String,<:Any})

Gets StreamingSession resource. Invoke this operation to poll for a streaming session state
while creating or deleting a session.

# Arguments
- `session_id`: The session ID.
- `studio_id`: The studio ID.

"""
get_streaming_session(sessionId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/streaming-sessions/$(sessionId)"; aws_config=aws_config)
get_streaming_session(sessionId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/streaming-sessions/$(sessionId)", params; aws_config=aws_config)

"""
    get_streaming_session_stream(session_id, stream_id, studio_id)
    get_streaming_session_stream(session_id, stream_id, studio_id, params::Dict{String,<:Any})

Gets a StreamingSessionStream for a streaming session. Invoke this operation to poll the
resource after invoking CreateStreamingSessionStream. After the StreamingSessionStream
changes to the state READY, the url property will contain a stream to be used with the DCV
streaming client.

# Arguments
- `session_id`: The session ID.
- `stream_id`: The stream ID.
- `studio_id`: The studio ID.

"""
get_streaming_session_stream(sessionId, streamId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/streaming-sessions/$(sessionId)/streams/$(streamId)"; aws_config=aws_config)
get_streaming_session_stream(sessionId, streamId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/streaming-sessions/$(sessionId)/streams/$(streamId)", params; aws_config=aws_config)

"""
    get_studio(studio_id)
    get_studio(studio_id, params::Dict{String,<:Any})

Get a Studio resource.

# Arguments
- `studio_id`: The studio ID.

"""
get_studio(studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)"; aws_config=aws_config)
get_studio(studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)", params; aws_config=aws_config)

"""
    get_studio_component(studio_component_id, studio_id)
    get_studio_component(studio_component_id, studio_id, params::Dict{String,<:Any})

Gets a studio component resource.

# Arguments
- `studio_component_id`: The studio component ID.
- `studio_id`: The studio ID.

"""
get_studio_component(studioComponentId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/studio-components/$(studioComponentId)"; aws_config=aws_config)
get_studio_component(studioComponentId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/studio-components/$(studioComponentId)", params; aws_config=aws_config)

"""
    get_studio_member(principal_id, studio_id)
    get_studio_member(principal_id, studio_id, params::Dict{String,<:Any})

Get a user's membership in a studio.

# Arguments
- `principal_id`: The principal ID.
- `studio_id`: The studio ID.

"""
get_studio_member(principalId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/membership/$(principalId)"; aws_config=aws_config)
get_studio_member(principalId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/membership/$(principalId)", params; aws_config=aws_config)

"""
    list_eula_acceptances(studio_id)
    list_eula_acceptances(studio_id, params::Dict{String,<:Any})

List Eula Acceptances.

# Arguments
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"eulaIds"`: A collection of EULA IDs.
- `"nextToken"`: The token for the next set of results, or null if there are no more
  results.
"""
list_eula_acceptances(studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/eula-acceptances"; aws_config=aws_config)
list_eula_acceptances(studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/eula-acceptances", params; aws_config=aws_config)

"""
    list_eulas()
    list_eulas(params::Dict{String,<:Any})

List Eulas.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"eulaIds"`: A collection of EULA IDs.
- `"nextToken"`: The token for the next set of results, or null if there are no more
  results.
"""
list_eulas(; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/eulas"; aws_config=aws_config)
list_eulas(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/eulas", params; aws_config=aws_config)

"""
    list_launch_profile_members(launch_profile_id, studio_id)
    list_launch_profile_members(launch_profile_id, studio_id, params::Dict{String,<:Any})

Get all users in a given launch profile membership.

# Arguments
- `launch_profile_id`: The launch profile ID.
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results to be returned per request.
- `"nextToken"`: The token for the next set of results, or null if there are no more
  results.
"""
list_launch_profile_members(launchProfileId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)/membership"; aws_config=aws_config)
list_launch_profile_members(launchProfileId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)/membership", params; aws_config=aws_config)

"""
    list_launch_profiles(studio_id)
    list_launch_profiles(studio_id, params::Dict{String,<:Any})

List all the launch profiles a studio.

# Arguments
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results to be returned per request.
- `"nextToken"`: The token for the next set of results, or null if there are no more
  results.
- `"principalId"`: The principal ID.
- `"states"`: A list of states.
"""
list_launch_profiles(studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/launch-profiles"; aws_config=aws_config)
list_launch_profiles(studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/launch-profiles", params; aws_config=aws_config)

"""
    list_streaming_images(studio_id)
    list_streaming_images(studio_id, params::Dict{String,<:Any})

List the streaming image resources available to this studio. This list will contain both
images provided by AWS, as well as streaming images that you have created in your studio.

# Arguments
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"nextToken"`: The token for the next set of results, or null if there are no more
  results.
- `"owner"`: The owner.
"""
list_streaming_images(studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/streaming-images"; aws_config=aws_config)
list_streaming_images(studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/streaming-images", params; aws_config=aws_config)

"""
    list_streaming_sessions(studio_id)
    list_streaming_sessions(studio_id, params::Dict{String,<:Any})

Lists the streaming image resources in a studio.

# Arguments
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"createdBy"`: The user ID.
- `"nextToken"`: The token for the next set of results, or null if there are no more
  results.
- `"sessionIds"`: A collection of session IDs.
"""
list_streaming_sessions(studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/streaming-sessions"; aws_config=aws_config)
list_streaming_sessions(studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/streaming-sessions", params; aws_config=aws_config)

"""
    list_studio_components(studio_id)
    list_studio_components(studio_id, params::Dict{String,<:Any})

Lists the StudioComponents in a studio.

# Arguments
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results to be returned per request.
- `"nextToken"`: The token for the next set of results, or null if there are no more
  results.
- `"states"`: A list of states.
- `"types"`: The types.
"""
list_studio_components(studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/studio-components"; aws_config=aws_config)
list_studio_components(studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/studio-components", params; aws_config=aws_config)

"""
    list_studio_members(studio_id)
    list_studio_members(studio_id, params::Dict{String,<:Any})

Get all users in a given studio membership.

# Arguments
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results to be returned per request.
- `"nextToken"`: The token for the next set of results, or null if there are no more
  results.
"""
list_studio_members(studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/membership"; aws_config=aws_config)
list_studio_members(studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios/$(studioId)/membership", params; aws_config=aws_config)

"""
    list_studios()
    list_studios(params::Dict{String,<:Any})

List studios in your AWS account in the requested AWS Region.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"nextToken"`: The token for the next set of results, or null if there are no more
  results.
"""
list_studios(; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios"; aws_config=aws_config)
list_studios(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/studios", params; aws_config=aws_config)

"""
    list_tags_for_resource(resource_arn)
    list_tags_for_resource(resource_arn, params::Dict{String,<:Any})

Gets the tags for a resource, given its Amazon Resource Names (ARN). This operation
supports ARNs for all resource types in Nimble Studio that support tags, including studio,
studio component, launch profile, streaming image, and streaming session. All resources
that can be tagged will contain an ARN property, so you do not have to create this ARN
yourself.

# Arguments
- `resource_arn`: The ARN of the target resource for tagging operations.

"""
list_tags_for_resource(resourceArn; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/tags/$(resourceArn)"; aws_config=aws_config)
list_tags_for_resource(resourceArn, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("GET", "/2020-08-01/tags/$(resourceArn)", params; aws_config=aws_config)

"""
    put_launch_profile_members(identity_store_id, launch_profile_id, members, studio_id)
    put_launch_profile_members(identity_store_id, launch_profile_id, members, studio_id, params::Dict{String,<:Any})

Add/update users with given persona to launch profile membership.

# Arguments
- `identity_store_id`: The ID of the identity store.
- `launch_profile_id`: The launch profile ID.
- `members`: A list of members.
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
"""
put_launch_profile_members(identityStoreId, launchProfileId, members, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)/membership", Dict{String, Any}("identityStoreId"=>identityStoreId, "members"=>members, "X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
put_launch_profile_members(identityStoreId, launchProfileId, members, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)/membership", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("identityStoreId"=>identityStoreId, "members"=>members, "X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    put_studio_members(identity_store_id, members, studio_id)
    put_studio_members(identity_store_id, members, studio_id, params::Dict{String,<:Any})

Add/update users with given persona to studio membership.

# Arguments
- `identity_store_id`: The ID of the identity store.
- `members`: A list of members.
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
"""
put_studio_members(identityStoreId, members, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/studios/$(studioId)/membership", Dict{String, Any}("identityStoreId"=>identityStoreId, "members"=>members, "X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
put_studio_members(identityStoreId, members, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/studios/$(studioId)/membership", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("identityStoreId"=>identityStoreId, "members"=>members, "X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    start_studio_ssoconfiguration_repair(studio_id)
    start_studio_ssoconfiguration_repair(studio_id, params::Dict{String,<:Any})

Repairs the SSO configuration for a given studio. If the studio has a valid AWS SSO
configuration currently associated with it, this operation will fail with a validation
error. If the studio does not have a valid AWS SSO configuration currently associated with
it, then a new AWS SSO application is created for the studio and the studio is changed to
the READY state. After the AWS SSO application is repaired, you must use the Amazon Nimble
Studio console to add administrators and users to your studio.

# Arguments
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
"""
start_studio_ssoconfiguration_repair(studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("PUT", "/2020-08-01/studios/$(studioId)/sso-configuration", Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
start_studio_ssoconfiguration_repair(studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("PUT", "/2020-08-01/studios/$(studioId)/sso-configuration", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    tag_resource(resource_arn)
    tag_resource(resource_arn, params::Dict{String,<:Any})

Creates tags for a resource, given its ARN.

# Arguments
- `resource_arn`: The ARN of the target resource for tagging operations.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"tags"`: A collection of labels, in the form of key:value pairs, that apply to this
  resource.
"""
tag_resource(resourceArn; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/tags/$(resourceArn)"; aws_config=aws_config)
tag_resource(resourceArn, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("POST", "/2020-08-01/tags/$(resourceArn)", params; aws_config=aws_config)

"""
    untag_resource(resource_arn, tag_keys)
    untag_resource(resource_arn, tag_keys, params::Dict{String,<:Any})

Deletes the tags for a resource.

# Arguments
- `resource_arn`: The ARN of the target resource for tagging operations.
- `tag_keys`: An array of tag keys to delete.

"""
untag_resource(resourceArn, tagKeys; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("DELETE", "/2020-08-01/tags/$(resourceArn)", Dict{String, Any}("tagKeys"=>tagKeys); aws_config=aws_config)
untag_resource(resourceArn, tagKeys, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("DELETE", "/2020-08-01/tags/$(resourceArn)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("tagKeys"=>tagKeys), params)); aws_config=aws_config)

"""
    update_launch_profile(launch_profile_id, studio_id)
    update_launch_profile(launch_profile_id, studio_id, params::Dict{String,<:Any})

Update a launch profile.

# Arguments
- `launch_profile_id`: The launch profile ID.
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
- `"description"`: The description.
- `"launchProfileProtocolVersions"`: The version number of the protocol that is used by the
  launch profile. The only valid version is \"2021-03-31\".
- `"name"`: The name for the launch profile.
- `"streamConfiguration"`: A configuration for a streaming session.
- `"studioComponentIds"`: Unique identifiers for a collection of studio components that can
  be used with this launch profile.
"""
update_launch_profile(launchProfileId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("PATCH", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)", Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
update_launch_profile(launchProfileId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("PATCH", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    update_launch_profile_member(launch_profile_id, persona, principal_id, studio_id)
    update_launch_profile_member(launch_profile_id, persona, principal_id, studio_id, params::Dict{String,<:Any})

Update a user persona in launch profile membership.

# Arguments
- `launch_profile_id`: The launch profile ID.
- `persona`: The persona.
- `principal_id`: The principal ID.
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
"""
update_launch_profile_member(launchProfileId, persona, principalId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("PATCH", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)/membership/$(principalId)", Dict{String, Any}("persona"=>persona, "X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
update_launch_profile_member(launchProfileId, persona, principalId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("PATCH", "/2020-08-01/studios/$(studioId)/launch-profiles/$(launchProfileId)/membership/$(principalId)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("persona"=>persona, "X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    update_streaming_image(streaming_image_id, studio_id)
    update_streaming_image(streaming_image_id, studio_id, params::Dict{String,<:Any})

Update streaming image.

# Arguments
- `streaming_image_id`: The streaming image ID.
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
- `"description"`: The description.
- `"name"`: The name for the streaming image.
"""
update_streaming_image(streamingImageId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("PATCH", "/2020-08-01/studios/$(studioId)/streaming-images/$(streamingImageId)", Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
update_streaming_image(streamingImageId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("PATCH", "/2020-08-01/studios/$(studioId)/streaming-images/$(streamingImageId)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    update_studio(studio_id)
    update_studio(studio_id, params::Dict{String,<:Any})

Update a Studio resource. Currently, this operation only supports updating the displayName
of your studio.

# Arguments
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
- `"adminRoleArn"`: The IAM role that Studio Admins will assume when logging in to the
  Nimble Studio portal.
- `"displayName"`: A friendly name for the studio.
- `"userRoleArn"`: The IAM role that Studio Users will assume when logging in to the Nimble
  Studio portal.
"""
update_studio(studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("PATCH", "/2020-08-01/studios/$(studioId)", Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
update_studio(studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("PATCH", "/2020-08-01/studios/$(studioId)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)

"""
    update_studio_component(studio_component_id, studio_id)
    update_studio_component(studio_component_id, studio_id, params::Dict{String,<:Any})

Updates a studio component resource.

# Arguments
- `studio_component_id`: The studio component ID.
- `studio_id`: The studio ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"X-Amz-Client-Token"`: To make an idempotent API request using one of these actions,
  specify a client token in the request. You should not reuse the same client token for other
  API requests. If you retry a request that completed successfully using the same client
  token and the same parameters, the retry succeeds without performing any further actions.
  If you retry a successful request using the same client token, but one or more of the
  parameters are different, the retry fails with a ValidationException error.
- `"configuration"`: The configuration of the studio component, based on component type.
- `"description"`: The description.
- `"ec2SecurityGroupIds"`: The EC2 security groups that control access to the studio
  component.
- `"initializationScripts"`: Initialization scripts for studio components.
- `"name"`: The name for the studio component.
- `"scriptParameters"`: Parameters for the studio component scripts.
- `"subtype"`: The specific subtype of a studio component.
- `"type"`: The type of the studio component.
"""
update_studio_component(studioComponentId, studioId; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("PATCH", "/2020-08-01/studios/$(studioId)/studio-components/$(studioComponentId)", Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())); aws_config=aws_config)
update_studio_component(studioComponentId, studioId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = nimble("PATCH", "/2020-08-01/studios/$(studioId)/studio-components/$(studioComponentId)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("X-Amz-Client-Token"=>string(uuid4())), params)); aws_config=aws_config)


text:
local i::Int
local n::Int
local f::Int

i=2
n=5
f=1

while (i < n + 1)
    f=f*i
    i=i+1
end

println(f)

ext: jl


text:
@doc doc"""
    Metric

Abstract type for the pseudo-Riemannian metric tensor $g$, a family of smoothly
varying inner products on the tangent space. See [`inner`](@ref).
"""
abstract type Metric end

@doc doc"""
    RiemannianMetric <: Metric

Abstract type for Riemannian metrics, a family of positive definite inner
products. The positive definite property means that for $v \in T_x M$, the
inner product $g(v, v) > 0$ whenever $v$ is not the zero vector.
"""
abstract type RiemannianMetric <: Metric end

@doc doc"""
    LorentzMetric <: Metric

Abstract type for Lorentz metrics, which have a single time dimension. These
metrics assume the spacelike convention with the time dimension being last,
giving the signature $(++...+-)$.
"""
abstract type LorentzMetric <: Metric end

"""
    MetricManifold{M<:Manifold,G<:Metric} <: Manifold

Equip a manifold with a metric. Such a manifold is generally called pseudo-
or semi-Riemannian. Each `MetricManifold` must implement
[`local_metric`](@ref).

# Constructor

    MetricManifold(manifold, metric)
"""
struct MetricManifold{M<:Manifold,G<:Metric} <: Manifold
    manifold::M
    metric::G
end

convert(::Type{MT},M::MetricManifold{MT,GT}) where {MT,GT} = M.manifold

@traitimpl IsDecoratorManifold{MetricManifold}

"""
    HasMetric

A `Trait` to mark a `Manifold` `M` as being shorthand for a
`MetricManifold{M,G}` with metric `G`. This can be used to forward functions
called on the `MetricManifold` to the already-imlemented functions for the
`Manifold`.

For example,

```
@traitfn function my_feature(M::MMT, k...) where {MT<:Manifold,
                                                  GT<:Metric,
                                                  MMT<:MetricManifold{MT,GT};
                                                  HasMetric{MT,GT}}
    return my_feature(M.manifold, k...)
end
```

forwards the function `my_feature` from `M` to the already-implemented
`my_feature` on the base manifold `M.manifold`. A manifold with a default
metric can then be written

```
struct MyManifold{T} <: Manifold end
struct MyMetric{S} <: Metric end
@traitimpl HasMetric{MyManifold,MyMetric}
```
"""
@traitdef HasMetric{M,G}

@doc doc"""
    metric(M::MetricManifold)

Get the metric $g$ of the manifold `M`.
"""
metric(M::MetricManifold) = M.metric

@doc doc"""
    local_metric(M::MetricManifold, x)

Local matrix representation at the point `x` of the metric tensor $g$ on the
manifold `M`, usually written $g_{ij}$. The matrix has the property that
$g(v, w)=v^T [g_{ij}] w = g_{ij} v^i w^j$, where the latter expression uses
Einstein summation convention.
"""
function local_metric(M::MetricManifold, x)
    error("Local metric not implemented on $(typeof(M)) for point $(typeof(x))")
end

@doc doc"""
    inverse_local_metric(M::MetricManifold, x)

Local matrix representation of the inverse metric (cometric) tensor, usually
written $g^{ij}$
"""
inverse_local_metric(M::MetricManifold, x) = inv(local_metric(M, x))

@doc doc"""
    det_local_metric(M::MetricManifold, x)

Determinant of local matrix representation of the metric tensor $g$
"""
det_local_metric(M::MetricManifold, x) = det(local_metric(M, x))

@doc doc"""
    log_local_metric_density(M::MetricManifold, x)

Return the natural logarithm of the metric density $\rho$ of `M` at `x`, which
is given by $\rho=\log \sqrt{|\det [g_{ij}]|}$.
"""
log_local_metric_density(M::MetricManifold, x) = log(abs(det_local_metric(M, x))) / 2

@doc doc"""
    local_metric_jacobian(M::MetricManifold, x)

Get partial derivatives of the local metric of `M` at `x` with respect to the
coordinates of `x`, $\frac{\partial}{\partial x^k} g_{ij} = g_{ij,k}$. The
dimensions of the resulting multi-dimensional array are ordered $(i,j,k)$.
"""
function local_metric_jacobian(M::MetricManifold, x)
    n = size(x, 1)
    ∂g = reshape(ForwardDiff.jacobian(x -> local_metric(M, x), x), n, n, n)
    return ∂g
end

@traitfn function inner(M::MMT, x, v, w) where {MT<:Manifold,
                                                GT<:Metric,
                                                MMT<:MetricManifold{MT,GT};
                                                !HasMetric{MT,GT}}
    return dot(v, local_metric(M, x) * w)
end

@traitfn function inner(M::MMT, x, v, w) where {MT<:Manifold,
                                                GT<:Metric,
                                                MMT<:MetricManifold{MT,GT};
                                                HasMetric{MT,GT}}
    return inner(M.manifold, x, v, w)
end

@traitfn function norm(M::MMT, x, v) where {MT<:Manifold,
                                            GT<:Metric,
                                            MMT<:MetricManifold{MT,GT};
                                            !HasMetric{MT,GT}}
    return sqrt(inner(M, x, v, v))
end

@traitfn function norm(M::MMT, x, v) where {MT<:Manifold,
                                            GT<:Metric,
                                            MMT<:MetricManifold{MT,GT};
                                            HasMetric{MT,GT}}
    return norm(M.manifold, x, v)
end

@traitfn function distance(M::MMT, x, y) where {MT<:Manifold,
                                                GT<:Metric,
                                                MMT<:MetricManifold{MT,GT};
                                                !HasMetric{MT,GT}}
    return norm(M, x, log(M, x, y))
end

@traitfn function distance(M::MMT, x, y) where {MT<:Manifold,
                                                GT<:Metric,
                                                MMT<:MetricManifold{MT,GT};
                                                HasMetric{MT,GT}}
    return distance(M.manifold, x, y)
end

@doc doc"""
    christoffel_symbols_first(M::MetricManifold, x)

Compute the Christoffel symbols of the first kind in local coordinates.
The Christoffel symbols are (in Einstein summation convention)

$\Gamma_{ijk} = \frac{1}{2} \left[g_{kj,i} + g_{ik,j} - g_{ij,k}\right],$

where $g_{ij,k}=\frac{\partial}{\partial x^k} g_{ij}$ is the coordinate
derivative of the local representation of the metric tensor. The dimensions of
the resulting multi-dimensional array are ordered $(i,j,k)$.
"""
function christoffel_symbols_first(M::MetricManifold, x)
    ∂g = local_metric_jacobian(M, x)
    n = size(∂g, 1)
    Γ = similar(∂g, Size(n, n, n))
    @einsum Γ[i,j,k] = 1 / 2 * (∂g[k,j,i] + ∂g[i,k,j] - ∂g[i,j,k])
    return Γ
end

@doc doc"""
    christoffel_symbols_second(M::MetricManifold, x)

Compute the Christoffel symbols of the second kind in local coordinates.
The Christoffel symbols are (in Einstein summation convention)

$\Gamma^{l}_{ij} = g^{kl} \Gamma_{ijk},$

where $\Gamma_{ijk}$ are the Christoffel symbols of the first kind, and
$g^{kl}$ is the inverse of the local representation of the metric tensor.
The dimensions of the resulting multi-dimensional array are ordered $(l,i,j)$.
"""
function christoffel_symbols_second(M::MetricManifold, x)
    ginv = inverse_local_metric(M, x)
    Γ₁ = christoffel_symbols_first(M, x)
    Γ₂ = similar(Γ₁)
    @einsum Γ₂[l,i,j] = ginv[k,l] * Γ₁[i,j,k]
    return Γ₂
end

@doc doc"""
    riemann_tensor(M::MetricManifold, x)

Compute the Riemann tensor $R^l_{ijk}$, also known as the Riemann curvature
tensor, at the point `x`. The dimensions of the resulting multi-dimensional
array are ordered $(l,i,j,k)$.
"""
function riemann_tensor(M::MetricManifold, x)
    n = size(x, 1)
    Γ = christoffel_symbols_second(M, x)
    ∂Γ = reshape(
        ForwardDiff.jacobian(x -> christoffel_symbols_second(M, x), x),
        n, n, n, n
    ) ./ n
    R = similar(∂Γ, Size(n, n, n, n))
    @einsum R[l,i,j,k] = ∂Γ[l,i,k,j] - ∂Γ[l,i,j,k] + Γ[s,i,k] * Γ[l,s,j] - Γ[s,i,j] * Γ[l,s,k]
    return R
end

"""
    ricci_tensor(M::MetricManifold, x)

Compute the Ricci tensor, also known as the Ricci curvature tensor,
of the manifold `M` at the point `x`.
"""
function ricci_tensor(M::MetricManifold, x)
    R = riemann_tensor(M, x)
    n = size(R, 1)
    Ric = similar(R, Size(n, n))
    @einsum Ric[i,j] = R[l,i,l,j]
    return Ric
end

"""
    ricci_curvature(M::MetricManifold, x)

Compute the Ricci scalar curvature of the manifold `M` at the point `x`.
"""
function ricci_curvature(M::MetricManifold, x)
    ginv = inverse_local_metric(M, x)
    Ric = ricci_tensor(M, x)
    S = sum(ginv .* Ric)
    return S
end

"""
    gaussian_curvature(M::MetricManifold, x)

Compute the Gaussian curvature of the manifold `M` at the point `x`.
"""
gaussian_curvature(M::MetricManifold, x) = ricci_curvature(M, x) / 2

"""
    einstein_tensor(M::MetricManifold, x)

Compute the Einstein tensor of the manifold `M` at the point `x`.
"""
function einstein_tensor(M::MetricManifold, x)
    Ric = ricci_tensor(M, x)
    g = local_metric(M, x)
    ginv = inverse_local_metric(M, x)
    S = sum(ginv .* Ric)
    G = Ric - g .* S / 2
    return G
end

@doc doc"""
    solve_exp_ode(M::MetricManifold,
                  x,
                  v,
                  tspan;
                  solver=AutoVern9(Rodas5()),
                  kwargs...)

Approximate the exponential map on the manifold over the provided timespan
assuming the Levi-Civita connection by solving the ordinary differential
equation

$\frac{d^2}{dt^2} x^k + \Gamma^k_{ij} \frac{d}{dt} x_i \frac{d}{dt} x_j = 0,$

where $\Gamma^k_{ij}$ are the Christoffel symbols of the second kind, and
the Einstein summation convention is assumed. The arguments `tspan` and
`solver` follow the `OrdinaryDiffEq` conventions. `kwargs...` specify keyword
arguments that will be passed to `OrdinaryDiffEq.solve`.

Currently, the numerical integration is only accurate when using a single
coordinate chart that covers the entire manifold. This excludes coordinates
in an embedded space.
"""
function solve_exp_ode(M::MetricManifold,
                       x,
                       v,
                       tspan;
                       solver=AutoVern9(Rodas5()),
                       kwargs...)
    n = length(x)
    iv = SVector{n}(1:n)
    ix = SVector{n}(n+1:2n)
    u0 = similar(x, 2n)
    u0[iv] .= v
    u0[ix] .= x

    function exp_problem(u, p, t)
        M = p[1]
        dx = u[iv]
        x = u[ix]
        ddx = similar(u, Size(n))
        du = similar(u)
        Γ = christoffel_symbols_second(M, x)
        @einsum ddx[k] = -Γ[k,i,j] * dx[i] * dx[j]
        du[iv] .= ddx
        du[ix] .= dx
        return Base.convert(typeof(u), du)
    end

    p = (M,)
    prob = ODEProblem(exp_problem, u0, tspan, p)
    sol = solve(prob, solver; kwargs...)
    return sol
end

@traitfn function exp(M::MMT,
                      x,
                      v,
                      T::AbstractVector) where {MT<:Manifold,
                                                GT<:Metric,
                                                MMT<:MetricManifold{MT,GT};
                                                !HasMetric{MT,GT}}
    sol = solve_exp_ode(M, x, v, extrema(T); dense=false, saveat=T)
    n = length(x)
    return map(i -> sol.u[i][n+1:end], 1:length(T))
end

"""
    exp(M::MetricManifold, x, v, args...)

If the [`HasMetric`](@ref) trait is defined for `M`, compute the exponential
map of the base manifold. Otherwise, numerically integrate the exponential
map assuming the Levi-Civita connection. See [`solve_exp_ode`](@ref)

Currently, the numerical integration is only accurate when using a single
coordinate chart that covers the entire manifold. This excludes coordinates
in an embedded space.
"""
function exp end

@traitfn function exp!(M::MMT, y, x, v) where {MT<:Manifold,
                                               GT<:Metric,
                                               MMT<:MetricManifold{MT,GT};
                                               !HasMetric{MT,GT}}
    tspan = (0.0, 1.0)
    sol = solve_exp_ode(M, x, v, tspan; dense=false, saveat=[1.0])
    n = length(x)
    y .= sol.u[1][n+1:end]
    return y
end

@traitfn function exp!(M::MMT, y, x, v) where {MT<:Manifold,
                                               GT<:Metric,
                                               MMT<:MetricManifold{MT,GT};
                                               HasMetric{MT,GT}}
    return exp!(M.manifold, y, x, v)
end

@traitfn function log!(M::MMT, v, x, y) where {MT<:Manifold,
                                               GT<:Metric,
                                               MMT<:MetricManifold{MT,GT};
                                               !HasMetric{MT,GT}}
    error("Logarithmic map not implemented on $(typeof(M)) for points $(typeof(x)) and $(typeof(y))")
end

@traitfn function log!(M::MMT, v, x, y) where {MT<:Manifold,
                                               GT<:Metric,
                                               MMT<:MetricManifold{MT,GT};
                                               HasMetric{MT,GT}}
    return log!(M.manifold, v, x, y)
end

@traitfn function retract!(M::MMT,
                           y,
                           x,
                           v,
                           t::Real) where {MT<:Manifold,
                                           GT<:Metric,
                                           MMT<:MetricManifold{MT,GT};
                                           HasMetric{MT,GT}}
    return retract!(M.manifold, y, x, v, t)
end

@traitfn function retract!(M::MMT,
                           y,
                           x,
                           v) where {MT<:Manifold,
                                           GT<:Metric,
                                           MMT<:MetricManifold{MT,GT};
                                           HasMetric{MT,GT}}
    return retract!(M.manifold, y, x, v)
end

@traitfn function project_tangent!(M::MMT,
                                   w,
                                   x,
                                   v) where {MT<:Manifold,
                                             GT<:Metric,
                                             MMT<:MetricManifold{MT,GT};
                                             HasMetric{MT,GT}}
    return project_tangent!(M.manifold, w, x, v)
end

@traitfn function injectivity_radius(M::MMT,
                                     args...) where {MT<:Manifold,
                                                     GT<:Metric,
                                                     MMT<:MetricManifold{MT,GT};
                                                     HasMetric{MT,GT}}
    return injectivity_radius(M.manifold, args...)
end

@traitfn function zero_tangent_vector!(M::MMT,
                                       v,
                                       x) where {MT<:Manifold,
                                                 GT<:Metric,
                                                 MMT<:MetricManifold{MT,GT};
                                                 HasMetric{MT,GT}}
    return zero_tangent_vector!(M.manifold, v, x)
end

@traitfn function is_manifold_point(M::MMT,
                                    x;
                                    kwargs...) where {MT<:Manifold,
                                                      GT<:Metric,
                                                      MMT<:MetricManifold{MT,GT};
                                                      HasMetric{MT,GT}}
    return is_manifold_point(M.manifold, x; kwargs...)
end

@traitfn function is_tangent_vector(M::MMT,
                                    x,
                                    v;
                                    kwargs...) where {MT<:Manifold,
                                                      GT<:Metric,
                                                      MMT<:MetricManifold{MT,GT};
                                                      HasMetric{MT,GT}}
    return is_tangent_vector(M.manifold, x, v; kwargs...)
end


text:
using SDWBA
using Test

# include("test_bent_cylinder.jl")
include("test_scatterer.jl")

println("\nPassed all tests.")


text:
module OptionPrice

using Distributions
using GaussQuadrature
using Optim
using SDEModels

include("models/models.jl")
include("pricers/pricers.jl")

export Analytic, CarrMadan, Lewis,
       price

end # module


text:
using ArgParse
using LinearAlgebra

s = ArgParseSettings()
@add_arg_table s begin
    "--part2"
    help = "Do part 2"
    action = :store_true
    "--test"
    help = "Run test data"
    action = :store_true
end

rotx = [ 1 0 0
         0 0 -1;
         0 1 0]
roty = [ 0 0 1;
         0 1 0;
        -1 0 0]
rotz = [ 0 -1 0;
         1 0 0;
         0 0 1]

rotations = []
function mat_4ways(mat, rotation)
    r = mat
    for _ in 1:4
        push!(rotations, r)
        r = r * rotation
    end
end

function make_rotations()
    #
    mat = Matrix(1I, 3, 3)
    mat_4ways(mat, rotx)
    mat_4ways(rotz, roty)
    mat_4ways(rotz * rotz * rotz, roty)
    mat_4ways(roty, rotz)
    mat_4ways(roty * roty * roty, rotz)
    mat_4ways(rotz * rotz, rotx)
end

parsed_args = parse_args(ARGS, s)
test_suffix = parsed_args["test"] ? "_test" : ""
scanners = []
current_scanner = Set()
for l in readlines("input/day_19$test_suffix.txt")
    if startswith(l, "--- scanner")
        global current_scanner = Set()
    elseif isempty(l)
        push!(scanners, current_scanner)
    else
        coords = split(l, ",")
        push!(current_scanner,map(s -> parse(Int64, s), coords))
    end
end

function distance_map(scanner)
    dmap = Dict()
    function add_distances(s)
        if isempty(s)
            return dmap
        end
        b, rest = Iterators.peel(s)
        for c in rest
            dist = sum([(b[x]-c[x])^2 for x in 1:3])
            dmap[dist] = (b,c)
        end
        add_distances(rest)
    end
    add_distances(scanner)
    dmap
end

function find_known()
    # println("Scanners - $(length(scanners))")
    make_rotations()
    known_beacons = scanners[1] # Will aim to get all beacons in Scanner 0 co-ords
    popfirst!(scanners)

    # Work out distances between beacons in for remaining sets
    distance_sets = map(distance_map, scanners)
    distance_keys = map(ds -> Set(keys(ds)), distance_sets)
    found_one = true
    deltas = [[0,0,0]]
    while (found_one && length(scanners) > 0)
        # println("Remaining $(length(scanners))")
        # println("Known $(length(known_beacons))")
        known_dists = distance_map(known_beacons)
        known_distances = Set(keys(known_dists))
        # println("Known_distances $(length(known_distances))")
        found_one = false
        for (i, dk) in enumerate(distance_keys)
            # println("Checking $i")
            shared_distances = intersect(known_distances, dk)
            # println("  shared_distaces $(length(shared_distances))")
            if length(shared_distances) < 66 # 11 + 10 + ... :
                continue
            end
            dist = pop!(shared_distances)
            # println("Dist is $dist")
            (ki1, ki2) = known_dists[dist] # known co-ords of beacons.
            (ui1, ui2) = distance_sets[i][dist] # co-ords of same beacons in shifted/rotated co-ords
            # so now we rotate them so that the linear offsets are the same.
            matches = false
            for r in rotations
                # println("$r")
                ti1 = r * ui1
                ti2 = r * ui2
                delta = []
                if (ki1 - ti1) == (ki2 - ti2) # pairs match as is
                    delta = ki1 - ti1
                elseif (ki1 - ti2) == (ki2 - ti1)
                    delta = ki2 - ti1
                else
                    # println("Nomatch")
                    continue
                end
                # println("Offset $delta")
                # now double check overlap - map beacons
                s_abs = Set()
                for b in scanners[i]
                    push!(s_abs, r*b + delta)
                end
                if length(intersect(s_abs, known_beacons)) >= 12
                    union!(known_beacons, s_abs)
                    push!(deltas, delta)
                    matches = true
                    break
                end
                # println("!!! WTF")
            end
            if matches
                deleteat!(scanners, i)
                deleteat!(distance_sets, i)
                deleteat!(distance_keys, i)
                found_one = true
                break
            end
        end
    end
    (known_beacons, deltas)
end
function part1()
    length(find_known()[1])
end

function part2()
    (_, deltas) = find_known()
    md = 0
    function find_man(s)
        if isempty(s)
            return
        end
        b, rest = Iterators.peel(s)
        for c in rest
            # println("$b, $c")
            dist = sum([abs(b[x]-c[x]) for x in 1:3])
            if (dist > md)
                md = dist
            end
        end
        find_man(rest)
    end
    find_man(deltas)
    md
end

p = parsed_args["part2"] ? part2 : part1
answer = p()
println("The answer is: $answer")


text:
function NetworkCrawler(arg0::Vector{URL})
    return NetworkCrawler((Vector{URL},), arg0)
end

function set_timeout(obj::NetworkCrawler, arg0::jint)
    return jcall(obj, "setTimeout", void, (jint,), arg0)
end


text:
if R123_USE_AESNI
    import RandomNumbers: split_uint
    key = rand(UInt128)
    r = ARS1x(key)
    r1 = ARS4x(split_uint(key, UInt32))
    @test seed_type(r) == UInt128
    @test seed_type(r1) == NTuple{4, UInt32}
    @test copyto!(copy(r), r) == r
    @test copyto!(copy(r1), r1) == r1
    @test r.x == rand(r1, UInt128)
    @test rand(r, UInt128) == rand(r1, UInt128)
    set_counter!(r, 0)
    set_counter!(r1, 1)
    @test rand(r, Tuple{UInt128})[1] == rand(r1, UInt128)
end


text:
@doc raw"""
    LieODEProblemType

An initial value problem manifold ordinary differential equation in the Lie action formulation.

A Lie ODE on manifold ``M`` is defined in terms a vector field ``F: (ℝ × P × M) \to 𝔤``
where ``𝔤`` is the Lie algebra of a Lie group ``G`` acting on ``M``, with an
initial value ``y₀`` and ``P`` is the space of constant parameters. A solution to this
problem is a curve ``y:ℝ\to M`` such that ``y(0)=y₀`` and for each ``t ∈ [0, T]`` we have
``D_t y(t) = F(y(t), p, t)∘y(t)``, where the ``∘`` is defined as
````math
X∘m = \frac{d}{dt}\vert_{t=0} \exp(tZ)⋅m
````
and ``⋅`` is the group action of ``G`` on ``M``.

!!! note

    Proofs of convergence and order have several assumptions, including time-independence
    of ``F``. Integrators may not work well if these assumptions do not hold.
"""
struct LieODEProblemType end

@doc raw"""
    ExplicitManifoldODEProblemType

An initial value problem manifold ordinary differential equation in the frozen coefficients
formulation by Crouch and Grossman, see [^CrouchGrossman1993].

A frozen coefficients ODE on manifold ``M`` is defined in terms a vector field
``F: (M × P × ℝ) \to T_p M`` where ``p`` is the point given as the third argument to ``F``,
with an initial value ``y₀`` and ``P`` is the space of constant parameters. A solution to
this problem is a curve ``y:ℝ\to M`` such that ``y(0)=y₀`` and for each ``t ∈ [0, T]`` we
have ``D_t y(t) = F(y(t), p, t)``,

!!! note

    Proofs of convergence and order have several assumptions, including time-independence
    of ``F``. Integrators may not work well if these assumptions do not hold.

[^CrouchGrossman1993]:
    > P. E. Crouch and R. Grossman, “Numerical integration of ordinary differential
    > equations on manifolds,” J Nonlinear Sci, vol. 3, no. 1, pp. 1–33, Dec. 1993,
    > doi: [10.1007/BF02429858](https://doi.org/10.1007/BF02429858).

"""
struct ExplicitManifoldODEProblemType end

"""
    ManifoldODEProblem

A general problem for ODE problems on Riemannian manifolds.

# Fields

* `f` the tangent vector field `f(u,p,t)`
* `u0` the initial condition
* `tspan` time interval for the solution
* `p` constant parameters for `f``
* `kwargs` A callback to be applied to every solver which uses the problem.
* `problem_type` type of problem
* `manifold` the manifold the vector field is defined on
"""
struct ManifoldODEProblem{uType,tType,isinplace,P,F,K,PT,TM} <:
       AbstractODEProblem{uType,tType,isinplace}
    f::F
    u0::uType
    tspan::tType
    p::P
    kwargs::K
    problem_type::PT
    manifold::TM
    function ManifoldODEProblem{iip}(
        f::AbstractODEFunction{iip},
        u0,
        tspan,
        manifold::AbstractManifold,
        p = NullParameters(),
        problem_type = ExplicitManifoldODEProblemType();
        kwargs...,
    ) where {iip}
        _tspan = promote_tspan(tspan)
        return new{
            typeof(u0),
            typeof(_tspan),
            isinplace(f),
            typeof(p),
            typeof(f),
            typeof(kwargs),
            typeof(problem_type),
            typeof(manifold),
        }(
            f,
            u0,
            _tspan,
            p,
            kwargs,
            problem_type,
            manifold,
        )
    end

    """
        ManifoldODEProblem{isinplace}(f,u0,tspan,p=NullParameters(),callback=CallbackSet())

    Define an ODE problem with the specified function.
    `isinplace` optionally sets whether the function is inplace or not.
    This is determined automatically, but not inferred.
    """
    function ManifoldODEProblem{iip}(
        f,
        u0,
        tspan,
        manifold::AbstractManifold,
        p = NullParameters();
        kwargs...,
    ) where {iip}
        return ManifoldODEProblem(
            convert(ODEFunction{iip}, f),
            u0,
            tspan,
            manifold,
            p;
            kwargs...,
        )
    end

    function ManifoldODEProblem{iip,recompile}(
        f,
        u0,
        tspan,
        manifold::AbstractManifold,
        p = NullParameters();
        kwargs...,
    ) where {iip,recompile}
        if !recompile
            if iip
                ManifoldODEProblem{iip}(
                    wrapfun_iip(f, (u0, u0, p, tspan[1])),
                    u0,
                    tspan,
                    manifold,
                    p;
                    kwargs...,
                )
            else
                ManifoldODEProblem{iip}(
                    wrapfun_oop(f, (u0, p, tspan[1])),
                    u0,
                    tspan,
                    manifold,
                    p;
                    kwargs...,
                )
            end
        else
            ManifoldODEProblem{iip}(f, u0, tspan, p, manifold; kwargs...)
        end
    end
end

"""
    ManifoldODEProblem(f::ODEFunction, u0, tspan, p=NullParameters(), callback=CallbackSet())

Define an ODE problem from an [`ODEFunction`](@ref).
"""
function ManifoldODEProblem(
    f::AbstractODEFunction,
    u0,
    tspan,
    manifold::AbstractManifold,
    args...;
    kwargs...,
)
    return ManifoldODEProblem{isinplace(f)}(f, u0, tspan, manifold, args...; kwargs...)
end

function ManifoldODEProblem(
    f,
    u0,
    tspan,
    manifold::AbstractManifold,
    p = NullParameters();
    kwargs...,
)
    return ManifoldODEProblem(convert(ODEFunction, f), u0, tspan, manifold, p; kwargs...)
end

function OrdinaryDiffEq.ode_determine_initdt(
    u0,
    t,
    tdir,
    dtmax,
    abstol,
    reltol,
    internalnorm,
    prob::ManifoldODEProblem{uType,tType},
    integrator,
) where {tType,uType}
    _tType = number_eltype(tType)
    oneunit_tType = oneunit(_tType)
    return convert(_tType, oneunit_tType * 1 // 10^(6))
end

function build_solution(
    prob::ManifoldODEProblem,
    alg,
    t,
    u;
    timeseries_errors = length(u) > 2,
    dense = false,
    dense_errors = dense,
    calculate_error = true,
    k = nothing,
    interp::InterpolationData,
    retcode = :Default,
    destats = nothing,
    kwargs...,
)
    T = eltype(eltype(u))

    manifold_interp = ManifoldInterpolationData(
        interp.f,
        interp.timeseries,
        interp.ts,
        interp.ks,
        interp.dense,
        interp.cache,
        prob.manifold,
    )
    return ODESolution{
        T,
        1,
        typeof(u),
        Nothing,
        Nothing,
        typeof(t),
        typeof(k),
        typeof(prob),
        typeof(alg),
        typeof(manifold_interp),
        typeof(destats),
    }(
        u,
        nothing,
        nothing,
        t,
        k,
        prob,
        alg,
        manifold_interp,
        dense,
        0,
        destats,
        retcode,
    )
end


text:
export StandardBasisVector

import Base: *
import LinearAlgebra: dot, transpose, mul!

using LinearAlgebra

@doc raw"""

    StandardBasisVector{T, len, ind}(scale::T)

`StandardBasisVector` creates a standard Cartesian basis vector of zeros of length `len` with a single element `scale` at index `ind`.

An example is the 3-dimensional standard basis vector for the first dimension
```math
e = \begin{bmatrix} 1 \\ 0 \\ 0 \end{bmatrix}
```
Which can be constructed by calling `e = StandardBasisVector(3, 1, 1)`
"""
struct StandardBasisVector{T} <: AbstractVector{T}
    length :: Int
    index  :: Int
    scale  :: T
end

function StandardBasisVector(length::Int, index::Int, scale::T = one(Int)) where { T <: Real }
    @assert length >= 0 && (1 <= index <= length)
    return StandardBasisVector{T}(length, index, scale)
end

Base.eltype(::StandardBasisVector{T})         where { T } = T
Base.eltype(::Type{ StandardBasisVector{T} }) where { T } = T

# extensions of base functionality
Base.size(e::StandardBasisVector)    = (length(e), )
Base.size(e::StandardBasisVector, d) = d::Integer == 1 ? length(e) : 1
Base.length(e::StandardBasisVector)  = e.length

Base.@propagate_inbounds function Base.getindex(e::StandardBasisVector, i::Int)
    @boundscheck checkbounds(e, i)
    return ifelse(getind(e) === i, e.scale, zero(eltype(e)))
end

function Base.show(io::IO, ::MIME"text/plain", e::StandardBasisVector{T}) where { T }
    N = length(e)
    I = getind(e)
    if N < 10
        x = zeros(T, N)
        x[I] = e.scale
        print(io, x)
    else
        if I == 1
            print(io, "[$(e.scale), 0, 0, ...]")
        elseif I == 2
            print(io, "[0, $(e.scale), 0, ...]")
        else
            print(io, "[..., 0, $(e.scale), 0, ...]\n         ^\n         $I")
        end
    end
end

function Base.show(io::IO, e::StandardBasisVector{T}) where { T }
    N = length(e)
    I = getind(e)
    if N < 10
        x = zeros(T, N)
        x[I] = e.scale
        print(io, x)
    else
        compact = get(io, :compact, false)
        if I == 1
            print(io, "[$(e.scale), 0, 0, ...]")
        elseif I == 2
            print(io, "[0, $(e.scale), 0, ...]")
        else
            if compact
                print(io, "[..., 0, $(e.scale), 0, ...]\n         ^\n         $I")
            else
                print(io, "[0, ..., $(e.scale) at index $I, ..., 0]")
            end
        end
    end
end

# get index function
getind(e::StandardBasisVector) = e.index

LinearAlgebra.adjoint(e::S) where { S <: StandardBasisVector } = Adjoint{eltype(S), S}(e)

# standard basis vector - scalar
Base.:*(e::StandardBasisVector, x::Real) = StandardBasisVector(length(e), getind(e), e.scale * x)
Base.:*(x::Real, e::StandardBasisVector) = StandardBasisVector(length(e), getind(e), x * e.scale)

Base.:*(a::Adjoint{T, StandardBasisVector{T}}, x::Real) where { T } = (a' * x)'
Base.:*(x::Real, a::Adjoint{T, StandardBasisVector{T}}) where { T } = (x * a')'

# dot product
function LinearAlgebra.dot(e::StandardBasisVector, v::AbstractVector)
    @assert length(v) === length(e)
    return e.scale * v[ getind(e) ]
end

function LinearAlgebra.dot(v::AbstractVector, e::StandardBasisVector)
    @assert length(v) === length(e)
    return v[ getind(e) ] * e.scale
end

function LinearAlgebra.dot(e1::StandardBasisVector{T1}, e2::StandardBasisVector{T2}) where { T1, T2 }
    @assert length(e1) === length(e2)
    T = promote_type(T1, T2)
    return ifelse(getind(e1) === getind(e2), convert(T, e1.scale * e2.scale), zero(T))::T
end

function LinearAlgebra.dot(e1::StandardBasisVector, A::AbstractMatrix, e2::StandardBasisVector)
    @assert size(A) == (length(e1), length(e2))
    return e1.scale * A[ getind(e1), getind(e2) ] * e2.scale
end

# vector - vector
function Base.:*(v::AbstractVector{T1}, a::Adjoint{T2, StandardBasisVector{T2}}) where { T1 <: Real, T2 <: Real }
    parent = a'
    N = length(parent)
    I = getind(parent)
    T  = promote_type(T1, T2)
    lv = length(v)
    s  = parent.scale
    result = zeros(T, lv, N)
    @inbounds @simd for k in 1:lv
        result[k, I] = v[k] * s
    end
    return result
end

function Base.:*(v::StandardBasisVector{T1}, a::Adjoint{T2, StandardBasisVector{T2}}) where { T1 <: Real, T2 <: Real }
    T  = promote_type(T1, T2)
    N1 = length(v)
    I1 = getind(v)
    p2 = a'
    N2 = length(p2)
    I2 = getind(p2)
    s  = p2.scale
    result = zeros(T, N1, N2)
    result[I1, I2] = v.scale * s
    return result
end

function Base.:*(e::StandardBasisVector{T1}, a::Adjoint{T2, <: AbstractVector{T2}}) where { T1 <: Real, T2 <: Real }
    N  = length(e)
    I  = getind(e)
    T  = promote_type(T1, T2)
    lv = length(a)
    s  = e.scale
    result = zeros(T, N, lv)
    @inbounds @simd for k in 1:lv
        result[I, k] = s * a[k]
    end
    return result
end

function Base.:*(v::Adjoint{T1, <:AbstractVector{T1}}, e::StandardBasisVector{T2}) where { T1 <: Real, T2 <: Real }
    @assert length(v) === length(e)
    return v[ getind(e) ] * e.scale
end

# vector matrix
function Base.:*(A::AbstractMatrix, e::StandardBasisVector)
    @assert size(A, 2) === length(e)
    v = A[:, getind(e)]
    v = mul_inplace!(e.scale, v)
    return v
end

function Base.:*(A::Adjoint{T, <:AbstractMatrix{T}}, e::StandardBasisVector) where { T <: Real }
    @assert size(A, 2) === length(e)
    v = A[:, getind(e)]
    v = mul_inplace!(e.scale, v)
    return v
end

function Base.:*(A::AbstractMatrix{T1}, a::Adjoint{T2, StandardBasisVector{T2}}) where { T2 <: Real, T1 <: Real }
    sA = size(A)
    @assert sA[2] === 1
    p      = a'
    N      = length(p)
    I      = getind(p)
    T      = promote_type(T1, T2)
    s      = p.scale
    result = zeros(T, sA[1], N)
    @inbounds @simd for k in 1:sA[1]
        result[k, I] = A[k] * s
    end
    return result
end

function Base.:*(e::StandardBasisVector{T1}, A::AbstractMatrix{T2}) where { T1 <: Real, T2 <: Real }
    sA = size(A)
    @assert sA[1] === 1
    N      = length(e)
    I      = getind(e)
    T      = promote_type(T1, T2)
    s      = e.scale
    result = zeros(T, N, sA[2])
    @inbounds @simd for k in 1:sA[2]
        result[I, k] = s * A[k]
    end
    return result
end

function Base.:*(e::StandardBasisVector, A::Adjoint{T, <: AbstractMatrix{T}}) where { T <: Real }
    @assert size(A, 2) === length(e)
    v = A[:, getind(e)]
    v = mul_inplace!(e.scale, v)
    return v
end

# custom
function v_a_vT(e1::StandardBasisVector{T1}, a::T3, e2::StandardBasisVector{T2}) where { T1 <: Real, T2 <: Real, T3 <: Real }

    T = promote_type(T1, T3, T2)
    Y = zeros(T, length(e1), length(e2))
    Y[getind(e1), getind(e2)] = e1.scale * a * e2.scale

    # return output
    return Y

end

function v_a_vT(e::StandardBasisVector{T1}, a::T2) where { T1 <: Real, T2 <: Real }

    N = length(e)
    I = getind(e)
    T = promote_type(T1, T2)
    Y = zeros(T, N, N)
    Y[I, I] = e.scale * a * e.scale

    # return output
    return Y

end


text:
struct Piecewise{T, B, VT<:AbstractVector{T}, VB<:AbstractVector{B}}
    subfunctions::VT
    breaks::VB
    clamp::Bool

    function Piecewise(subfunctions::VT, breaks::VB; clamp::Bool=true) where {T, B, VT<:AbstractVector{T}, VB<:AbstractVector{B}}
        @assert issorted(breaks)
        @assert length(breaks) == length(subfunctions) + 1
        new{T, B, VT, VB}(subfunctions, breaks, clamp)
    end
end

function (traj::Piecewise)(x, args...)
    breaks = traj.breaks
    subfunctions = traj.subfunctions
    x0, xf = first(breaks), last(breaks)
    x′ = if traj.clamp
        clamp(x, x0, xf)
    else
        (x < x0 || x > xf) && throw_trajectory_domain_error(x, x0, xf)
        x
    end
    index = min(searchsortedlast(breaks, x′), length(subfunctions))
    @inbounds xbreak = breaks[index]
    @inbounds subtraj = traj.subfunctions[index]
    return subtraj(x′ - xbreak, args...)
end

subfunctions(traj::Piecewise) = traj.subfunctions
breaks(traj::Piecewise) = traj.breaks


text:
# first create the individual plot containers
p1=FramedPlot("xlabel","time","ylabel","R")
p2=FramedPlot("xlabel","time","ylabel","L")
p3=FramedPlot("xlabel","time","ylabel","RL")

# add the different plot types to the containers
# first points
add(p1,Points(time,R,"type","diamond", "color","blue"))
add(p2,Points(time,L,"type","circle", "color","blue"))
add(p3,Points(time,RL,"type","cross", "color","blue"))

# then line plots
add(p1,Curve(time,R, "color","blue"))
add(p2,Curve(time,L, "color","blue"))
add(p3,Curve(time,RL, "color","blue"))

# finally, create a Table with 1 row and 3 columns
t = Table(1,3)
# and add the different FramedPlot
# containers to the Table elements
# (which is somewhat similar in style to MATLAB subplots)
t[1,1] = p1
t[1,2] = p2
t[1,3] = p3

# The figure width and height can be
# changed when creating the graphics file
file(t,"julia_rlbinding_subplot.png","width",800,"height",400)