/*
 * Jellyfin API
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 *
 * The version of the OpenAPI document: 10.11.6
 * 
 *
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */

package org.openhab.binding.jellyfin.internal.gen.current.model;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.UUID;

import com.fasterxml.jackson.annotation.JsonProperty;

/**
 * Session info DTO.
 */
@jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "OpenAPI Generator")
public class SessionInfoDto {
    public static final String JSON_PROPERTY_PLAY_STATE = "PlayState";
    private @org.eclipse.jdt.annotation.Nullable PlayerStateInfo playState;

    public static final String JSON_PROPERTY_ADDITIONAL_USERS = "AdditionalUsers";
    private @org.eclipse.jdt.annotation.Nullable List<SessionUserInfo> additionalUsers;

    public static final String JSON_PROPERTY_CAPABILITIES = "Capabilities";
    private @org.eclipse.jdt.annotation.Nullable ClientCapabilitiesDto capabilities;

    public static final String JSON_PROPERTY_REMOTE_END_POINT = "RemoteEndPoint";
    private @org.eclipse.jdt.annotation.Nullable String remoteEndPoint;

    public static final String JSON_PROPERTY_PLAYABLE_MEDIA_TYPES = "PlayableMediaTypes";
    private @org.eclipse.jdt.annotation.Nullable List<MediaType> playableMediaTypes = new ArrayList<>();

    public static final String JSON_PROPERTY_ID = "Id";
    private @org.eclipse.jdt.annotation.Nullable String id;

    public static final String JSON_PROPERTY_USER_ID = "UserId";
    private @org.eclipse.jdt.annotation.Nullable UUID userId;

    public static final String JSON_PROPERTY_USER_NAME = "UserName";
    private @org.eclipse.jdt.annotation.Nullable String userName;

    public static final String JSON_PROPERTY_CLIENT = "Client";
    private @org.eclipse.jdt.annotation.Nullable String client;

    public static final String JSON_PROPERTY_LAST_ACTIVITY_DATE = "LastActivityDate";
    private @org.eclipse.jdt.annotation.Nullable OffsetDateTime lastActivityDate;

    public static final String JSON_PROPERTY_LAST_PLAYBACK_CHECK_IN = "LastPlaybackCheckIn";
    private @org.eclipse.jdt.annotation.Nullable OffsetDateTime lastPlaybackCheckIn;

    public static final String JSON_PROPERTY_LAST_PAUSED_DATE = "LastPausedDate";
    private @org.eclipse.jdt.annotation.Nullable OffsetDateTime lastPausedDate;

    public static final String JSON_PROPERTY_DEVICE_NAME = "DeviceName";
    private @org.eclipse.jdt.annotation.Nullable String deviceName;

    public static final String JSON_PROPERTY_DEVICE_TYPE = "DeviceType";
    private @org.eclipse.jdt.annotation.Nullable String deviceType;

    public static final String JSON_PROPERTY_NOW_PLAYING_ITEM = "NowPlayingItem";
    private @org.eclipse.jdt.annotation.Nullable BaseItemDto nowPlayingItem;

    public static final String JSON_PROPERTY_NOW_VIEWING_ITEM = "NowViewingItem";
    private @org.eclipse.jdt.annotation.Nullable BaseItemDto nowViewingItem;

    public static final String JSON_PROPERTY_DEVICE_ID = "DeviceId";
    private @org.eclipse.jdt.annotation.Nullable String deviceId;

    public static final String JSON_PROPERTY_APPLICATION_VERSION = "ApplicationVersion";
    private @org.eclipse.jdt.annotation.Nullable String applicationVersion;

    public static final String JSON_PROPERTY_TRANSCODING_INFO = "TranscodingInfo";
    private @org.eclipse.jdt.annotation.Nullable TranscodingInfo transcodingInfo;

    public static final String JSON_PROPERTY_IS_ACTIVE = "IsActive";
    private @org.eclipse.jdt.annotation.Nullable Boolean isActive;

    public static final String JSON_PROPERTY_SUPPORTS_MEDIA_CONTROL = "SupportsMediaControl";
    private @org.eclipse.jdt.annotation.Nullable Boolean supportsMediaControl;

    public static final String JSON_PROPERTY_SUPPORTS_REMOTE_CONTROL = "SupportsRemoteControl";
    private @org.eclipse.jdt.annotation.Nullable Boolean supportsRemoteControl;

    public static final String JSON_PROPERTY_NOW_PLAYING_QUEUE = "NowPlayingQueue";
    private @org.eclipse.jdt.annotation.Nullable List<QueueItem> nowPlayingQueue;

    public static final String JSON_PROPERTY_NOW_PLAYING_QUEUE_FULL_ITEMS = "NowPlayingQueueFullItems";
    private @org.eclipse.jdt.annotation.Nullable List<BaseItemDto> nowPlayingQueueFullItems;

    public static final String JSON_PROPERTY_HAS_CUSTOM_DEVICE_NAME = "HasCustomDeviceName";
    private @org.eclipse.jdt.annotation.Nullable Boolean hasCustomDeviceName;

    public static final String JSON_PROPERTY_PLAYLIST_ITEM_ID = "PlaylistItemId";
    private @org.eclipse.jdt.annotation.Nullable String playlistItemId;

    public static final String JSON_PROPERTY_SERVER_ID = "ServerId";
    private @org.eclipse.jdt.annotation.Nullable String serverId;

    public static final String JSON_PROPERTY_USER_PRIMARY_IMAGE_TAG = "UserPrimaryImageTag";
    private @org.eclipse.jdt.annotation.Nullable String userPrimaryImageTag;

    public static final String JSON_PROPERTY_SUPPORTED_COMMANDS = "SupportedCommands";
    private @org.eclipse.jdt.annotation.Nullable List<GeneralCommandType> supportedCommands = new ArrayList<>();

    public SessionInfoDto() {
    }

    public SessionInfoDto playState(@org.eclipse.jdt.annotation.Nullable PlayerStateInfo playState) {
        this.playState = playState;
        return this;
    }

    /**
     * Gets or sets the play state.
     * 
     * @return playState
     */
    @JsonProperty(value = JSON_PROPERTY_PLAY_STATE)
    public @org.eclipse.jdt.annotation.Nullable PlayerStateInfo getPlayState() {
        return playState;
    }

    @JsonProperty(value = JSON_PROPERTY_PLAY_STATE)
    public void setPlayState(@org.eclipse.jdt.annotation.Nullable PlayerStateInfo playState) {
        this.playState = playState;
    }

    public SessionInfoDto additionalUsers(@org.eclipse.jdt.annotation.Nullable List<SessionUserInfo> additionalUsers) {
        this.additionalUsers = additionalUsers;
        return this;
    }

