/* 
 * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
 */

package dev.plexapi.sdk;

import com.fasterxml.jackson.core.type.TypeReference;
import dev.plexapi.sdk.models.errors.DeleteLibraryBadRequest;
import dev.plexapi.sdk.models.errors.DeleteLibraryUnauthorized;
import dev.plexapi.sdk.models.errors.GetAllLibrariesBadRequest;
import dev.plexapi.sdk.models.errors.GetAllLibrariesUnauthorized;
import dev.plexapi.sdk.models.errors.GetFileHashBadRequest;
import dev.plexapi.sdk.models.errors.GetFileHashUnauthorized;
import dev.plexapi.sdk.models.errors.GetLibraryDetailsBadRequest;
import dev.plexapi.sdk.models.errors.GetLibraryDetailsUnauthorized;
import dev.plexapi.sdk.models.errors.GetLibraryItemsBadRequest;
import dev.plexapi.sdk.models.errors.GetLibraryItemsUnauthorized;
import dev.plexapi.sdk.models.errors.GetMetaDataByRatingKeyBadRequest;
import dev.plexapi.sdk.models.errors.GetMetaDataByRatingKeyUnauthorized;
import dev.plexapi.sdk.models.errors.GetMetadataChildrenBadRequest;
import dev.plexapi.sdk.models.errors.GetMetadataChildrenUnauthorized;
import dev.plexapi.sdk.models.errors.GetOnDeckBadRequest;
import dev.plexapi.sdk.models.errors.GetOnDeckUnauthorized;
import dev.plexapi.sdk.models.errors.GetRecentlyAddedLibraryBadRequest;
import dev.plexapi.sdk.models.errors.GetRecentlyAddedLibraryUnauthorized;
import dev.plexapi.sdk.models.errors.GetRefreshLibraryMetadataBadRequest;
import dev.plexapi.sdk.models.errors.GetRefreshLibraryMetadataUnauthorized;
import dev.plexapi.sdk.models.errors.GetSearchAllLibrariesBadRequest;
import dev.plexapi.sdk.models.errors.GetSearchAllLibrariesUnauthorized;
import dev.plexapi.sdk.models.errors.GetSearchLibraryBadRequest;
import dev.plexapi.sdk.models.errors.GetSearchLibraryUnauthorized;
import dev.plexapi.sdk.models.errors.GetTopWatchedContentBadRequest;
import dev.plexapi.sdk.models.errors.GetTopWatchedContentUnauthorized;
import dev.plexapi.sdk.models.errors.SDKError;
import dev.plexapi.sdk.models.operations.DeleteLibraryRequest;
import dev.plexapi.sdk.models.operations.DeleteLibraryRequestBuilder;
import dev.plexapi.sdk.models.operations.DeleteLibraryResponse;
import dev.plexapi.sdk.models.operations.Force;
import dev.plexapi.sdk.models.operations.GetAllLibrariesRequestBuilder;
import dev.plexapi.sdk.models.operations.GetAllLibrariesResponse;
import dev.plexapi.sdk.models.operations.GetAllLibrariesResponseBody;
import dev.plexapi.sdk.models.operations.GetFileHashRequest;
import dev.plexapi.sdk.models.operations.GetFileHashRequestBuilder;
import dev.plexapi.sdk.models.operations.GetFileHashResponse;
import dev.plexapi.sdk.models.operations.GetLibraryDetailsRequest;
import dev.plexapi.sdk.models.operations.GetLibraryDetailsRequestBuilder;
import dev.plexapi.sdk.models.operations.GetLibraryDetailsResponse;
import dev.plexapi.sdk.models.operations.GetLibraryDetailsResponseBody;
import dev.plexapi.sdk.models.operations.GetLibraryItemsRequest;
import dev.plexapi.sdk.models.operations.GetLibraryItemsRequestBuilder;
import dev.plexapi.sdk.models.operations.GetLibraryItemsResponse;
import dev.plexapi.sdk.models.operations.GetLibraryItemsResponseBody;
import dev.plexapi.sdk.models.operations.GetMetaDataByRatingKeyRequest;
import dev.plexapi.sdk.models.operations.GetMetaDataByRatingKeyRequestBuilder;
import dev.plexapi.sdk.models.operations.GetMetaDataByRatingKeyResponse;
import dev.plexapi.sdk.models.operations.GetMetaDataByRatingKeyResponseBody;
import dev.plexapi.sdk.models.operations.GetMetadataChildrenRequest;
import dev.plexapi.sdk.models.operations.GetMetadataChildrenRequestBuilder;
import dev.plexapi.sdk.models.operations.GetMetadataChildrenResponse;
import dev.plexapi.sdk.models.operations.GetMetadataChildrenResponseBody;
import dev.plexapi.sdk.models.operations.GetOnDeckRequestBuilder;
import dev.plexapi.sdk.models.operations.GetOnDeckResponse;
import dev.plexapi.sdk.models.operations.GetOnDeckResponseBody;
import dev.plexapi.sdk.models.operations.GetRecentlyAddedLibraryRequest;
import dev.plexapi.sdk.models.operations.GetRecentlyAddedLibraryRequestBuilder;
import dev.plexapi.sdk.models.operations.GetRecentlyAddedLibraryResponse;
import dev.plexapi.sdk.models.operations.GetRecentlyAddedLibraryResponseBody;
import dev.plexapi.sdk.models.operations.GetRefreshLibraryMetadataRequest;
import dev.plexapi.sdk.models.operations.GetRefreshLibraryMetadataRequestBuilder;
import dev.plexapi.sdk.models.operations.GetRefreshLibraryMetadataResponse;
import dev.plexapi.sdk.models.operations.GetSearchAllLibrariesRequest;
import dev.plexapi.sdk.models.operations.GetSearchAllLibrariesRequestBuilder;
import dev.plexapi.sdk.models.operations.GetSearchAllLibrariesResponse;
import dev.plexapi.sdk.models.operations.GetSearchAllLibrariesResponseBody;
import dev.plexapi.sdk.models.operations.GetSearchLibraryQueryParamType;
import dev.plexapi.sdk.models.operations.GetSearchLibraryRequest;
import dev.plexapi.sdk.models.operations.GetSearchLibraryRequestBuilder;
import dev.plexapi.sdk.models.operations.GetSearchLibraryResponse;
import dev.plexapi.sdk.models.operations.GetSearchLibraryResponseBody;
import dev.plexapi.sdk.models.operations.GetTopWatchedContentQueryParamType;
import dev.plexapi.sdk.models.operations.GetTopWatchedContentRequest;
import dev.plexapi.sdk.models.operations.GetTopWatchedContentRequestBuilder;
import dev.plexapi.sdk.models.operations.GetTopWatchedContentResponse;
import dev.plexapi.sdk.models.operations.GetTopWatchedContentResponseBody;
import dev.plexapi.sdk.models.operations.IncludeDetails;
import dev.plexapi.sdk.models.operations.SDKMethodInterfaces.*;
import dev.plexapi.sdk.utils.HTTPClient;
import dev.plexapi.sdk.utils.HTTPRequest;
import dev.plexapi.sdk.utils.Hook.AfterErrorContextImpl;
import dev.plexapi.sdk.utils.Hook.AfterSuccessContextImpl;
import dev.plexapi.sdk.utils.Hook.BeforeRequestContextImpl;
import dev.plexapi.sdk.utils.Utils;
import java.io.InputStream;
import java.lang.Double;
import java.lang.Exception;
import java.lang.Long;
import java.lang.String;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.List;
import java.util.Optional; 

/**
 * API Calls interacting with Plex Media Server Libraries
 * 
 */