    public SessionInfoDto addAdditionalUsersItem(SessionUserInfo additionalUsersItem) {
        if (this.additionalUsers == null) {
            this.additionalUsers = new ArrayList<>();
        }
        this.additionalUsers.add(additionalUsersItem);
        return this;
    }

    /**
     * Gets or sets the additional users.
     * 
     * @return additionalUsers
     */
    @JsonProperty(value = JSON_PROPERTY_ADDITIONAL_USERS)
    public @org.eclipse.jdt.annotation.Nullable List<SessionUserInfo> getAdditionalUsers() {
        return additionalUsers;
    }

    @JsonProperty(value = JSON_PROPERTY_ADDITIONAL_USERS)
    public void setAdditionalUsers(@org.eclipse.jdt.annotation.Nullable List<SessionUserInfo> additionalUsers) {
        this.additionalUsers = additionalUsers;
    }

    public SessionInfoDto capabilities(@org.eclipse.jdt.annotation.Nullable ClientCapabilitiesDto capabilities) {
        this.capabilities = capabilities;
        return this;
    }

    /**
     * Gets or sets the client capabilities.
     * 
     * @return capabilities
     */
    @JsonProperty(value = JSON_PROPERTY_CAPABILITIES)
    public @org.eclipse.jdt.annotation.Nullable ClientCapabilitiesDto getCapabilities() {
        return capabilities;
    }

    @JsonProperty(value = JSON_PROPERTY_CAPABILITIES)
    public void setCapabilities(@org.eclipse.jdt.annotation.Nullable ClientCapabilitiesDto capabilities) {
        this.capabilities = capabilities;
    }

    public SessionInfoDto remoteEndPoint(@org.eclipse.jdt.annotation.Nullable String remoteEndPoint) {
        this.remoteEndPoint = remoteEndPoint;
        return this;
    }

    /**
     * Gets or sets the remote end point.
     * 
     * @return remoteEndPoint
     */
    @JsonProperty(value = JSON_PROPERTY_REMOTE_END_POINT)
    public @org.eclipse.jdt.annotation.Nullable String getRemoteEndPoint() {
        return remoteEndPoint;
    }

    @JsonProperty(value = JSON_PROPERTY_REMOTE_END_POINT)
    public void setRemoteEndPoint(@org.eclipse.jdt.annotation.Nullable String remoteEndPoint) {
        this.remoteEndPoint = remoteEndPoint;
    }

    public SessionInfoDto playableMediaTypes(@org.eclipse.jdt.annotation.Nullable List<MediaType> playableMediaTypes) {
        this.playableMediaTypes = playableMediaTypes;
        return this;
    }

    public SessionInfoDto addPlayableMediaTypesItem(MediaType playableMediaTypesItem) {
        if (this.playableMediaTypes == null) {
            this.playableMediaTypes = new ArrayList<>();
        }
        this.playableMediaTypes.add(playableMediaTypesItem);
        return this;
    }

    /**
     * Gets or sets the playable media types.
     * 
     * @return playableMediaTypes
     */
    @JsonProperty(value = JSON_PROPERTY_PLAYABLE_MEDIA_TYPES)
    public @org.eclipse.jdt.annotation.Nullable List<MediaType> getPlayableMediaTypes() {
        return playableMediaTypes;
    }

    @JsonProperty(value = JSON_PROPERTY_PLAYABLE_MEDIA_TYPES)
    public void setPlayableMediaTypes(@org.eclipse.jdt.annotation.Nullable List<MediaType> playableMediaTypes) {
        this.playableMediaTypes = playableMediaTypes;
    }

    public SessionInfoDto id(@org.eclipse.jdt.annotation.Nullable String id) {
        this.id = id;
        return this;
    }

    /**
     * Gets or sets the id.
     * 
     * @return id
     */
    @JsonProperty(value = JSON_PROPERTY_ID)
    public @org.eclipse.jdt.annotation.Nullable String getId() {
        return id;
    }

    @JsonProperty(value = JSON_PROPERTY_ID)
    public void setId(@org.eclipse.jdt.annotation.Nullable String id) {
        this.id = id;
    }

    public SessionInfoDto userId(@org.eclipse.jdt.annotation.Nullable UUID userId) {
        this.userId = userId;
        return this;
    }

    /**
     * Gets or sets the user id.
     * 
     * @return userId
     */
    @JsonProperty(value = JSON_PROPERTY_USER_ID)
    public @org.eclipse.jdt.annotation.Nullable UUID getUserId() {
        return userId;
    }

    @JsonProperty(value = JSON_PROPERTY_USER_ID)
    public void setUserId(@org.eclipse.jdt.annotation.Nullable UUID userId) {
        this.userId = userId;
    }

    public SessionInfoDto userName(@org.eclipse.jdt.annotation.Nullable String userName) {
        this.userName = userName;
        return this;
    }

    /**
     * Gets or sets the username.
     * 
     * @return userName
     */
    @JsonProperty(value = JSON_PROPERTY_USER_NAME)
    public @org.eclipse.jdt.annotation.Nullable String getUserName() {
        return userName;
    }

    @JsonProperty(value = JSON_PROPERTY_USER_NAME)
    public void setUserName(@org.eclipse.jdt.annotation.Nullable String userName) {
        this.userName = userName;
    }

    public SessionInfoDto client(@org.eclipse.jdt.annotation.Nullable String client) {
        this.client = client;
        return this;
    }

    /**
     * Gets or sets the type of the client.
     * 
     * @return client
     */
    @JsonProperty(value = JSON_PROPERTY_CLIENT)
    public @org.eclipse.jdt.annotation.Nullable String getClient() {
        return client;
    }

    @JsonProperty(value = JSON_PROPERTY_CLIENT)
    public void setClient(@org.eclipse.jdt.annotation.Nullable String client) {
        this.client = client;
    }

    public SessionInfoDto lastActivityDate(@org.eclipse.jdt.annotation.Nullable OffsetDateTime lastActivityDate) {
        this.lastActivityDate = lastActivityDate;
        return this;
    }

    /**
     * Gets or sets the last activity date.
     * 
     * @return lastActivityDate
     */
    @JsonProperty(value = JSON_PROPERTY_LAST_ACTIVITY_DATE)
    public @org.eclipse.jdt.annotation.Nullable OffsetDateTime getLastActivityDate() {
        return lastActivityDate;
    }

    @JsonProperty(value = JSON_PROPERTY_LAST_ACTIVITY_DATE)
    public void setLastActivityDate(@org.eclipse.jdt.annotation.Nullable OffsetDateTime lastActivityDate) {
        this.lastActivityDate = lastActivityDate;
    }

    public SessionInfoDto lastPlaybackCheckIn(@org.eclipse.jdt.annotation.Nullable OffsetDateTime lastPlaybackCheckIn) {
        this.lastPlaybackCheckIn = lastPlaybackCheckIn;
        return this;
    }

    /**
     * Gets or sets the last playback check in.
     * 
     * @return lastPlaybackCheckIn
     */
    @JsonProperty(value = JSON_PROPERTY_LAST_PLAYBACK_CHECK_IN)
    public @org.eclipse.jdt.annotation.Nullable OffsetDateTime getLastPlaybackCheckIn() {
        return lastPlaybackCheckIn;
    }

    @JsonProperty(value = JSON_PROPERTY_LAST_PLAYBACK_CHECK_IN)
    public void setLastPlaybackCheckIn(@org.eclipse.jdt.annotation.Nullable OffsetDateTime lastPlaybackCheckIn) {
        this.lastPlaybackCheckIn = lastPlaybackCheckIn;
    }

    public SessionInfoDto lastPausedDate(@org.eclipse.jdt.annotation.Nullable OffsetDateTime lastPausedDate) {
        this.lastPausedDate = lastPausedDate;
        return this;
    }

    /**
     * Gets or sets the last paused date.
     * 
     * @return lastPausedDate
     */
    @JsonProperty(value = JSON_PROPERTY_LAST_PAUSED_DATE)
    public @org.eclipse.jdt.annotation.Nullable OffsetDateTime getLastPausedDate() {
        return lastPausedDate;
    }

    @JsonProperty(value = JSON_PROPERTY_LAST_PAUSED_DATE)
    public void setLastPausedDate(@org.eclipse.jdt.annotation.Nullable OffsetDateTime lastPausedDate) {
        this.lastPausedDate = lastPausedDate;
    }

    public SessionInfoDto deviceName(@org.eclipse.jdt.annotation.Nullable String deviceName) {
        this.deviceName = deviceName;
        return this;
    }

    /**
     * Gets or sets the name of the device.
     * 
     * @return deviceName
     */
    @JsonProperty(value = JSON_PROPERTY_DEVICE_NAME)
    public @org.eclipse.jdt.annotation.Nullable String getDeviceName() {
        return deviceName;
    }

    @JsonProperty(value = JSON_PROPERTY_DEVICE_NAME)
    public void setDeviceName(@org.eclipse.jdt.annotation.Nullable String deviceName) {
        this.deviceName = deviceName;
    }

    public SessionInfoDto deviceType(@org.eclipse.jdt.annotation.Nullable String deviceType) {
        this.deviceType = deviceType;
        return this;
    }

    /**
     * Gets or sets the type of the device.
     * 
     * @return deviceType
     */
    @JsonProperty(value = JSON_PROPERTY_DEVICE_TYPE)
    public @org.eclipse.jdt.annotation.Nullable String getDeviceType() {
        return deviceType;
    }

    @JsonProperty(value = JSON_PROPERTY_DEVICE_TYPE)
    public void setDeviceType(@org.eclipse.jdt.annotation.Nullable String deviceType) {
        this.deviceType = deviceType;
    }

    public SessionInfoDto nowPlayingItem(@org.eclipse.jdt.annotation.Nullable BaseItemDto nowPlayingItem) {
        this.nowPlayingItem = nowPlayingItem;
        return this;
    }

    /**
     * Gets or sets the now playing item.
     * 
     * @return nowPlayingItem
     */
    @JsonProperty(value = JSON_PROPERTY_NOW_PLAYING_ITEM)
    public @org.eclipse.jdt.annotation.Nullable BaseItemDto getNowPlayingItem() {
        return nowPlayingItem;
    }

    @JsonProperty(value = JSON_PROPERTY_NOW_PLAYING_ITEM)
    public void setNowPlayingItem(@org.eclipse.jdt.annotation.Nullable BaseItemDto nowPlayingItem) {
        this.nowPlayingItem = nowPlayingItem;
    }

    public SessionInfoDto nowViewingItem(@org.eclipse.jdt.annotation.Nullable BaseItemDto nowViewingItem) {
        this.nowViewingItem = nowViewingItem;
        return this;
    }

    /**
     * Gets or sets the now viewing item.
     * 
     * @return nowViewingItem
     */
    @JsonProperty(value = JSON_PROPERTY_NOW_VIEWING_ITEM)
    public @org.eclipse.jdt.annotation.Nullable BaseItemDto getNowViewingItem() {
        return nowViewingItem;
    }

    @JsonProperty(value = JSON_PROPERTY_NOW_VIEWING_ITEM)
    public void setNowViewingItem(@org.eclipse.jdt.annotation.Nullable BaseItemDto nowViewingItem) {
        this.nowViewingItem = nowViewingItem;
    }

    public SessionInfoDto deviceId(@org.eclipse.jdt.annotation.Nullable String deviceId) {
        this.deviceId = deviceId;
        return this;
    }

    /**
     * Gets or sets the device id.
     * 
     * @return deviceId
     */
    @JsonProperty(value = JSON_PROPERTY_DEVICE_ID)
    public @org.eclipse.jdt.annotation.Nullable String getDeviceId() {
        return deviceId;
    }

    @JsonProperty(value = JSON_PROPERTY_DEVICE_ID)
    public void setDeviceId(@org.eclipse.jdt.annotation.Nullable String deviceId) {
        this.deviceId = deviceId;
    }

    public SessionInfoDto applicationVersion(@org.eclipse.jdt.annotation.Nullable String applicationVersion) {
        this.applicationVersion = applicationVersion;
        return this;
    }

    /**
     * Gets or sets the application version.
     * 
     * @return applicationVersion
     */
    @JsonProperty(value = JSON_PROPERTY_APPLICATION_VERSION)
    public @org.eclipse.jdt.annotation.Nullable String getApplicationVersion() {
        return applicationVersion;
    }

    @JsonProperty(value = JSON_PROPERTY_APPLICATION_VERSION)
    public void setApplicationVersion(@org.eclipse.jdt.annotation.Nullable String applicationVersion) {
        this.applicationVersion = applicationVersion;
    }

    public SessionInfoDto transcodingInfo(@org.eclipse.jdt.annotation.Nullable TranscodingInfo transcodingInfo) {
        this.transcodingInfo = transcodingInfo;
        return this;
    }

    /**
     * Gets or sets the transcoding info.
     * 
     * @return transcodingInfo
     */
    @JsonProperty(value = JSON_PROPERTY_TRANSCODING_INFO)
    public @org.eclipse.jdt.annotation.Nullable TranscodingInfo getTranscodingInfo() {
        return transcodingInfo;
    }