public class Library implements
            MethodCallGetFileHash,
            MethodCallGetRecentlyAddedLibrary,
            MethodCallGetAllLibraries,
            MethodCallGetLibraryDetails,
            MethodCallDeleteLibrary,
            MethodCallGetLibraryItems,
            MethodCallGetRefreshLibraryMetadata,
            MethodCallGetSearchLibrary,
            MethodCallGetSearchAllLibraries,
            MethodCallGetMetaDataByRatingKey,
            MethodCallGetMetadataChildren,
            MethodCallGetTopWatchedContent,
            MethodCallGetOnDeck {

    private final SDKConfiguration sdkConfiguration;

    Library(SDKConfiguration sdkConfiguration) {
        this.sdkConfiguration = sdkConfiguration;
    }


    /**
     * Get Hash Value
     * This resource returns hash values for local files
     * @return The call builder
     */
    public GetFileHashRequestBuilder getFileHash() {
        return new GetFileHashRequestBuilder(this);
    }

    /**
     * Get Hash Value
     * This resource returns hash values for local files
     * @param url This is the path to the local file, must be prefixed by `file://`
     * @return The response from the API call
     * @throws Exception if the API call fails
     */
    public GetFileHashResponse getFileHash(
            String url) throws Exception {
        return getFileHash(url, Optional.empty());
    }
    
    /**
     * Get Hash Value
     * This resource returns hash values for local files
     * @param url This is the path to the local file, must be prefixed by `file://`
     * @param type Item type
     * @return The response from the API call
     * @throws Exception if the API call fails
     */
    public GetFileHashResponse getFileHash(
            String url,
            Optional<Double> type) throws Exception {
        GetFileHashRequest request =
            GetFileHashRequest
                .builder()
                .url(url)
                .type(type)
                .build();
        
        String _baseUrl = Utils.templateUrl(
                this.sdkConfiguration.serverUrl, this.sdkConfiguration.getServerVariableDefaults());
        String _url = Utils.generateURL(
                _baseUrl,
                "/library/hashes");
        
        HTTPRequest _req = new HTTPRequest(_url, "GET");
        _req.addHeader("Accept", "application/json")
            .addHeader("user-agent", 
                SDKConfiguration.USER_AGENT);

        _req.addQueryParams(Utils.getQueryParams(
                GetFileHashRequest.class,
                request, 
                this.sdkConfiguration.globals));

        Utils.configureSecurity(_req,  
                this.sdkConfiguration.securitySource.getSecurity());

        HTTPClient _client = this.sdkConfiguration.defaultClient;
        HttpRequest _r = 
            sdkConfiguration.hooks()
               .beforeRequest(
                  new BeforeRequestContextImpl(
                      "getFileHash", 
                      Optional.of(List.of()), 
                      sdkConfiguration.securitySource()),
                  _req.build());
        HttpResponse<InputStream> _httpRes;
        try {
            _httpRes = _client.send(_r);
            if (Utils.statusCodeMatches(_httpRes.statusCode(), "400", "401", "4XX", "5XX")) {
                _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "getFileHash",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()),
                        Optional.of(_httpRes),
                        Optional.empty());
            } else {
                _httpRes = sdkConfiguration.hooks()
                    .afterSuccess(
                        new AfterSuccessContextImpl(
                            "getFileHash",
                            Optional.of(List.of()), 
                            sdkConfiguration.securitySource()),
                         _httpRes);
            }
        } catch (Exception _e) {
            _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "getFileHash",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()), 
                        Optional.empty(),
                        Optional.of(_e));
        }
        String _contentType = _httpRes
            .headers()
            .firstValue("Content-Type")
            .orElse("application/octet-stream");
        GetFileHashResponse.Builder _resBuilder = 
            GetFileHashResponse
                .builder()
                .contentType(_contentType)
                .statusCode(_httpRes.statusCode())
                .rawResponse(_httpRes);

        GetFileHashResponse _res = _resBuilder.build();
        
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "200")) {
            // no content 
            return _res;
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "400")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetFileHashBadRequest _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetFileHashBadRequest>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "401")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetFileHashUnauthorized _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetFileHashUnauthorized>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "4XX", "5XX")) {
            // no content 
            throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "API error occurred", 
                    Utils.extractByteArrayFromBody(_httpRes));
        }
        throw new SDKError(
            _httpRes, 
            _httpRes.statusCode(), 
            "Unexpected status code received: " + _httpRes.statusCode(), 
            Utils.extractByteArrayFromBody(_httpRes));
    }



    /**
     * Get Recently Added
     * This endpoint will return the recently added content.
     * 
     * @return The call builder
     */
    public GetRecentlyAddedLibraryRequestBuilder getRecentlyAddedLibrary() {
        return new GetRecentlyAddedLibraryRequestBuilder(this);
    }

    /**
     * Get Recently Added
     * This endpoint will return the recently added content.
     * 
     * @param request The request object containing all of the parameters for the API call.
     * @return The response from the API call
     * @throws Exception if the API call fails
     */
    public GetRecentlyAddedLibraryResponse getRecentlyAddedLibrary(
            GetRecentlyAddedLibraryRequest request) throws Exception {
        String _baseUrl = Utils.templateUrl(
                this.sdkConfiguration.serverUrl, this.sdkConfiguration.getServerVariableDefaults());
        String _url = Utils.generateURL(
                _baseUrl,
                "/library/recentlyAdded");
        
        HTTPRequest _req = new HTTPRequest(_url, "GET");
        _req.addHeader("Accept", "application/json")
            .addHeader("user-agent", 
                SDKConfiguration.USER_AGENT);

        _req.addQueryParams(Utils.getQueryParams(
                GetRecentlyAddedLibraryRequest.class,
                request, 
                this.sdkConfiguration.globals));

        Utils.configureSecurity(_req,  
                this.sdkConfiguration.securitySource.getSecurity());

        HTTPClient _client = this.sdkConfiguration.defaultClient;
        HttpRequest _r = 
            sdkConfiguration.hooks()
               .beforeRequest(
                  new BeforeRequestContextImpl(
                      "get-recently-added-library", 
                      Optional.of(List.of()), 
                      sdkConfiguration.securitySource()),
                  _req.build());
        HttpResponse<InputStream> _httpRes;
        try {
            _httpRes = _client.send(_r);
            if (Utils.statusCodeMatches(_httpRes.statusCode(), "400", "401", "4XX", "5XX")) {
                _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "get-recently-added-library",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()),
                        Optional.of(_httpRes),
                        Optional.empty());
            } else {
                _httpRes = sdkConfiguration.hooks()
                    .afterSuccess(
                        new AfterSuccessContextImpl(
                            "get-recently-added-library",
                            Optional.of(List.of()), 
                            sdkConfiguration.securitySource()),
                         _httpRes);
            }
        } catch (Exception _e) {
            _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "get-recently-added-library",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()), 
                        Optional.empty(),
                        Optional.of(_e));
        }
        String _contentType = _httpRes
            .headers()
            .firstValue("Content-Type")
            .orElse("application/octet-stream");
        GetRecentlyAddedLibraryResponse.Builder _resBuilder = 
            GetRecentlyAddedLibraryResponse
                .builder()
                .contentType(_contentType)
                .statusCode(_httpRes.statusCode())
                .rawResponse(_httpRes);

        GetRecentlyAddedLibraryResponse _res = _resBuilder.build();
        
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "200")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetRecentlyAddedLibraryResponseBody _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetRecentlyAddedLibraryResponseBody>() {});
                _res.withObject(Optional.ofNullable(_out));
                return _res;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "400")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetRecentlyAddedLibraryBadRequest _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetRecentlyAddedLibraryBadRequest>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "401")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetRecentlyAddedLibraryUnauthorized _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetRecentlyAddedLibraryUnauthorized>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "4XX", "5XX")) {
            // no content 
            throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "API error occurred", 
                    Utils.extractByteArrayFromBody(_httpRes));
        }
        throw new SDKError(
            _httpRes, 
            _httpRes.statusCode(), 
            "Unexpected status code received: " + _httpRes.statusCode(), 
            Utils.extractByteArrayFromBody(_httpRes));
    }



    /**
     * Get All Libraries
     * A library section (commonly referred to as just a library) is a collection of media. 
     * Libraries are typed, and depending on their type provide either a flat or a hierarchical view of the media. 
     * For example, a music library has an artist &gt; albums &gt; tracks structure, whereas a movie library is flat.
     * 
     * Libraries have features beyond just being a collection of media; for starters, they include information about supported types, filters and sorts. 
     * This allows a client to provide a rich interface around the media (e.g. allow sorting movies by release year).
     * 
     * @return The call builder
     */
    public GetAllLibrariesRequestBuilder getAllLibraries() {
        return new GetAllLibrariesRequestBuilder(this);
    }

    /**
     * Get All Libraries
     * A library section (commonly referred to as just a library) is a collection of media. 
     * Libraries are typed, and depending on their type provide either a flat or a hierarchical view of the media. 
     * For example, a music library has an artist &gt; albums &gt; tracks structure, whereas a movie library is flat.
     * 
     * Libraries have features beyond just being a collection of media; for starters, they include information about supported types, filters and sorts. 
     * This allows a client to provide a rich interface around the media (e.g. allow sorting movies by release year).
     * 
     * @return The response from the API call
     * @throws Exception if the API call fails
     */
    public GetAllLibrariesResponse getAllLibrariesDirect() throws Exception {
        String _baseUrl = Utils.templateUrl(
                this.sdkConfiguration.serverUrl, this.sdkConfiguration.getServerVariableDefaults());
        String _url = Utils.generateURL(
                _baseUrl,
                "/library/sections");
        
        HTTPRequest _req = new HTTPRequest(_url, "GET");
        _req.addHeader("Accept", "application/json")
            .addHeader("user-agent", 
                SDKConfiguration.USER_AGENT);

        Utils.configureSecurity(_req,  
                this.sdkConfiguration.securitySource.getSecurity());

        HTTPClient _client = this.sdkConfiguration.defaultClient;
        HttpRequest _r = 
            sdkConfiguration.hooks()
               .beforeRequest(
                  new BeforeRequestContextImpl(
                      "get-all-libraries", 
                      Optional.of(List.of()), 
                      sdkConfiguration.securitySource()),
                  _req.build());
        HttpResponse<InputStream> _httpRes;
        try {
            _httpRes = _client.send(_r);
            if (Utils.statusCodeMatches(_httpRes.statusCode(), "400", "401", "4XX", "5XX")) {
                _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "get-all-libraries",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()),
                        Optional.of(_httpRes),
                        Optional.empty());
            } else {
                _httpRes = sdkConfiguration.hooks()
                    .afterSuccess(
                        new AfterSuccessContextImpl(
                            "get-all-libraries",
                            Optional.of(List.of()), 
                            sdkConfiguration.securitySource()),
                         _httpRes);
            }
        } catch (Exception _e) {
            _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "get-all-libraries",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()), 
                        Optional.empty(),
                        Optional.of(_e));
        }
        String _contentType = _httpRes
            .headers()
            .firstValue("Content-Type")
            .orElse("application/octet-stream");
        GetAllLibrariesResponse.Builder _resBuilder = 
            GetAllLibrariesResponse
                .builder()
                .contentType(_contentType)
                .statusCode(_httpRes.statusCode())
                .rawResponse(_httpRes);

        GetAllLibrariesResponse _res = _resBuilder.build();
        
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "200")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetAllLibrariesResponseBody _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetAllLibrariesResponseBody>() {});
                _res.withObject(Optional.ofNullable(_out));
                return _res;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "400")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetAllLibrariesBadRequest _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetAllLibrariesBadRequest>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "401")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetAllLibrariesUnauthorized _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetAllLibrariesUnauthorized>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "4XX", "5XX")) {
            // no content 
            throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "API error occurred", 
                    Utils.extractByteArrayFromBody(_httpRes));
        }
        throw new SDKError(
            _httpRes, 
            _httpRes.statusCode(), 
            "Unexpected status code received: " + _httpRes.statusCode(), 
            Utils.extractByteArrayFromBody(_httpRes));
    }



    /**
     * Get Library Details
     * ## Library Details Endpoint
     * 
     * This endpoint provides comprehensive details about the library, focusing on organizational aspects rather than the content itself.   
     * 
     * The details include:
     * 
     * ### Directories
     * Organized into three categories:
     * 
     * - **Primary Directories**: 
     *   - Used in some clients for quick access to media subsets (e.g., "All", "On Deck").
     *   - Most can be replicated via media queries.
     *   - Customizable by users.
     * 
     * - **Secondary Directories**:
     *   - Marked with `secondary="1"`.
     *   - Used in older clients for structured navigation.
     * 
     * - **Special Directories**:
     *   - Includes a "By Folder" entry for filesystem-based browsing.
     *   - Contains an obsolete `search="1"` entry for on-the-fly search dialog creation.
     * 
     * ### Types
     * Each type in the library comes with a set of filters and sorts, aiding in building dynamic media controls:
     * 
     * - **Type Object Attributes**:
     *   - `key`: Endpoint for the media list of this type.
     *   - `type`: Metadata type (if standard Plex type).
     *   - `title`: Title for this content type (e.g., "Movies").
     * 
     * - **Filter Objects**:
     *   - Subset of the media query language.
     *   - Attributes include `filter` (name), `filterType` (data type), `key` (endpoint for value range), and `title`.
     * 
     * - **Sort Objects**:
     *   - Description of sort fields.
     *   - Attributes include `defaultDirection` (asc/desc), `descKey` and `key` (sort parameters), and `title`.
     * 
     * &gt; **Note**: Filters and sorts are optional; without them, no filtering controls are rendered.
     * 
     * @return The call builder
     */
    public GetLibraryDetailsRequestBuilder getLibraryDetails() {
        return new GetLibraryDetailsRequestBuilder(this);
    }

    /**
     * Get Library Details
     * ## Library Details Endpoint
     * 
     * This endpoint provides comprehensive details about the library, focusing on organizational aspects rather than the content itself.   
     * 
     * The details include:
     * 
     * ### Directories
     * Organized into three categories:
     * 
     * - **Primary Directories**: 
     *   - Used in some clients for quick access to media subsets (e.g., "All", "On Deck").
     *   - Most can be replicated via media queries.
     *   - Customizable by users.
     * 
     * - **Secondary Directories**:
     *   - Marked with `secondary="1"`.
     *   - Used in older clients for structured navigation.
     * 
     * - **Special Directories**:
     *   - Includes a "By Folder" entry for filesystem-based browsing.
     *   - Contains an obsolete `search="1"` entry for on-the-fly search dialog creation.
     * 
     * ### Types
     * Each type in the library comes with a set of filters and sorts, aiding in building dynamic media controls:
     * 
     * - **Type Object Attributes**:
     *   - `key`: Endpoint for the media list of this type.
     *   - `type`: Metadata type (if standard Plex type).
     *   - `title`: Title for this content type (e.g., "Movies").
     * 
     * - **Filter Objects**:
     *   - Subset of the media query language.
     *   - Attributes include `filter` (name), `filterType` (data type), `key` (endpoint for value range), and `title`.
     * 
     * - **Sort Objects**:
     *   - Description of sort fields.
     *   - Attributes include `defaultDirection` (asc/desc), `descKey` and `key` (sort parameters), and `title`.
     * 
     * &gt; **Note**: Filters and sorts are optional; without them, no filtering controls are rendered.
     * 
     * @param sectionKey The unique key of the Plex library. 
    Note: This is unique in the context of the Plex server.

     * @return The response from the API call
     * @throws Exception if the API call fails
     */
    public GetLibraryDetailsResponse getLibraryDetails(
            int sectionKey) throws Exception {
        return getLibraryDetails(Optional.empty(), sectionKey);
    }
    
    /**
     * Get Library Details
     * ## Library Details Endpoint
     * 
     * This endpoint provides comprehensive details about the library, focusing on organizational aspects rather than the content itself.   
     * 
     * The details include:
     * 
     * ### Directories
     * Organized into three categories:
     * 
     * - **Primary Directories**: 
     *   - Used in some clients for quick access to media subsets (e.g., "All", "On Deck").
     *   - Most can be replicated via media queries.
     *   - Customizable by users.
     * 
     * - **Secondary Directories**:
     *   - Marked with `secondary="1"`.
     *   - Used in older clients for structured navigation.
     * 
     * - **Special Directories**:
     *   - Includes a "By Folder" entry for filesystem-based browsing.
     *   - Contains an obsolete `search="1"` entry for on-the-fly search dialog creation.
     * 
     * ### Types
     * Each type in the library comes with a set of filters and sorts, aiding in building dynamic media controls:
     * 
     * - **Type Object Attributes**:
     *   - `key`: Endpoint for the media list of this type.
     *   - `type`: Metadata type (if standard Plex type).
     *   - `title`: Title for this content type (e.g., "Movies").
     * 
     * - **Filter Objects**:
     *   - Subset of the media query language.
     *   - Attributes include `filter` (name), `filterType` (data type), `key` (endpoint for value range), and `title`.
     * 
     * - **Sort Objects**:
     *   - Description of sort fields.
     *   - Attributes include `defaultDirection` (asc/desc), `descKey` and `key` (sort parameters), and `title`.
     * 
     * &gt; **Note**: Filters and sorts are optional; without them, no filtering controls are rendered.
     * 
     * @param includeDetails Whether or not to include details for a section (types, filters, and sorts). 
    Only exists for backwards compatibility, media providers other than the server libraries have it on always.

     * @param sectionKey The unique key of the Plex library. 
    Note: This is unique in the context of the Plex server.

     * @return The response from the API call
     * @throws Exception if the API call fails
     */
    public GetLibraryDetailsResponse getLibraryDetails(
            Optional<? extends IncludeDetails> includeDetails,
            int sectionKey) throws Exception {
        GetLibraryDetailsRequest request =
            GetLibraryDetailsRequest
                .builder()
                .includeDetails(includeDetails)
                .sectionKey(sectionKey)
                .build();
        
        String _baseUrl = Utils.templateUrl(
                this.sdkConfiguration.serverUrl, this.sdkConfiguration.getServerVariableDefaults());
        String _url = Utils.generateURL(
                GetLibraryDetailsRequest.class,
                _baseUrl,
                "/library/sections/{sectionKey}",
                request, this.sdkConfiguration.globals);
        
        HTTPRequest _req = new HTTPRequest(_url, "GET");
        _req.addHeader("Accept", "application/json")
            .addHeader("user-agent", 
                SDKConfiguration.USER_AGENT);

        _req.addQueryParams(Utils.getQueryParams(
                GetLibraryDetailsRequest.class,
                request, 
                this.sdkConfiguration.globals));

        Utils.configureSecurity(_req,  
                this.sdkConfiguration.securitySource.getSecurity());

        HTTPClient _client = this.sdkConfiguration.defaultClient;
        HttpRequest _r = 
            sdkConfiguration.hooks()
               .beforeRequest(
                  new BeforeRequestContextImpl(
                      "get-library-details", 
                      Optional.of(List.of()), 
                      sdkConfiguration.securitySource()),
                  _req.build());
        HttpResponse<InputStream> _httpRes;
        try {
            _httpRes = _client.send(_r);
            if (Utils.statusCodeMatches(_httpRes.statusCode(), "400", "401", "4XX", "5XX")) {
                _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "get-library-details",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()),
                        Optional.of(_httpRes),
                        Optional.empty());
            } else {
                _httpRes = sdkConfiguration.hooks()
                    .afterSuccess(
                        new AfterSuccessContextImpl(
                            "get-library-details",
                            Optional.of(List.of()), 
                            sdkConfiguration.securitySource()),
                         _httpRes);
            }
        } catch (Exception _e) {
            _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "get-library-details",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()), 
                        Optional.empty(),
                        Optional.of(_e));
        }
        String _contentType = _httpRes
            .headers()
            .firstValue("Content-Type")
            .orElse("application/octet-stream");
        GetLibraryDetailsResponse.Builder _resBuilder = 
            GetLibraryDetailsResponse
                .builder()
                .contentType(_contentType)
                .statusCode(_httpRes.statusCode())
                .rawResponse(_httpRes);

        GetLibraryDetailsResponse _res = _resBuilder.build();
        
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "200")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetLibraryDetailsResponseBody _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetLibraryDetailsResponseBody>() {});
                _res.withObject(Optional.ofNullable(_out));
                return _res;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "400")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetLibraryDetailsBadRequest _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetLibraryDetailsBadRequest>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "401")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetLibraryDetailsUnauthorized _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetLibraryDetailsUnauthorized>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "4XX", "5XX")) {
            // no content 
            throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "API error occurred", 
                    Utils.extractByteArrayFromBody(_httpRes));
        }
        throw new SDKError(
            _httpRes, 
            _httpRes.statusCode(), 
            "Unexpected status code received: " + _httpRes.statusCode(), 
            Utils.extractByteArrayFromBody(_httpRes));
    }



    /**
     * Delete Library Section
     * Delete a library using a specific section id
     * @return The call builder
     */
    public DeleteLibraryRequestBuilder deleteLibrary() {
        return new DeleteLibraryRequestBuilder(this);
    }

    /**
     * Delete Library Section
     * Delete a library using a specific section id
     * @param sectionKey The unique key of the Plex library. 
    Note: This is unique in the context of the Plex server.

     * @return The response from the API call
     * @throws Exception if the API call fails
     */
    public DeleteLibraryResponse deleteLibrary(
            int sectionKey) throws Exception {
        DeleteLibraryRequest request =
            DeleteLibraryRequest
                .builder()
                .sectionKey(sectionKey)
                .build();
        
        String _baseUrl = Utils.templateUrl(
                this.sdkConfiguration.serverUrl, this.sdkConfiguration.getServerVariableDefaults());
        String _url = Utils.generateURL(
                DeleteLibraryRequest.class,
                _baseUrl,
                "/library/sections/{sectionKey}",
                request, this.sdkConfiguration.globals);
        
        HTTPRequest _req = new HTTPRequest(_url, "DELETE");
        _req.addHeader("Accept", "application/json")
            .addHeader("user-agent", 
                SDKConfiguration.USER_AGENT);

        Utils.configureSecurity(_req,  
                this.sdkConfiguration.securitySource.getSecurity());

        HTTPClient _client = this.sdkConfiguration.defaultClient;
        HttpRequest _r = 
            sdkConfiguration.hooks()
               .beforeRequest(
                  new BeforeRequestContextImpl(
                      "deleteLibrary", 
                      Optional.of(List.of()), 
                      sdkConfiguration.securitySource()),
                  _req.build());
        HttpResponse<InputStream> _httpRes;
        try {
            _httpRes = _client.send(_r);
            if (Utils.statusCodeMatches(_httpRes.statusCode(), "400", "401", "4XX", "5XX")) {
                _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "deleteLibrary",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()),
                        Optional.of(_httpRes),
                        Optional.empty());
            } else {
                _httpRes = sdkConfiguration.hooks()
                    .afterSuccess(
                        new AfterSuccessContextImpl(
                            "deleteLibrary",
                            Optional.of(List.of()), 
                            sdkConfiguration.securitySource()),
                         _httpRes);
            }
        } catch (Exception _e) {
            _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "deleteLibrary",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()), 
                        Optional.empty(),
                        Optional.of(_e));
        }
        String _contentType = _httpRes
            .headers()
            .firstValue("Content-Type")
            .orElse("application/octet-stream");
        DeleteLibraryResponse.Builder _resBuilder = 
            DeleteLibraryResponse
                .builder()
                .contentType(_contentType)
                .statusCode(_httpRes.statusCode())
                .rawResponse(_httpRes);

        DeleteLibraryResponse _res = _resBuilder.build();
        
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "200")) {
            // no content 
            return _res;
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "400")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                DeleteLibraryBadRequest _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<DeleteLibraryBadRequest>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "401")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                DeleteLibraryUnauthorized _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<DeleteLibraryUnauthorized>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "4XX", "5XX")) {
            // no content 
            throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "API error occurred", 
                    Utils.extractByteArrayFromBody(_httpRes));
        }
        throw new SDKError(
            _httpRes, 
            _httpRes.statusCode(), 
            "Unexpected status code received: " + _httpRes.statusCode(), 
            Utils.extractByteArrayFromBody(_httpRes));
    }



    /**
     * Get Library Items
     * Fetches details from a specific section of the library identified by a section key and a tag. The tag parameter accepts the following values:
     * - `all`: All items in the section.
     * - `unwatched`: Items that have not been played.
     * - `newest`: Items that are recently released.
     * - `recentlyAdded`: Items that are recently added to the library.
     * - `recentlyViewed`: Items that were recently viewed.
     * - `onDeck`: Items to continue watching.
     * - `collection`: Items categorized by collection.
     * - `edition`: Items categorized by edition.
     * - `genre`: Items categorized by genre.
     * - `year`: Items categorized by year of release.
     * - `decade`: Items categorized by decade.
     * - `director`: Items categorized by director.
     * - `actor`: Items categorized by starring actor.
     * - `country`: Items categorized by country of origin.
     * - `contentRating`: Items categorized by content rating.
     * - `rating`: Items categorized by rating.
     * - `resolution`: Items categorized by resolution.
     * - `firstCharacter`: Items categorized by the first letter.
     * - `folder`: Items categorized by folder.
     * 
     * @return The call builder
     */
    public GetLibraryItemsRequestBuilder getLibraryItems() {
        return new GetLibraryItemsRequestBuilder(this);
    }

    /**
     * Get Library Items
     * Fetches details from a specific section of the library identified by a section key and a tag. The tag parameter accepts the following values:
     * - `all`: All items in the section.
     * - `unwatched`: Items that have not been played.
     * - `newest`: Items that are recently released.
     * - `recentlyAdded`: Items that are recently added to the library.
     * - `recentlyViewed`: Items that were recently viewed.
     * - `onDeck`: Items to continue watching.
     * - `collection`: Items categorized by collection.
     * - `edition`: Items categorized by edition.
     * - `genre`: Items categorized by genre.
     * - `year`: Items categorized by year of release.
     * - `decade`: Items categorized by decade.
     * - `director`: Items categorized by director.
     * - `actor`: Items categorized by starring actor.
     * - `country`: Items categorized by country of origin.
     * - `contentRating`: Items categorized by content rating.
     * - `rating`: Items categorized by rating.
     * - `resolution`: Items categorized by resolution.
     * - `firstCharacter`: Items categorized by the first letter.
     * - `folder`: Items categorized by folder.
     * 
     * @param request The request object containing all of the parameters for the API call.
     * @return The response from the API call
     * @throws Exception if the API call fails
     */
    public GetLibraryItemsResponse getLibraryItems(
            GetLibraryItemsRequest request) throws Exception {
        String _baseUrl = Utils.templateUrl(
                this.sdkConfiguration.serverUrl, this.sdkConfiguration.getServerVariableDefaults());
        String _url = Utils.generateURL(
                GetLibraryItemsRequest.class,
                _baseUrl,
                "/library/sections/{sectionKey}/{tag}",
                request, this.sdkConfiguration.globals);
        
        HTTPRequest _req = new HTTPRequest(_url, "GET");
        _req.addHeader("Accept", "application/json")
            .addHeader("user-agent", 
                SDKConfiguration.USER_AGENT);

        _req.addQueryParams(Utils.getQueryParams(
                GetLibraryItemsRequest.class,
                request, 
                this.sdkConfiguration.globals));

        Utils.configureSecurity(_req,  
                this.sdkConfiguration.securitySource.getSecurity());

        HTTPClient _client = this.sdkConfiguration.defaultClient;
        HttpRequest _r = 
            sdkConfiguration.hooks()
               .beforeRequest(
                  new BeforeRequestContextImpl(
                      "get-library-items", 
                      Optional.of(List.of()), 
                      sdkConfiguration.securitySource()),
                  _req.build());
        HttpResponse<InputStream> _httpRes;
        try {
            _httpRes = _client.send(_r);
            if (Utils.statusCodeMatches(_httpRes.statusCode(), "400", "401", "4XX", "5XX")) {
                _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "get-library-items",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()),
                        Optional.of(_httpRes),
                        Optional.empty());
            } else {
                _httpRes = sdkConfiguration.hooks()
                    .afterSuccess(
                        new AfterSuccessContextImpl(
                            "get-library-items",
                            Optional.of(List.of()), 
                            sdkConfiguration.securitySource()),
                         _httpRes);
            }
        } catch (Exception _e) {
            _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "get-library-items",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()), 
                        Optional.empty(),
                        Optional.of(_e));
        }
        String _contentType = _httpRes
            .headers()
            .firstValue("Content-Type")
            .orElse("application/octet-stream");
        GetLibraryItemsResponse.Builder _resBuilder = 
            GetLibraryItemsResponse
                .builder()
                .contentType(_contentType)
                .statusCode(_httpRes.statusCode())
                .rawResponse(_httpRes);

        GetLibraryItemsResponse _res = _resBuilder.build();
        
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "200")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetLibraryItemsResponseBody _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetLibraryItemsResponseBody>() {});
                _res.withObject(Optional.ofNullable(_out));
                return _res;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "400")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetLibraryItemsBadRequest _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetLibraryItemsBadRequest>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "401")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetLibraryItemsUnauthorized _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetLibraryItemsUnauthorized>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "4XX", "5XX")) {
            // no content 
            throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "API error occurred", 
                    Utils.extractByteArrayFromBody(_httpRes));
        }
        throw new SDKError(
            _httpRes, 
            _httpRes.statusCode(), 
            "Unexpected status code received: " + _httpRes.statusCode(), 
            Utils.extractByteArrayFromBody(_httpRes));
    }



    /**
     * Refresh Metadata Of The Library
     * This endpoint Refreshes all the Metadata of the library.
     * 
     * @return The call builder
     */
    public GetRefreshLibraryMetadataRequestBuilder getRefreshLibraryMetadata() {
        return new GetRefreshLibraryMetadataRequestBuilder(this);
    }

    /**
     * Refresh Metadata Of The Library
     * This endpoint Refreshes all the Metadata of the library.
     * 
     * @param sectionKey The unique key of the Plex library. 
    Note: This is unique in the context of the Plex server.

     * @return The response from the API call
     * @throws Exception if the API call fails
     */
    public GetRefreshLibraryMetadataResponse getRefreshLibraryMetadata(
            int sectionKey) throws Exception {
        return getRefreshLibraryMetadata(Optional.empty(), sectionKey);
    }
    
    /**
     * Refresh Metadata Of The Library
     * This endpoint Refreshes all the Metadata of the library.
     * 
     * @param force Force the refresh even if the library is already being refreshed.
     * @param sectionKey The unique key of the Plex library. 
    Note: This is unique in the context of the Plex server.

     * @return The response from the API call
     * @throws Exception if the API call fails
     */
    public GetRefreshLibraryMetadataResponse getRefreshLibraryMetadata(
            Optional<? extends Force> force,
            int sectionKey) throws Exception {
        GetRefreshLibraryMetadataRequest request =
            GetRefreshLibraryMetadataRequest
                .builder()
                .force(force)
                .sectionKey(sectionKey)
                .build();
        
        String _baseUrl = Utils.templateUrl(
                this.sdkConfiguration.serverUrl, this.sdkConfiguration.getServerVariableDefaults());
        String _url = Utils.generateURL(
                GetRefreshLibraryMetadataRequest.class,
                _baseUrl,
                "/library/sections/{sectionKey}/refresh",
                request, this.sdkConfiguration.globals);
        
        HTTPRequest _req = new HTTPRequest(_url, "GET");
        _req.addHeader("Accept", "application/json")
            .addHeader("user-agent", 
                SDKConfiguration.USER_AGENT);

        _req.addQueryParams(Utils.getQueryParams(
                GetRefreshLibraryMetadataRequest.class,
                request, 
                this.sdkConfiguration.globals));

        Utils.configureSecurity(_req,  
                this.sdkConfiguration.securitySource.getSecurity());

        HTTPClient _client = this.sdkConfiguration.defaultClient;
        HttpRequest _r = 
            sdkConfiguration.hooks()
               .beforeRequest(
                  new BeforeRequestContextImpl(
                      "get-refresh-library-metadata", 
                      Optional.of(List.of()), 
                      sdkConfiguration.securitySource()),
                  _req.build());
        HttpResponse<InputStream> _httpRes;
        try {
            _httpRes = _client.send(_r);
            if (Utils.statusCodeMatches(_httpRes.statusCode(), "400", "401", "4XX", "5XX")) {
                _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "get-refresh-library-metadata",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()),
                        Optional.of(_httpRes),
                        Optional.empty());
            } else {
                _httpRes = sdkConfiguration.hooks()
                    .afterSuccess(
                        new AfterSuccessContextImpl(
                            "get-refresh-library-metadata",
                            Optional.of(List.of()), 
                            sdkConfiguration.securitySource()),
                         _httpRes);
            }
        } catch (Exception _e) {
            _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "get-refresh-library-metadata",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()), 
                        Optional.empty(),
                        Optional.of(_e));
        }
        String _contentType = _httpRes
            .headers()
            .firstValue("Content-Type")
            .orElse("application/octet-stream");
        GetRefreshLibraryMetadataResponse.Builder _resBuilder = 
            GetRefreshLibraryMetadataResponse
                .builder()
                .contentType(_contentType)
                .statusCode(_httpRes.statusCode())
                .rawResponse(_httpRes);

        GetRefreshLibraryMetadataResponse _res = _resBuilder.build();
        
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "200")) {
            // no content 
            return _res;
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "400")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetRefreshLibraryMetadataBadRequest _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetRefreshLibraryMetadataBadRequest>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "401")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetRefreshLibraryMetadataUnauthorized _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetRefreshLibraryMetadataUnauthorized>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "4XX", "5XX")) {
            // no content 
            throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "API error occurred", 
                    Utils.extractByteArrayFromBody(_httpRes));
        }
        throw new SDKError(
            _httpRes, 
            _httpRes.statusCode(), 
            "Unexpected status code received: " + _httpRes.statusCode(), 
            Utils.extractByteArrayFromBody(_httpRes));
    }



    /**
     * Search Library
     * Search for content within a specific section of the library.
     * 
     * ### Types
     * Each type in the library comes with a set of filters and sorts, aiding in building dynamic media controls:
     * 
     * - **Type Object Attributes**:
     *   - `type`: Metadata type (if standard Plex type).  
     *   - `title`: Title for this content type (e.g., "Movies").
     * 
     * - **Filter Objects**:
     *   - Subset of the media query language.
     *   - Attributes include `filter` (name), `filterType` (data type), `key` (endpoint for value range), and `title`.
     * 
     * - **Sort Objects**:
     *   - Description of sort fields.
     *   - Attributes include `defaultDirection` (asc/desc), `descKey` and `key` (sort parameters), and `title`.
     * 
     * &gt; **Note**: Filters and sorts are optional; without them, no filtering controls are rendered.
     * 
     * @return The call builder
     */
    public GetSearchLibraryRequestBuilder getSearchLibrary() {
        return new GetSearchLibraryRequestBuilder(this);
    }

    /**
     * Search Library
     * Search for content within a specific section of the library.
     * 
     * ### Types
     * Each type in the library comes with a set of filters and sorts, aiding in building dynamic media controls:
     * 
     * - **Type Object Attributes**:
     *   - `type`: Metadata type (if standard Plex type).  
     *   - `title`: Title for this content type (e.g., "Movies").
     * 
     * - **Filter Objects**:
     *   - Subset of the media query language.
     *   - Attributes include `filter` (name), `filterType` (data type), `key` (endpoint for value range), and `title`.
     * 
     * - **Sort Objects**:
     *   - Description of sort fields.
     *   - Attributes include `defaultDirection` (asc/desc), `descKey` and `key` (sort parameters), and `title`.
     * 
     * &gt; **Note**: Filters and sorts are optional; without them, no filtering controls are rendered.
     * 
     * @param sectionKey The unique key of the Plex library. 
    Note: This is unique in the context of the Plex server.

     * @param type The type of media to retrieve.
    1 = movie
    2 = show
    3 = season
    4 = episode
    E.g. A movie library will not return anything with type 3 as there are no seasons for movie libraries

     * @return The response from the API call
     * @throws Exception if the API call fails
     */
    public GetSearchLibraryResponse getSearchLibrary(
            int sectionKey,
            GetSearchLibraryQueryParamType type) throws Exception {
        GetSearchLibraryRequest request =
            GetSearchLibraryRequest
                .builder()
                .sectionKey(sectionKey)
                .type(type)
                .build();
        
        String _baseUrl = Utils.templateUrl(
                this.sdkConfiguration.serverUrl, this.sdkConfiguration.getServerVariableDefaults());
        String _url = Utils.generateURL(
                GetSearchLibraryRequest.class,
                _baseUrl,
                "/library/sections/{sectionKey}/search",
                request, this.sdkConfiguration.globals);
        
        HTTPRequest _req = new HTTPRequest(_url, "GET");
        _req.addHeader("Accept", "application/json")
            .addHeader("user-agent", 
                SDKConfiguration.USER_AGENT);

        _req.addQueryParams(Utils.getQueryParams(
                GetSearchLibraryRequest.class,
                request, 
                this.sdkConfiguration.globals));

        Utils.configureSecurity(_req,  
                this.sdkConfiguration.securitySource.getSecurity());

        HTTPClient _client = this.sdkConfiguration.defaultClient;
        HttpRequest _r = 
            sdkConfiguration.hooks()
               .beforeRequest(
                  new BeforeRequestContextImpl(
                      "get-search-library", 
                      Optional.of(List.of()), 
                      sdkConfiguration.securitySource()),
                  _req.build());
        HttpResponse<InputStream> _httpRes;
        try {
            _httpRes = _client.send(_r);
            if (Utils.statusCodeMatches(_httpRes.statusCode(), "400", "401", "4XX", "5XX")) {
                _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "get-search-library",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()),
                        Optional.of(_httpRes),
                        Optional.empty());
            } else {
                _httpRes = sdkConfiguration.hooks()
                    .afterSuccess(
                        new AfterSuccessContextImpl(
                            "get-search-library",
                            Optional.of(List.of()), 
                            sdkConfiguration.securitySource()),
                         _httpRes);
            }
        } catch (Exception _e) {
            _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "get-search-library",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()), 
                        Optional.empty(),
                        Optional.of(_e));
        }
        String _contentType = _httpRes
            .headers()
            .firstValue("Content-Type")
            .orElse("application/octet-stream");
        GetSearchLibraryResponse.Builder _resBuilder = 
            GetSearchLibraryResponse
                .builder()
                .contentType(_contentType)
                .statusCode(_httpRes.statusCode())
                .rawResponse(_httpRes);

        GetSearchLibraryResponse _res = _resBuilder.build();
        
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "200")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetSearchLibraryResponseBody _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetSearchLibraryResponseBody>() {});
                _res.withObject(Optional.ofNullable(_out));
                return _res;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "400")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetSearchLibraryBadRequest _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetSearchLibraryBadRequest>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "401")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetSearchLibraryUnauthorized _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetSearchLibraryUnauthorized>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "4XX", "5XX")) {
            // no content 
            throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "API error occurred", 
                    Utils.extractByteArrayFromBody(_httpRes));
        }
        throw new SDKError(
            _httpRes, 
            _httpRes.statusCode(), 
            "Unexpected status code received: " + _httpRes.statusCode(), 
            Utils.extractByteArrayFromBody(_httpRes));
    }



    /**
     * Search All Libraries
     * Search the provided query across all library sections, or a single section, and return matches as hubs, split up by type.
     * 
     * @return The call builder
     */
    public GetSearchAllLibrariesRequestBuilder getSearchAllLibraries() {
        return new GetSearchAllLibrariesRequestBuilder(this);
    }

    /**
     * Search All Libraries
     * Search the provided query across all library sections, or a single section, and return matches as hubs, split up by type.
     * 
     * @param request The request object containing all of the parameters for the API call.
     * @return The response from the API call
     * @throws Exception if the API call fails
     */
    public GetSearchAllLibrariesResponse getSearchAllLibraries(
            GetSearchAllLibrariesRequest request) throws Exception {
        String _baseUrl = Utils.templateUrl(
                this.sdkConfiguration.serverUrl, this.sdkConfiguration.getServerVariableDefaults());
        String _url = Utils.generateURL(
                _baseUrl,
                "/library/search");
        
        HTTPRequest _req = new HTTPRequest(_url, "GET");
        _req.addHeader("Accept", "application/json")
            .addHeader("user-agent", 
                SDKConfiguration.USER_AGENT);

        _req.addQueryParams(Utils.getQueryParams(
                GetSearchAllLibrariesRequest.class,
                request, 
                this.sdkConfiguration.globals));
        _req.addHeaders(Utils.getHeadersFromMetadata(request, this.sdkConfiguration.globals));

        Utils.configureSecurity(_req,  
                this.sdkConfiguration.securitySource.getSecurity());

        HTTPClient _client = this.sdkConfiguration.defaultClient;
        HttpRequest _r = 
            sdkConfiguration.hooks()
               .beforeRequest(
                  new BeforeRequestContextImpl(
                      "get-search-all-libraries", 
                      Optional.of(List.of()), 
                      sdkConfiguration.securitySource()),
                  _req.build());
        HttpResponse<InputStream> _httpRes;
        try {
            _httpRes = _client.send(_r);
            if (Utils.statusCodeMatches(_httpRes.statusCode(), "400", "401", "4XX", "5XX")) {
                _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "get-search-all-libraries",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()),
                        Optional.of(_httpRes),
                        Optional.empty());
            } else {
                _httpRes = sdkConfiguration.hooks()
                    .afterSuccess(
                        new AfterSuccessContextImpl(
                            "get-search-all-libraries",
                            Optional.of(List.of()), 
                            sdkConfiguration.securitySource()),
                         _httpRes);
            }
        } catch (Exception _e) {
            _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "get-search-all-libraries",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()), 
                        Optional.empty(),
                        Optional.of(_e));
        }
        String _contentType = _httpRes
            .headers()
            .firstValue("Content-Type")
            .orElse("application/octet-stream");
        GetSearchAllLibrariesResponse.Builder _resBuilder = 
            GetSearchAllLibrariesResponse
                .builder()
                .contentType(_contentType)
                .statusCode(_httpRes.statusCode())
                .rawResponse(_httpRes);

        GetSearchAllLibrariesResponse _res = _resBuilder.build();
        
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "200")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetSearchAllLibrariesResponseBody _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetSearchAllLibrariesResponseBody>() {});
                _res.withObject(Optional.ofNullable(_out));
                return _res;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "400")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetSearchAllLibrariesBadRequest _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetSearchAllLibrariesBadRequest>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "401")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetSearchAllLibrariesUnauthorized _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetSearchAllLibrariesUnauthorized>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "4XX", "5XX")) {
            // no content 
            throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "API error occurred", 
                    Utils.extractByteArrayFromBody(_httpRes));
        }
        throw new SDKError(
            _httpRes, 
            _httpRes.statusCode(), 
            "Unexpected status code received: " + _httpRes.statusCode(), 
            Utils.extractByteArrayFromBody(_httpRes));
    }



    /**
     * Get Metadata by RatingKey
     * This endpoint will return the metadata of a library item specified with the ratingKey.
     * 
     * @return The call builder
     */
    public GetMetaDataByRatingKeyRequestBuilder getMetaDataByRatingKey() {
        return new GetMetaDataByRatingKeyRequestBuilder(this);
    }

    /**
     * Get Metadata by RatingKey
     * This endpoint will return the metadata of a library item specified with the ratingKey.
     * 
     * @param ratingKey the id of the library item to return the children of.
     * @return The response from the API call
     * @throws Exception if the API call fails
     */
    public GetMetaDataByRatingKeyResponse getMetaDataByRatingKey(
            long ratingKey) throws Exception {
        GetMetaDataByRatingKeyRequest request =
            GetMetaDataByRatingKeyRequest
                .builder()
                .ratingKey(ratingKey)
                .build();
        
        String _baseUrl = Utils.templateUrl(
                this.sdkConfiguration.serverUrl, this.sdkConfiguration.getServerVariableDefaults());
        String _url = Utils.generateURL(
                GetMetaDataByRatingKeyRequest.class,
                _baseUrl,
                "/library/metadata/{ratingKey}",
                request, this.sdkConfiguration.globals);
        
        HTTPRequest _req = new HTTPRequest(_url, "GET");
        _req.addHeader("Accept", "application/json")
            .addHeader("user-agent", 
                SDKConfiguration.USER_AGENT);

        Utils.configureSecurity(_req,  
                this.sdkConfiguration.securitySource.getSecurity());

        HTTPClient _client = this.sdkConfiguration.defaultClient;
        HttpRequest _r = 
            sdkConfiguration.hooks()
               .beforeRequest(
                  new BeforeRequestContextImpl(
                      "get-meta-data-by-rating-key", 
                      Optional.of(List.of()), 
                      sdkConfiguration.securitySource()),
                  _req.build());
        HttpResponse<InputStream> _httpRes;
        try {
            _httpRes = _client.send(_r);
            if (Utils.statusCodeMatches(_httpRes.statusCode(), "400", "401", "4XX", "5XX")) {
                _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "get-meta-data-by-rating-key",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()),
                        Optional.of(_httpRes),
                        Optional.empty());
            } else {
                _httpRes = sdkConfiguration.hooks()
                    .afterSuccess(
                        new AfterSuccessContextImpl(
                            "get-meta-data-by-rating-key",
                            Optional.of(List.of()), 
                            sdkConfiguration.securitySource()),
                         _httpRes);
            }
        } catch (Exception _e) {
            _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "get-meta-data-by-rating-key",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()), 
                        Optional.empty(),
                        Optional.of(_e));
        }
        String _contentType = _httpRes
            .headers()
            .firstValue("Content-Type")
            .orElse("application/octet-stream");
        GetMetaDataByRatingKeyResponse.Builder _resBuilder = 
            GetMetaDataByRatingKeyResponse
                .builder()
                .contentType(_contentType)
                .statusCode(_httpRes.statusCode())
                .rawResponse(_httpRes);

        GetMetaDataByRatingKeyResponse _res = _resBuilder.build();
        
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "200")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetMetaDataByRatingKeyResponseBody _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetMetaDataByRatingKeyResponseBody>() {});
                _res.withObject(Optional.ofNullable(_out));
                return _res;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "400")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetMetaDataByRatingKeyBadRequest _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetMetaDataByRatingKeyBadRequest>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "401")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetMetaDataByRatingKeyUnauthorized _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetMetaDataByRatingKeyUnauthorized>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "4XX", "5XX")) {
            // no content 
            throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "API error occurred", 
                    Utils.extractByteArrayFromBody(_httpRes));
        }
        throw new SDKError(
            _httpRes, 
            _httpRes.statusCode(), 
            "Unexpected status code received: " + _httpRes.statusCode(), 
            Utils.extractByteArrayFromBody(_httpRes));
    }



    /**
     * Get Items Children
     * This endpoint will return the children of of a library item specified with the ratingKey.
     * 
     * @return The call builder
     */
    public GetMetadataChildrenRequestBuilder getMetadataChildren() {
        return new GetMetadataChildrenRequestBuilder(this);
    }

    /**
     * Get Items Children
     * This endpoint will return the children of of a library item specified with the ratingKey.
     * 
     * @param ratingKey the id of the library item to return the children of.
     * @return The response from the API call
     * @throws Exception if the API call fails
     */
    public GetMetadataChildrenResponse getMetadataChildren(
            double ratingKey) throws Exception {
        return getMetadataChildren(ratingKey, Optional.empty());
    }
    
    /**
     * Get Items Children
     * This endpoint will return the children of of a library item specified with the ratingKey.
     * 
     * @param ratingKey the id of the library item to return the children of.
     * @param includeElements Adds additional elements to the response. Supported types are (Stream)

     * @return The response from the API call
     * @throws Exception if the API call fails
     */
    public GetMetadataChildrenResponse getMetadataChildren(
            double ratingKey,
            Optional<String> includeElements) throws Exception {
        GetMetadataChildrenRequest request =
            GetMetadataChildrenRequest
                .builder()
                .ratingKey(ratingKey)
                .includeElements(includeElements)
                .build();
        
        String _baseUrl = Utils.templateUrl(
                this.sdkConfiguration.serverUrl, this.sdkConfiguration.getServerVariableDefaults());
        String _url = Utils.generateURL(
                GetMetadataChildrenRequest.class,
                _baseUrl,
                "/library/metadata/{ratingKey}/children",
                request, this.sdkConfiguration.globals);
        
        HTTPRequest _req = new HTTPRequest(_url, "GET");
        _req.addHeader("Accept", "application/json")
            .addHeader("user-agent", 
                SDKConfiguration.USER_AGENT);

        _req.addQueryParams(Utils.getQueryParams(
                GetMetadataChildrenRequest.class,
                request, 
                this.sdkConfiguration.globals));

        Utils.configureSecurity(_req,  
                this.sdkConfiguration.securitySource.getSecurity());

        HTTPClient _client = this.sdkConfiguration.defaultClient;
        HttpRequest _r = 
            sdkConfiguration.hooks()
               .beforeRequest(
                  new BeforeRequestContextImpl(
                      "getMetadataChildren", 
                      Optional.of(List.of()), 
                      sdkConfiguration.securitySource()),
                  _req.build());
        HttpResponse<InputStream> _httpRes;
        try {
            _httpRes = _client.send(_r);
            if (Utils.statusCodeMatches(_httpRes.statusCode(), "400", "401", "4XX", "5XX")) {
                _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "getMetadataChildren",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()),
                        Optional.of(_httpRes),
                        Optional.empty());
            } else {
                _httpRes = sdkConfiguration.hooks()
                    .afterSuccess(
                        new AfterSuccessContextImpl(
                            "getMetadataChildren",
                            Optional.of(List.of()), 
                            sdkConfiguration.securitySource()),
                         _httpRes);
            }
        } catch (Exception _e) {
            _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "getMetadataChildren",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()), 
                        Optional.empty(),
                        Optional.of(_e));
        }
        String _contentType = _httpRes
            .headers()
            .firstValue("Content-Type")
            .orElse("application/octet-stream");
        GetMetadataChildrenResponse.Builder _resBuilder = 
            GetMetadataChildrenResponse
                .builder()
                .contentType(_contentType)
                .statusCode(_httpRes.statusCode())
                .rawResponse(_httpRes);

        GetMetadataChildrenResponse _res = _resBuilder.build();
        
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "200")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetMetadataChildrenResponseBody _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetMetadataChildrenResponseBody>() {});
                _res.withObject(Optional.ofNullable(_out));
                return _res;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "400")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetMetadataChildrenBadRequest _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetMetadataChildrenBadRequest>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "401")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetMetadataChildrenUnauthorized _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetMetadataChildrenUnauthorized>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "4XX", "5XX")) {
            // no content 
            throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "API error occurred", 
                    Utils.extractByteArrayFromBody(_httpRes));
        }
        throw new SDKError(
            _httpRes, 
            _httpRes.statusCode(), 
            "Unexpected status code received: " + _httpRes.statusCode(), 
            Utils.extractByteArrayFromBody(_httpRes));
    }



    /**
     * Get Top Watched Content
     * This endpoint will return the top watched content from libraries of a certain type
     * 
     * @return The call builder
     */
    public GetTopWatchedContentRequestBuilder getTopWatchedContent() {
        return new GetTopWatchedContentRequestBuilder(this);
    }

    /**
     * Get Top Watched Content
     * This endpoint will return the top watched content from libraries of a certain type
     * 
     * @param type The type of media to retrieve.
    1 = movie
    2 = show
    3 = season
    4 = episode
    E.g. A movie library will not return anything with type 3 as there are no seasons for movie libraries

     * @return The response from the API call
     * @throws Exception if the API call fails
     */
    public GetTopWatchedContentResponse getTopWatchedContent(
            GetTopWatchedContentQueryParamType type) throws Exception {
        return getTopWatchedContent(Optional.empty(), type);
    }
    
    /**
     * Get Top Watched Content
     * This endpoint will return the top watched content from libraries of a certain type
     * 
     * @param includeGuids Adds the Guids object to the response

     * @param type The type of media to retrieve.
    1 = movie
    2 = show
    3 = season
    4 = episode
    E.g. A movie library will not return anything with type 3 as there are no seasons for movie libraries

     * @return The response from the API call
     * @throws Exception if the API call fails
     */
    public GetTopWatchedContentResponse getTopWatchedContent(
            Optional<Long> includeGuids,
            GetTopWatchedContentQueryParamType type) throws Exception {
        GetTopWatchedContentRequest request =
            GetTopWatchedContentRequest
                .builder()
                .includeGuids(includeGuids)
                .type(type)
                .build();
        
        String _baseUrl = Utils.templateUrl(
                this.sdkConfiguration.serverUrl, this.sdkConfiguration.getServerVariableDefaults());
        String _url = Utils.generateURL(
                _baseUrl,
                "/library/all/top");
        
        HTTPRequest _req = new HTTPRequest(_url, "GET");
        _req.addHeader("Accept", "application/json")
            .addHeader("user-agent", 
                SDKConfiguration.USER_AGENT);

        _req.addQueryParams(Utils.getQueryParams(
                GetTopWatchedContentRequest.class,
                request, 
                this.sdkConfiguration.globals));

        Utils.configureSecurity(_req,  
                this.sdkConfiguration.securitySource.getSecurity());

        HTTPClient _client = this.sdkConfiguration.defaultClient;
        HttpRequest _r = 
            sdkConfiguration.hooks()
               .beforeRequest(
                  new BeforeRequestContextImpl(
                      "getTopWatchedContent", 
                      Optional.of(List.of()), 
                      sdkConfiguration.securitySource()),
                  _req.build());
        HttpResponse<InputStream> _httpRes;
        try {
            _httpRes = _client.send(_r);
            if (Utils.statusCodeMatches(_httpRes.statusCode(), "400", "401", "4XX", "5XX")) {
                _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "getTopWatchedContent",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()),
                        Optional.of(_httpRes),
                        Optional.empty());
            } else {
                _httpRes = sdkConfiguration.hooks()
                    .afterSuccess(
                        new AfterSuccessContextImpl(
                            "getTopWatchedContent",
                            Optional.of(List.of()), 
                            sdkConfiguration.securitySource()),
                         _httpRes);
            }
        } catch (Exception _e) {
            _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "getTopWatchedContent",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()), 
                        Optional.empty(),
                        Optional.of(_e));
        }
        String _contentType = _httpRes
            .headers()
            .firstValue("Content-Type")
            .orElse("application/octet-stream");
        GetTopWatchedContentResponse.Builder _resBuilder = 
            GetTopWatchedContentResponse
                .builder()
                .contentType(_contentType)
                .statusCode(_httpRes.statusCode())
                .rawResponse(_httpRes);

        GetTopWatchedContentResponse _res = _resBuilder.build();
        
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "200")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetTopWatchedContentResponseBody _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetTopWatchedContentResponseBody>() {});
                _res.withObject(Optional.ofNullable(_out));
                return _res;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "400")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetTopWatchedContentBadRequest _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetTopWatchedContentBadRequest>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "401")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetTopWatchedContentUnauthorized _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetTopWatchedContentUnauthorized>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "4XX", "5XX")) {
            // no content 
            throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "API error occurred", 
                    Utils.extractByteArrayFromBody(_httpRes));
        }
        throw new SDKError(
            _httpRes, 
            _httpRes.statusCode(), 
            "Unexpected status code received: " + _httpRes.statusCode(), 
            Utils.extractByteArrayFromBody(_httpRes));
    }



    /**
     * Get On Deck
     * This endpoint will return the on deck content.
     * 
     * @return The call builder
     */
    public GetOnDeckRequestBuilder getOnDeck() {
        return new GetOnDeckRequestBuilder(this);
    }

    /**
     * Get On Deck
     * This endpoint will return the on deck content.
     * 
     * @return The response from the API call
     * @throws Exception if the API call fails
     */
    public GetOnDeckResponse getOnDeckDirect() throws Exception {
        String _baseUrl = Utils.templateUrl(
                this.sdkConfiguration.serverUrl, this.sdkConfiguration.getServerVariableDefaults());
        String _url = Utils.generateURL(
                _baseUrl,
                "/library/onDeck");
        
        HTTPRequest _req = new HTTPRequest(_url, "GET");
        _req.addHeader("Accept", "application/json")
            .addHeader("user-agent", 
                SDKConfiguration.USER_AGENT);

        Utils.configureSecurity(_req,  
                this.sdkConfiguration.securitySource.getSecurity());

        HTTPClient _client = this.sdkConfiguration.defaultClient;
        HttpRequest _r = 
            sdkConfiguration.hooks()
               .beforeRequest(
                  new BeforeRequestContextImpl(
                      "getOnDeck", 
                      Optional.of(List.of()), 
                      sdkConfiguration.securitySource()),
                  _req.build());
        HttpResponse<InputStream> _httpRes;
        try {
            _httpRes = _client.send(_r);
            if (Utils.statusCodeMatches(_httpRes.statusCode(), "400", "401", "4XX", "5XX")) {
                _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "getOnDeck",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()),
                        Optional.of(_httpRes),
                        Optional.empty());
            } else {
                _httpRes = sdkConfiguration.hooks()
                    .afterSuccess(
                        new AfterSuccessContextImpl(
                            "getOnDeck",
                            Optional.of(List.of()), 
                            sdkConfiguration.securitySource()),
                         _httpRes);
            }
        } catch (Exception _e) {
            _httpRes = sdkConfiguration.hooks()
                    .afterError(
                        new AfterErrorContextImpl(
                            "getOnDeck",
                            Optional.of(List.of()),
                            sdkConfiguration.securitySource()), 
                        Optional.empty(),
                        Optional.of(_e));
        }
        String _contentType = _httpRes
            .headers()
            .firstValue("Content-Type")
            .orElse("application/octet-stream");
        GetOnDeckResponse.Builder _resBuilder = 
            GetOnDeckResponse
                .builder()
                .contentType(_contentType)
                .statusCode(_httpRes.statusCode())
                .rawResponse(_httpRes);

        GetOnDeckResponse _res = _resBuilder.build();
        
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "200")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetOnDeckResponseBody _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetOnDeckResponseBody>() {});
                _res.withObject(Optional.ofNullable(_out));
                return _res;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "400")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetOnDeckBadRequest _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetOnDeckBadRequest>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "401")) {
            if (Utils.contentTypeMatches(_contentType, "application/json")) {
                GetOnDeckUnauthorized _out = Utils.mapper().readValue(
                    Utils.toUtf8AndClose(_httpRes.body()),
                    new TypeReference<GetOnDeckUnauthorized>() {});
                    _out.withRawResponse(Optional.ofNullable(_httpRes));
                
                throw _out;
            } else {
                throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "Unexpected content-type received: " + _contentType, 
                    Utils.extractByteArrayFromBody(_httpRes));
            }
        }
        if (Utils.statusCodeMatches(_httpRes.statusCode(), "4XX", "5XX")) {
            // no content 
            throw new SDKError(
                    _httpRes, 
                    _httpRes.statusCode(), 
                    "API error occurred", 
                    Utils.extractByteArrayFromBody(_httpRes));
        }
        throw new SDKError(
            _httpRes, 
            _httpRes.statusCode(), 
            "Unexpected status code received: " + _httpRes.statusCode(), 
            Utils.extractByteArrayFromBody(_httpRes));
    }

}