    @JsonProperty(value = JSON_PROPERTY_TRANSCODING_INFO)
    public void setTranscodingInfo(@org.eclipse.jdt.annotation.Nullable TranscodingInfo transcodingInfo) {
        this.transcodingInfo = transcodingInfo;
    }

    public SessionInfoDto isActive(@org.eclipse.jdt.annotation.Nullable Boolean isActive) {
        this.isActive = isActive;
        return this;
    }

    /**
     * Gets or sets a value indicating whether this session is active.
     * 
     * @return isActive
     */
    @JsonProperty(value = JSON_PROPERTY_IS_ACTIVE)
    public @org.eclipse.jdt.annotation.Nullable Boolean getIsActive() {
        return isActive;
    }

    @JsonProperty(value = JSON_PROPERTY_IS_ACTIVE)
    public void setIsActive(@org.eclipse.jdt.annotation.Nullable Boolean isActive) {
        this.isActive = isActive;
    }

    public SessionInfoDto supportsMediaControl(@org.eclipse.jdt.annotation.Nullable Boolean supportsMediaControl) {
        this.supportsMediaControl = supportsMediaControl;
        return this;
    }

    /**
     * Gets or sets a value indicating whether the session supports media control.
     * 
     * @return supportsMediaControl
     */
    @JsonProperty(value = JSON_PROPERTY_SUPPORTS_MEDIA_CONTROL)
    public @org.eclipse.jdt.annotation.Nullable Boolean getSupportsMediaControl() {
        return supportsMediaControl;
    }

    @JsonProperty(value = JSON_PROPERTY_SUPPORTS_MEDIA_CONTROL)
    public void setSupportsMediaControl(@org.eclipse.jdt.annotation.Nullable Boolean supportsMediaControl) {
        this.supportsMediaControl = supportsMediaControl;
    }

    public SessionInfoDto supportsRemoteControl(@org.eclipse.jdt.annotation.Nullable Boolean supportsRemoteControl) {
        this.supportsRemoteControl = supportsRemoteControl;
        return this;
    }

    /**
     * Gets or sets a value indicating whether the session supports remote control.
     * 
     * @return supportsRemoteControl
     */
    @JsonProperty(value = JSON_PROPERTY_SUPPORTS_REMOTE_CONTROL)
    public @org.eclipse.jdt.annotation.Nullable Boolean getSupportsRemoteControl() {
        return supportsRemoteControl;
    }

    @JsonProperty(value = JSON_PROPERTY_SUPPORTS_REMOTE_CONTROL)
    public void setSupportsRemoteControl(@org.eclipse.jdt.annotation.Nullable Boolean supportsRemoteControl) {
        this.supportsRemoteControl = supportsRemoteControl;
    }

    public SessionInfoDto nowPlayingQueue(@org.eclipse.jdt.annotation.Nullable List<QueueItem> nowPlayingQueue) {
        this.nowPlayingQueue = nowPlayingQueue;
        return this;
    }

    public SessionInfoDto addNowPlayingQueueItem(QueueItem nowPlayingQueueItem) {
        if (this.nowPlayingQueue == null) {
            this.nowPlayingQueue = new ArrayList<>();
        }
        this.nowPlayingQueue.add(nowPlayingQueueItem);
        return this;
    }

    /**
     * Gets or sets the now playing queue.
     * 
     * @return nowPlayingQueue
     */
    @JsonProperty(value = JSON_PROPERTY_NOW_PLAYING_QUEUE)
    public @org.eclipse.jdt.annotation.Nullable List<QueueItem> getNowPlayingQueue() {
        return nowPlayingQueue;
    }

    @JsonProperty(value = JSON_PROPERTY_NOW_PLAYING_QUEUE)
    public void setNowPlayingQueue(@org.eclipse.jdt.annotation.Nullable List<QueueItem> nowPlayingQueue) {
        this.nowPlayingQueue = nowPlayingQueue;
    }

    public SessionInfoDto nowPlayingQueueFullItems(
            @org.eclipse.jdt.annotation.Nullable List<BaseItemDto> nowPlayingQueueFullItems) {
        this.nowPlayingQueueFullItems = nowPlayingQueueFullItems;
        return this;
    }

    public SessionInfoDto addNowPlayingQueueFullItemsItem(BaseItemDto nowPlayingQueueFullItemsItem) {
        if (this.nowPlayingQueueFullItems == null) {
            this.nowPlayingQueueFullItems = new ArrayList<>();
        }
        this.nowPlayingQueueFullItems.add(nowPlayingQueueFullItemsItem);
        return this;
    }

    /**
     * Gets or sets the now playing queue full items.
     * 
     * @return nowPlayingQueueFullItems
     */
    @JsonProperty(value = JSON_PROPERTY_NOW_PLAYING_QUEUE_FULL_ITEMS)
    public @org.eclipse.jdt.annotation.Nullable List<BaseItemDto> getNowPlayingQueueFullItems() {
        return nowPlayingQueueFullItems;
    }

    @JsonProperty(value = JSON_PROPERTY_NOW_PLAYING_QUEUE_FULL_ITEMS)
    public void setNowPlayingQueueFullItems(
            @org.eclipse.jdt.annotation.Nullable List<BaseItemDto> nowPlayingQueueFullItems) {
        this.nowPlayingQueueFullItems = nowPlayingQueueFullItems;
    }

    public SessionInfoDto hasCustomDeviceName(@org.eclipse.jdt.annotation.Nullable Boolean hasCustomDeviceName) {
        this.hasCustomDeviceName = hasCustomDeviceName;
        return this;
    }

    /**
     * Gets or sets a value indicating whether the session has a custom device name.
     * 
     * @return hasCustomDeviceName
     */
    @JsonProperty(value = JSON_PROPERTY_HAS_CUSTOM_DEVICE_NAME)
    public @org.eclipse.jdt.annotation.Nullable Boolean getHasCustomDeviceName() {
        return hasCustomDeviceName;
    }

    @JsonProperty(value = JSON_PROPERTY_HAS_CUSTOM_DEVICE_NAME)
    public void setHasCustomDeviceName(@org.eclipse.jdt.annotation.Nullable Boolean hasCustomDeviceName) {
        this.hasCustomDeviceName = hasCustomDeviceName;
    }

    public SessionInfoDto playlistItemId(@org.eclipse.jdt.annotation.Nullable String playlistItemId) {
        this.playlistItemId = playlistItemId;
        return this;
    }

    /**
     * Gets or sets the playlist item id.
     * 
     * @return playlistItemId
     */
    @JsonProperty(value = JSON_PROPERTY_PLAYLIST_ITEM_ID)
    public @org.eclipse.jdt.annotation.Nullable String getPlaylistItemId() {
        return playlistItemId;
    }

    @JsonProperty(value = JSON_PROPERTY_PLAYLIST_ITEM_ID)
    public void setPlaylistItemId(@org.eclipse.jdt.annotation.Nullable String playlistItemId) {
        this.playlistItemId = playlistItemId;
    }

    public SessionInfoDto serverId(@org.eclipse.jdt.annotation.Nullable String serverId) {
        this.serverId = serverId;
        return this;
    }

    /**
     * Gets or sets the server id.
     * 
     * @return serverId
     */
    @JsonProperty(value = JSON_PROPERTY_SERVER_ID)
    public @org.eclipse.jdt.annotation.Nullable String getServerId() {
        return serverId;
    }

    @JsonProperty(value = JSON_PROPERTY_SERVER_ID)
    public void setServerId(@org.eclipse.jdt.annotation.Nullable String serverId) {
        this.serverId = serverId;
    }

    public SessionInfoDto userPrimaryImageTag(@org.eclipse.jdt.annotation.Nullable String userPrimaryImageTag) {
        this.userPrimaryImageTag = userPrimaryImageTag;
        return this;
    }

    /**
     * Gets or sets the user primary image tag.
     * 
     * @return userPrimaryImageTag
     */
    @JsonProperty(value = JSON_PROPERTY_USER_PRIMARY_IMAGE_TAG)
    public @org.eclipse.jdt.annotation.Nullable String getUserPrimaryImageTag() {
        return userPrimaryImageTag;
    }

    @JsonProperty(value = JSON_PROPERTY_USER_PRIMARY_IMAGE_TAG)
    public void setUserPrimaryImageTag(@org.eclipse.jdt.annotation.Nullable String userPrimaryImageTag) {
        this.userPrimaryImageTag = userPrimaryImageTag;
    }

    public SessionInfoDto supportedCommands(
            @org.eclipse.jdt.annotation.Nullable List<GeneralCommandType> supportedCommands) {
        this.supportedCommands = supportedCommands;
        return this;
    }

    public SessionInfoDto addSupportedCommandsItem(GeneralCommandType supportedCommandsItem) {
        if (this.supportedCommands == null) {
            this.supportedCommands = new ArrayList<>();
        }
        this.supportedCommands.add(supportedCommandsItem);
        return this;
    }

    /**
     * Gets or sets the supported commands.
     * 
     * @return supportedCommands
     */
    @JsonProperty(value = JSON_PROPERTY_SUPPORTED_COMMANDS)
    public @org.eclipse.jdt.annotation.Nullable List<GeneralCommandType> getSupportedCommands() {
        return supportedCommands;
    }

    @JsonProperty(value = JSON_PROPERTY_SUPPORTED_COMMANDS)
    public void setSupportedCommands(@org.eclipse.jdt.annotation.Nullable List<GeneralCommandType> supportedCommands) {
        this.supportedCommands = supportedCommands;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        SessionInfoDto sessionInfoDto = (SessionInfoDto) o;
        return Objects.equals(this.playState, sessionInfoDto.playState)
                && Objects.equals(this.additionalUsers, sessionInfoDto.additionalUsers)
                && Objects.equals(this.capabilities, sessionInfoDto.capabilities)
                && Objects.equals(this.remoteEndPoint, sessionInfoDto.remoteEndPoint)
                && Objects.equals(this.playableMediaTypes, sessionInfoDto.playableMediaTypes)
                && Objects.equals(this.id, sessionInfoDto.id) && Objects.equals(this.userId, sessionInfoDto.userId)
                && Objects.equals(this.userName, sessionInfoDto.userName)
                && Objects.equals(this.client, sessionInfoDto.client)
                && Objects.equals(this.lastActivityDate, sessionInfoDto.lastActivityDate)
                && Objects.equals(this.lastPlaybackCheckIn, sessionInfoDto.lastPlaybackCheckIn)
                && Objects.equals(this.lastPausedDate, sessionInfoDto.lastPausedDate)
                && Objects.equals(this.deviceName, sessionInfoDto.deviceName)
                && Objects.equals(this.deviceType, sessionInfoDto.deviceType)
                && Objects.equals(this.nowPlayingItem, sessionInfoDto.nowPlayingItem)
                && Objects.equals(this.nowViewingItem, sessionInfoDto.nowViewingItem)
                && Objects.equals(this.deviceId, sessionInfoDto.deviceId)
                && Objects.equals(this.applicationVersion, sessionInfoDto.applicationVersion)
                && Objects.equals(this.transcodingInfo, sessionInfoDto.transcodingInfo)
                && Objects.equals(this.isActive, sessionInfoDto.isActive)
                && Objects.equals(this.supportsMediaControl, sessionInfoDto.supportsMediaControl)
                && Objects.equals(this.supportsRemoteControl, sessionInfoDto.supportsRemoteControl)
                && Objects.equals(this.nowPlayingQueue, sessionInfoDto.nowPlayingQueue)
                && Objects.equals(this.nowPlayingQueueFullItems, sessionInfoDto.nowPlayingQueueFullItems)
                && Objects.equals(this.hasCustomDeviceName, sessionInfoDto.hasCustomDeviceName)
                && Objects.equals(this.playlistItemId, sessionInfoDto.playlistItemId)
                && Objects.equals(this.serverId, sessionInfoDto.serverId)
                && Objects.equals(this.userPrimaryImageTag, sessionInfoDto.userPrimaryImageTag)
                && Objects.equals(this.supportedCommands, sessionInfoDto.supportedCommands);
    }

    @Override
    public int hashCode() {
        return Objects.hash(playState, additionalUsers, capabilities, remoteEndPoint, playableMediaTypes, id, userId,
                userName, client, lastActivityDate, lastPlaybackCheckIn, lastPausedDate, deviceName, deviceType,
                nowPlayingItem, nowViewingItem, deviceId, applicationVersion, transcodingInfo, isActive,
                supportsMediaControl, supportsRemoteControl, nowPlayingQueue, nowPlayingQueueFullItems,
                hasCustomDeviceName, playlistItemId, serverId, userPrimaryImageTag, supportedCommands);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("class SessionInfoDto {\n");
        sb.append("    playState: ").append(toIndentedString(playState)).append("\n");
        sb.append("    additionalUsers: ").append(toIndentedString(additionalUsers)).append("\n");
        sb.append("    capabilities: ").append(toIndentedString(capabilities)).append("\n");
        sb.append("    remoteEndPoint: ").append(toIndentedString(remoteEndPoint)).append("\n");
        sb.append("    playableMediaTypes: ").append(toIndentedString(playableMediaTypes)).append("\n");
        sb.append("    id: ").append(toIndentedString(id)).append("\n");
        sb.append("    userId: ").append(toIndentedString(userId)).append("\n");
        sb.append("    userName: ").append(toIndentedString(userName)).append("\n");
        sb.append("    client: ").append(toIndentedString(client)).append("\n");
        sb.append("    lastActivityDate: ").append(toIndentedString(lastActivityDate)).append("\n");
        sb.append("    lastPlaybackCheckIn: ").append(toIndentedString(lastPlaybackCheckIn)).append("\n");
        sb.append("    lastPausedDate: ").append(toIndentedString(lastPausedDate)).append("\n");
        sb.append("    deviceName: ").append(toIndentedString(deviceName)).append("\n");
        sb.append("    deviceType: ").append(toIndentedString(deviceType)).append("\n");
        sb.append("    nowPlayingItem: ").append(toIndentedString(nowPlayingItem)).append("\n");
        sb.append("    nowViewingItem: ").append(toIndentedString(nowViewingItem)).append("\n");
        sb.append("    deviceId: ").append(toIndentedString(deviceId)).append("\n");
        sb.append("    applicationVersion: ").append(toIndentedString(applicationVersion)).append("\n");
        sb.append("    transcodingInfo: ").append(toIndentedString(transcodingInfo)).append("\n");
        sb.append("    isActive: ").append(toIndentedString(isActive)).append("\n");
        sb.append("    supportsMediaControl: ").append(toIndentedString(supportsMediaControl)).append("\n");
        sb.append("    supportsRemoteControl: ").append(toIndentedString(supportsRemoteControl)).append("\n");
        sb.append("    nowPlayingQueue: ").append(toIndentedString(nowPlayingQueue)).append("\n");
        sb.append("    nowPlayingQueueFullItems: ").append(toIndentedString(nowPlayingQueueFullItems)).append("\n");
        sb.append("    hasCustomDeviceName: ").append(toIndentedString(hasCustomDeviceName)).append("\n");
        sb.append("    playlistItemId: ").append(toIndentedString(playlistItemId)).append("\n");
        sb.append("    serverId: ").append(toIndentedString(serverId)).append("\n");
        sb.append("    userPrimaryImageTag: ").append(toIndentedString(userPrimaryImageTag)).append("\n");
        sb.append("    supportedCommands: ").append(toIndentedString(supportedCommands)).append("\n");
        sb.append("}");
        return sb.toString();
    }

    /**
     * Convert the given object to string with each line indented by 4 spaces
     * (except the first line).
     */
    private String toIndentedString(Object o) {
        return o == null ? "null" : o.toString().replace("\n", "\n    ");
    }

    /**
     * Convert the instance into URL query string.
     *
     * @return URL query string
     */
    public String toUrlQueryString() {
        return toUrlQueryString(null);
    }

    /**
     * Convert the instance into URL query string.
     *
     * @param prefix prefix of the query string
     * @return URL query string
     */
    public String toUrlQueryString(String prefix) {
        String suffix = "";
        String containerSuffix = "";
        String containerPrefix = "";
        if (prefix == null) {
            // style=form, explode=true, e.g. /pet?name=cat&type=manx
            prefix = "";
        } else {
            // deepObject style e.g. /pet?id[name]=cat&id[type]=manx
            prefix = prefix + "[";
            suffix = "]";
            containerSuffix = "]";
            containerPrefix = "[";
        }

        StringJoiner joiner = new StringJoiner("&");

        // add `PlayState` to the URL query string
        if (getPlayState() != null) {
            joiner.add(getPlayState().toUrlQueryString(prefix + "PlayState" + suffix));
        }

        // add `AdditionalUsers` to the URL query string
        if (getAdditionalUsers() != null) {
            for (int i = 0; i < getAdditionalUsers().size(); i++) {
                if (getAdditionalUsers().get(i) != null) {
                    joiner.add(getAdditionalUsers().get(i).toUrlQueryString(
                            String.format(java.util.Locale.ROOT, "%sAdditionalUsers%s%s", prefix, suffix,
                                    "".equals(suffix) ? ""
                                            : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i,
                                                    containerSuffix))));
                }
            }
        }

        // add `Capabilities` to the URL query string
        if (getCapabilities() != null) {
            joiner.add(getCapabilities().toUrlQueryString(prefix + "Capabilities" + suffix));
        }

        // add `RemoteEndPoint` to the URL query string
        if (getRemoteEndPoint() != null) {
            try {
                joiner.add(String.format(java.util.Locale.ROOT, "%sRemoteEndPoint%s=%s", prefix, suffix,
                        URLEncoder.encode(String.valueOf(getRemoteEndPoint()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `PlayableMediaTypes` to the URL query string
        if (getPlayableMediaTypes() != null) {
            for (int i = 0; i < getPlayableMediaTypes().size(); i++) {
                if (getPlayableMediaTypes().get(i) != null) {
                    try {
                        joiner.add(String.format(java.util.Locale.ROOT, "%sPlayableMediaTypes%s%s=%s", prefix, suffix,
                                "".equals(suffix) ? ""
                                        : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i,
                                                containerSuffix),
                                URLEncoder.encode(String.valueOf(getPlayableMediaTypes().get(i)), "UTF-8")
                                        .replaceAll("\\+", "%20")));
                    } catch (UnsupportedEncodingException e) {
                        // Should never happen, UTF-8 is always supported
                        throw new RuntimeException(e);
                    }
                }
            }
        }

        // add `Id` to the URL query string
        if (getId() != null) {
            try {
                joiner.add(String.format(java.util.Locale.ROOT, "%sId%s=%s", prefix, suffix,
                        URLEncoder.encode(String.valueOf(getId()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `UserId` to the URL query string
        if (getUserId() != null) {
            try {
                joiner.add(String.format(java.util.Locale.ROOT, "%sUserId%s=%s", prefix, suffix,
                        URLEncoder.encode(String.valueOf(getUserId()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `UserName` to the URL query string
        if (getUserName() != null) {
            try {
                joiner.add(String.format(java.util.Locale.ROOT, "%sUserName%s=%s", prefix, suffix,
                        URLEncoder.encode(String.valueOf(getUserName()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `Client` to the URL query string
        if (getClient() != null) {
            try {
                joiner.add(String.format(java.util.Locale.ROOT, "%sClient%s=%s", prefix, suffix,
                        URLEncoder.encode(String.valueOf(getClient()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `LastActivityDate` to the URL query string
        if (getLastActivityDate() != null) {
            try {
                joiner.add(String.format(java.util.Locale.ROOT, "%sLastActivityDate%s=%s", prefix, suffix,
                        URLEncoder.encode(String.valueOf(getLastActivityDate()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `LastPlaybackCheckIn` to the URL query string
        if (getLastPlaybackCheckIn() != null) {
            try {
                joiner.add(String.format(java.util.Locale.ROOT, "%sLastPlaybackCheckIn%s=%s", prefix, suffix,
                        URLEncoder.encode(String.valueOf(getLastPlaybackCheckIn()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `LastPausedDate` to the URL query string
        if (getLastPausedDate() != null) {
            try {
                joiner.add(String.format(java.util.Locale.ROOT, "%sLastPausedDate%s=%s", prefix, suffix,
                        URLEncoder.encode(String.valueOf(getLastPausedDate()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `DeviceName` to the URL query string
        if (getDeviceName() != null) {
            try {
                joiner.add(String.format(java.util.Locale.ROOT, "%sDeviceName%s=%s", prefix, suffix,
                        URLEncoder.encode(String.valueOf(getDeviceName()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `DeviceType` to the URL query string
        if (getDeviceType() != null) {
            try {
                joiner.add(String.format(java.util.Locale.ROOT, "%sDeviceType%s=%s", prefix, suffix,
                        URLEncoder.encode(String.valueOf(getDeviceType()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `NowPlayingItem` to the URL query string
        if (getNowPlayingItem() != null) {
            joiner.add(getNowPlayingItem().toUrlQueryString(prefix + "NowPlayingItem" + suffix));
        }

        // add `NowViewingItem` to the URL query string
        if (getNowViewingItem() != null) {
            joiner.add(getNowViewingItem().toUrlQueryString(prefix + "NowViewingItem" + suffix));
        }

        // add `DeviceId` to the URL query string
        if (getDeviceId() != null) {
            try {
                joiner.add(String.format(java.util.Locale.ROOT, "%sDeviceId%s=%s", prefix, suffix,
                        URLEncoder.encode(String.valueOf(getDeviceId()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `ApplicationVersion` to the URL query string
        if (getApplicationVersion() != null) {
            try {
                joiner.add(String.format(java.util.Locale.ROOT, "%sApplicationVersion%s=%s", prefix, suffix,
                        URLEncoder.encode(String.valueOf(getApplicationVersion()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `TranscodingInfo` to the URL query string
        if (getTranscodingInfo() != null) {
            joiner.add(getTranscodingInfo().toUrlQueryString(prefix + "TranscodingInfo" + suffix));
        }

        // add `IsActive` to the URL query string
        if (getIsActive() != null) {
            try {
                joiner.add(String.format(java.util.Locale.ROOT, "%sIsActive%s=%s", prefix, suffix,
                        URLEncoder.encode(String.valueOf(getIsActive()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `SupportsMediaControl` to the URL query string
        if (getSupportsMediaControl() != null) {
            try {
                joiner.add(
                        String.format(java.util.Locale.ROOT, "%sSupportsMediaControl%s=%s", prefix, suffix, URLEncoder
                                .encode(String.valueOf(getSupportsMediaControl()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `SupportsRemoteControl` to the URL query string
        if (getSupportsRemoteControl() != null) {
            try {
                joiner.add(
                        String.format(java.util.Locale.ROOT, "%sSupportsRemoteControl%s=%s", prefix, suffix, URLEncoder
                                .encode(String.valueOf(getSupportsRemoteControl()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `NowPlayingQueue` to the URL query string
        if (getNowPlayingQueue() != null) {
            for (int i = 0; i < getNowPlayingQueue().size(); i++) {
                if (getNowPlayingQueue().get(i) != null) {
                    joiner.add(getNowPlayingQueue().get(i).toUrlQueryString(
                            String.format(java.util.Locale.ROOT, "%sNowPlayingQueue%s%s", prefix, suffix,
                                    "".equals(suffix) ? ""
                                            : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i,
                                                    containerSuffix))));
                }
            }
        }

        // add `NowPlayingQueueFullItems` to the URL query string
        if (getNowPlayingQueueFullItems() != null) {
            for (int i = 0; i < getNowPlayingQueueFullItems().size(); i++) {
                if (getNowPlayingQueueFullItems().get(i) != null) {
                    joiner.add(getNowPlayingQueueFullItems().get(i)
                            .toUrlQueryString(String.format(java.util.Locale.ROOT, "%sNowPlayingQueueFullItems%s%s",
                                    prefix, suffix,
                                    "".equals(suffix) ? ""
                                            : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i,
                                                    containerSuffix))));
                }
            }
        }

        // add `HasCustomDeviceName` to the URL query string
        if (getHasCustomDeviceName() != null) {
            try {
                joiner.add(String.format(java.util.Locale.ROOT, "%sHasCustomDeviceName%s=%s", prefix, suffix,
                        URLEncoder.encode(String.valueOf(getHasCustomDeviceName()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `PlaylistItemId` to the URL query string
        if (getPlaylistItemId() != null) {
            try {
                joiner.add(String.format(java.util.Locale.ROOT, "%sPlaylistItemId%s=%s", prefix, suffix,
                        URLEncoder.encode(String.valueOf(getPlaylistItemId()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `ServerId` to the URL query string
        if (getServerId() != null) {
            try {
                joiner.add(String.format(java.util.Locale.ROOT, "%sServerId%s=%s", prefix, suffix,
                        URLEncoder.encode(String.valueOf(getServerId()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `UserPrimaryImageTag` to the URL query string
        if (getUserPrimaryImageTag() != null) {
            try {
                joiner.add(String.format(java.util.Locale.ROOT, "%sUserPrimaryImageTag%s=%s", prefix, suffix,
                        URLEncoder.encode(String.valueOf(getUserPrimaryImageTag()), "UTF-8").replaceAll("\\+", "%20")));
            } catch (UnsupportedEncodingException e) {
                // Should never happen, UTF-8 is always supported
                throw new RuntimeException(e);
            }
        }

        // add `SupportedCommands` to the URL query string
        if (getSupportedCommands() != null) {
            for (int i = 0; i < getSupportedCommands().size(); i++) {
                if (getSupportedCommands().get(i) != null) {
                    try {
                        joiner.add(String.format(java.util.Locale.ROOT, "%sSupportedCommands%s%s=%s", prefix, suffix,
                                "".equals(suffix) ? ""
                                        : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i,
                                                containerSuffix),
                                URLEncoder.encode(String.valueOf(getSupportedCommands().get(i)), "UTF-8")
                                        .replaceAll("\\+", "%20")));
                    } catch (UnsupportedEncodingException e) {
                        // Should never happen, UTF-8 is always supported
                        throw new RuntimeException(e);
                    }
                }
            }
        }

        return joiner.toString();
    }

    public static class Builder {

        private SessionInfoDto instance;

        public Builder() {
            this(new SessionInfoDto());
        }

        protected Builder(SessionInfoDto instance) {
            this.instance = instance;
        }

        public SessionInfoDto.Builder playState(PlayerStateInfo playState) {
            this.instance.playState = playState;
            return this;
        }

        public SessionInfoDto.Builder additionalUsers(List<SessionUserInfo> additionalUsers) {
            this.instance.additionalUsers = additionalUsers;
            return this;
        }

        public SessionInfoDto.Builder capabilities(ClientCapabilitiesDto capabilities) {
            this.instance.capabilities = capabilities;
            return this;
        }

        public SessionInfoDto.Builder remoteEndPoint(String remoteEndPoint) {
            this.instance.remoteEndPoint = remoteEndPoint;
            return this;
        }

        public SessionInfoDto.Builder playableMediaTypes(List<MediaType> playableMediaTypes) {
            this.instance.playableMediaTypes = playableMediaTypes;
            return this;
        }

        public SessionInfoDto.Builder id(String id) {
            this.instance.id = id;
            return this;
        }

        public SessionInfoDto.Builder userId(UUID userId) {
            this.instance.userId = userId;
            return this;
        }

        public SessionInfoDto.Builder userName(String userName) {
            this.instance.userName = userName;
            return this;
        }

        public SessionInfoDto.Builder client(String client) {
            this.instance.client = client;
            return this;
        }

        public SessionInfoDto.Builder lastActivityDate(OffsetDateTime lastActivityDate) {
            this.instance.lastActivityDate = lastActivityDate;
            return this;
        }

        public SessionInfoDto.Builder lastPlaybackCheckIn(OffsetDateTime lastPlaybackCheckIn) {
            this.instance.lastPlaybackCheckIn = lastPlaybackCheckIn;
            return this;
        }

        public SessionInfoDto.Builder lastPausedDate(OffsetDateTime lastPausedDate) {
            this.instance.lastPausedDate = lastPausedDate;
            return this;
        }

        public SessionInfoDto.Builder deviceName(String deviceName) {
            this.instance.deviceName = deviceName;
            return this;
        }

        public SessionInfoDto.Builder deviceType(String deviceType) {
            this.instance.deviceType = deviceType;
            return this;
        }

        public SessionInfoDto.Builder nowPlayingItem(BaseItemDto nowPlayingItem) {
            this.instance.nowPlayingItem = nowPlayingItem;
            return this;
        }

        public SessionInfoDto.Builder nowViewingItem(BaseItemDto nowViewingItem) {
            this.instance.nowViewingItem = nowViewingItem;
            return this;
        }

        public SessionInfoDto.Builder deviceId(String deviceId) {
            this.instance.deviceId = deviceId;
            return this;
        }

        public SessionInfoDto.Builder applicationVersion(String applicationVersion) {
            this.instance.applicationVersion = applicationVersion;
            return this;
        }

        public SessionInfoDto.Builder transcodingInfo(TranscodingInfo transcodingInfo) {
            this.instance.transcodingInfo = transcodingInfo;
            return this;
        }

        public SessionInfoDto.Builder isActive(Boolean isActive) {
            this.instance.isActive = isActive;
            return this;
        }

        public SessionInfoDto.Builder supportsMediaControl(Boolean supportsMediaControl) {
            this.instance.supportsMediaControl = supportsMediaControl;
            return this;
        }

        public SessionInfoDto.Builder supportsRemoteControl(Boolean supportsRemoteControl) {
            this.instance.supportsRemoteControl = supportsRemoteControl;
            return this;
        }

        public SessionInfoDto.Builder nowPlayingQueue(List<QueueItem> nowPlayingQueue) {
            this.instance.nowPlayingQueue = nowPlayingQueue;
            return this;
        }

        public SessionInfoDto.Builder nowPlayingQueueFullItems(List<BaseItemDto> nowPlayingQueueFullItems) {
            this.instance.nowPlayingQueueFullItems = nowPlayingQueueFullItems;
            return this;
        }

        public SessionInfoDto.Builder hasCustomDeviceName(Boolean hasCustomDeviceName) {
            this.instance.hasCustomDeviceName = hasCustomDeviceName;
            return this;
        }

        public SessionInfoDto.Builder playlistItemId(String playlistItemId) {
            this.instance.playlistItemId = playlistItemId;
            return this;
        }

        public SessionInfoDto.Builder serverId(String serverId) {
            this.instance.serverId = serverId;
            return this;
        }

        public SessionInfoDto.Builder userPrimaryImageTag(String userPrimaryImageTag) {
            this.instance.userPrimaryImageTag = userPrimaryImageTag;
            return this;
        }

        public SessionInfoDto.Builder supportedCommands(List<GeneralCommandType> supportedCommands) {
            this.instance.supportedCommands = supportedCommands;
            return this;
        }

        /**
         * returns a built SessionInfoDto instance.
         *
         * The builder is not reusable.
         */
        public SessionInfoDto build() {
            try {
                return this.instance;
            } finally {
                // ensure that this.instance is not reused
                this.instance = null;
            }
        }

        @Override
        public String toString() {
            return getClass() + "=(" + instance + ")";
        }
    }

    /**
     * Create a builder with no initialized field.
     */
    public static SessionInfoDto.Builder builder() {
        return new SessionInfoDto.Builder();
    }

    /**
     * Create a builder with a shallow copy of this instance.
     */
    public SessionInfoDto.Builder toBuilder() {
        return new SessionInfoDto.Builder().playState(getPlayState()).additionalUsers(getAdditionalUsers())
                .capabilities(getCapabilities()).remoteEndPoint(getRemoteEndPoint())
                .playableMediaTypes(getPlayableMediaTypes()).id(getId()).userId(getUserId()).userName(getUserName())
                .client(getClient()).lastActivityDate(getLastActivityDate())
                .lastPlaybackCheckIn(getLastPlaybackCheckIn()).lastPausedDate(getLastPausedDate())
                .deviceName(getDeviceName()).deviceType(getDeviceType()).nowPlayingItem(getNowPlayingItem())
                .nowViewingItem(getNowViewingItem()).deviceId(getDeviceId()).applicationVersion(getApplicationVersion())
                .transcodingInfo(getTranscodingInfo()).isActive(getIsActive())
                .supportsMediaControl(getSupportsMediaControl()).supportsRemoteControl(getSupportsRemoteControl())
                .nowPlayingQueue(getNowPlayingQueue()).nowPlayingQueueFullItems(getNowPlayingQueueFullItems())
                .hasCustomDeviceName(getHasCustomDeviceName()).playlistItemId(getPlaylistItemId())
                .serverId(getServerId()).userPrimaryImageTag(getUserPrimaryImageTag())
                .supportedCommands(getSupportedCommands());
    }
}
