/**
 * This file was automatically generated by openapi-codegeneration.
 * DO NOT MODIFY IT BY HAND. Instead, modify the source OpenAPI file,
 * and run openapi-codegeneration to regenerate this file.
 */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/ban-ts-comment */
import fetch from 'node-fetch';
import * as RequestValidation from './requestValidation.js';
import * as Types from './types.js';
/**
 * This error class should be used if an error occurs during validation of a request/response.
 * @category Errors
 */
export class ValidationError extends Error {
    errors;
    constructor(message, errors) {
        super(message);
        this.name = 'ValidationError';
        this.errors = errors;
    }
}
/**
 * This error class should be used if an error occurs while fetching a request.
 * @category Errors
 */
export class FetchError extends Error {
    constructor(message) {
        super(message);
        this.name = 'FetchError';
    }
}
/**
 * This error class should be used if the response of the server has a status
 * greater than or equal to 400. This error should contain the validated response.
 * @category Errors
 */
export class UnsuccessfulRequestError extends Error {
    response;
    constructor(message, response) {
        super(message);
        this.response = response;
        this.name = 'UnsuccessfulRequestError';
    }
}
/**
 * This error class should be used if the validation of an url fails.
 * @category Errors
 */
export class InvalidUrlError extends Error {
    constructor(message) {
        super(message);
        this.name = 'InvalidUrlError';
    }
}
/**
 * This function attempts to parse a Response as ResponseData.
 */
async function parseResponse(response) {
    let text = null;
    try {
        text = await response.text();
        const json = JSON.parse(text);
        return { status: response.status, body: json };
    }
    catch {
        return { status: response.status, body: text };
    }
}
/**
 * This function checks if a string is a valid http url.
 * @param string The string to be checked.
 * @returns True if the string is a valid http url.
 */
function isValidHttpUrl(string) {
    let url;
    try {
        url = new URL(string);
    }
    catch (_) {
        return false;
    }
    return url.protocol === 'http:' || url.protocol === 'https:';
}
/**
 * This function takes an url and a pattern for the requested endpoint and parses the contained path parameters.
 * @param url The url to be parsed.
 * @param endpoint Pattern of the requested endpoint.
 * @throws {InvalidUrlError} Thrown if the provided url does not end with the provided endpoint.
 * @returns An array containing all parsed path parameters in order of appearance.
 * @example
 * // returns ["username", "role_name"]
 * parsePathParameters("https://api.example.com/users/username/roles/role_name", "/users/{}/roles/{}")
 */
function parsePathParameters(url, endpoint) {
    const parameterRegex = '([^\/]+)';
    const regex = new RegExp(endpoint.replaceAll('{}', parameterRegex) + '(?:.(?!\\\\))?$');
    const matches = url.match(regex);
    if (!matches)
        throw new InvalidUrlError('Url does not end with the provided endpoint');
    return matches.slice(1);
}
/**
 * This function validates a given http url and parses its path parameters.
 * @param url The url to be validated.
 * @param endpoint Pattern of the requested endpoint.
 * @throws {InvalidUrlError} Thrown if the validation of the provided url fails.
 * @returns An array containing all parsed path parameters in order of appearance (see {@link parsePathParameters}).
 * @example
 * // returns ["username", "role_name"]
 * validateUrl("https://api.example.com/users/username/roles/role_name", "/users/{}/roles/{}")
 */
function validateUrl(url, endpoint) {
    if (!isValidHttpUrl(url))
        throw new InvalidUrlError('Provided url is not a valid http url');
    return parsePathParameters(url, endpoint);
}
/**
 * This function appends a given endpoint to an url.
 * @param url The url to append the endpoint to.
 * @param endpoint The endpoint to be appended.
 * @example
 * // returns "https://api.example.com/devices/device_id/token"
 * appendToUrl("https://api.example.com/devices/device_id", "/token")
 * @example
 * // returns "https://api.example.com/devices/device_id/token"
 * appendToUrl("https://api.example.com/devices/device_id/", "/token")
 * @returns The url with the appended endpoint.
 */
function appendToUrl(url, endpoint) {
    return url.endsWith('/') ? `${url.slice(0, -1)}${endpoint}` : `${url}${endpoint}`;
}
/**
 * Client for the use of the Crosslab API
 * @category Client
 */
export class Client {
    baseUrl;
    serviceUrl;
    accessToken;
    fixedHeaders;
    fetch = async (url, init) => {
        let raw_response;
        const parsedUrl = new URL(url.toString());
        try {
            if (parsedUrl.toString().startsWith(this.baseUrl) ||
                parsedUrl.toString().startsWith(this.serviceUrl)) {
                raw_response = await fetch(url, init);
            }
            else {
                raw_response = await fetch(appendToUrl(this.baseUrl, '/proxy?' + new URLSearchParams([['URL', url.toString()]]).toString()), init);
            }
        }
        catch (error) {
            if (error instanceof Error) {
                throw new FetchError(error.message);
            }
            else if (typeof error === 'string') {
                throw new FetchError(error);
            }
            else {
                throw new FetchError('Something went wrong while trying to fetch the request');
            }
        }
        return await parseResponse(raw_response);
    };
    /**
     * @category Constructors
     */
    constructor(baseUrl, options) {
        this.baseUrl = new URL(baseUrl).toString().slice(0, -1);
        this.serviceUrl = new URL(options.serviceUrl ?? this.baseUrl).toString().slice(0, -1);
        this.accessToken = options.accessToken ?? '';
        this.fixedHeaders = options.fixedHeaders ?? [];
    }
    /**
     * List devices
     *
     * @param options.url
     * Url of the  to be used.
     *
     * @throws {@link FetchError | FetchError }
     * Thrown if fetch fails.
     * @throws {@link ValidationError | ValidationError }
     * Thrown if the request/response validation fails.
     * @throws {@link InvalidUrlError | InvalidUrlError }
     * Thrown if the provided url is not valid for this request.
     * @throws {@link UnsuccessfulRequestError | UnsuccessfulRequestError }
     * Thrown if response is validated but has status greater than or equal to 400.
     *
     * @returns
     * The list of all devices.
     */
    async listDevices(options) {
        const url = appendToUrl(options?.url ?? this.baseUrl, '/devices');
        if (!RequestValidation.validateListDevicesInput())
            throw new ValidationError('Request validation failed!', RequestValidation.validateListDevicesInput.errors);
        const authorization = `Bearer ${this.accessToken}`;
        const response = await this.fetch(new URL(url).toString().replace(this.baseUrl, this.serviceUrl), {
            method: 'GET',
            headers: [
                ['Content-Type', 'application/json'],
                ['Authorization', authorization],
                ...this.fixedHeaders,
                ...(options?.headers ?? []),
            ],
        });
        if (!RequestValidation.validateListDevicesOutput(response))
            throw new ValidationError('Response validation failed!', RequestValidation.validateListDevicesOutput.errors);
        if (Types.isErrorResponse(response))
            throw new UnsuccessfulRequestError(`Server returned response with status ${response.status}`, response);
        return response.body;
    }
    /**
     * Create a new device
     *
     * @param device
     * The device to be created.
     * @param options.changedUrl
     * **An URL that will be called once the device changes.**
     *
     * Once the device was given a changedUrl parameter the contained URL will be called every time a device is changed
     * as long as every callback resolves with a successful status code.
     *
     * If the callback fails the url MIGHT not be called in the future.
     *
     * There can be multiple callbacks registered with the same device.
     * @param options.url
     * Url of the  to be used.
     *
     * @throws {@link FetchError | FetchError }
     * Thrown if fetch fails.
     * @throws {@link ValidationError | ValidationError }
     * Thrown if the request/response validation fails.
     * @throws {@link InvalidUrlError | InvalidUrlError }
     * Thrown if the provided url is not valid for this request.
     * @throws {@link UnsuccessfulRequestError | UnsuccessfulRequestError }
     * Thrown if response is validated but has status greater than or equal to 400.
     *
     * @returns
     * The device was created. A JSON representation of the new device is returned.
     */
    async createDevice(device, options) {
        const url = appendToUrl(options?.url ?? this.baseUrl, '/devices');
        const body = device;
        const parameters = {
            changedUrl: options?.changedUrl,
        };
        const query = [];
        if (parameters['changedUrl'])
            query.push(['changedUrl', parameters['changedUrl'].toString()]);
        if (!RequestValidation.validateCreateDeviceInput(parameters, body))
            throw new ValidationError('Request validation failed!', RequestValidation.validateCreateDeviceInput.errors);
        const authorization = `Bearer ${this.accessToken}`;
        const response = await this.fetch(new URL(url).toString().replace(this.baseUrl, this.serviceUrl) +
            '?' +
            new URLSearchParams(query), {
            method: 'POST',
            headers: [
                ['Content-Type', 'application/json'],
                ['Authorization', authorization],
                ...this.fixedHeaders,
                ...(options?.headers ?? []),
            ],
            body: JSON.stringify(body),
        });
        if (!RequestValidation.validateCreateDeviceOutput(response))
            throw new ValidationError('Response validation failed!', RequestValidation.validateCreateDeviceOutput.errors);
        if (Types.isErrorResponse(response))
            throw new UnsuccessfulRequestError(`Server returned response with status ${response.status}`, response);
        return response.body;
    }
    /**
     * View a registered device
     *
     * @param url
     * Url of the resource to be accessed.
     * @param options.flat_group
     * If true the returned device group will only contain concrete devices. I.e. any subgroups will be flattend.
     *
     * @throws {@link FetchError | FetchError }
     * Thrown if fetch fails.
     * @throws {@link ValidationError | ValidationError }
     * Thrown if the request/response validation fails.
     * @throws {@link InvalidUrlError | InvalidUrlError }
     * Thrown if the provided url is not valid for this request.
     * @throws {@link UnsuccessfulRequestError | UnsuccessfulRequestError }
     * Thrown if response is validated but has status greater than or equal to 400.
     *
     * @returns
     * The JSON Representation of the device.
     */
    async getDevice(url, options) {
        const urlSuffix = '/devices/{}'.split('{}').at(-1) ?? '';
        if (urlSuffix && !url.endsWith(urlSuffix))
            url = appendToUrl(url, urlSuffix);
        const [device_id] = validateUrl(new URL(url).toString(), '/devices/{}');
        const parameters = {
            device_id: device_id,
            flat_group: options?.flat_group,
        };
        const query = [];
        if (parameters['flat_group'])
            query.push(['flat_group', parameters['flat_group'].toString()]);
        if (!RequestValidation.validateGetDeviceInput(parameters))
            throw new ValidationError('Request validation failed!', RequestValidation.validateGetDeviceInput.errors);
        const authorization = `Bearer ${this.accessToken}`;
        const response = await this.fetch(new URL(url).toString().replace(this.baseUrl, this.serviceUrl) +
            '?' +
            new URLSearchParams(query), {
            method: 'GET',
            headers: [
                ['Content-Type', 'application/json'],
                ['Authorization', authorization],
                ...this.fixedHeaders,
                ...(options?.headers ?? []),
            ],
        });
        if (!RequestValidation.validateGetDeviceOutput(response))
            throw new ValidationError('Response validation failed!', RequestValidation.validateGetDeviceOutput.errors);
        if (Types.isErrorResponse(response))
            throw new UnsuccessfulRequestError(`Server returned response with status ${response.status}`, response);
        return response.body;
    }
    /**
     * Update an existing device
     *
     * @param url
     * Url of the resource to be accessed.
     * @param deviceUpdate
     * Updated device.
     * @param options.changedUrl
     * **An URL that will be called once the device changes.**
     *
     * Once the device was given a changedUrl parameter the contained URL will be called every time a device is changed
     * as long as every callback resolves with a successful status code.
     *
     * If the callback fails the url MIGHT not be called in the future.
     *
     * There can be multiple callbacks registered with the same device.
     * @param options.deletedUrl
     * **An URL that will be called once the device is deleted.**
     *
     * Once the device was given a deletedUrl parameter the contained URL will be called once a device is deleted.
     *
     * There can be multiple callbacks registered with the same device.
     *
     * @throws {@link FetchError | FetchError }
     * Thrown if fetch fails.
     * @throws {@link ValidationError | ValidationError }
     * Thrown if the request/response validation fails.
     * @throws {@link InvalidUrlError | InvalidUrlError }
     * Thrown if the provided url is not valid for this request.
     * @throws {@link UnsuccessfulRequestError | UnsuccessfulRequestError }
     * Thrown if response is validated but has status greater than or equal to 400.
     *
     * @returns
     * The JSON Representation of the changed device.
     */
    async updateDevice(url, deviceUpdate, options) {
        const urlSuffix = '/devices/{}'.split('{}').at(-1) ?? '';
        if (urlSuffix && !url.endsWith(urlSuffix))
            url = appendToUrl(url, urlSuffix);
        const [device_id] = validateUrl(new URL(url).toString(), '/devices/{}');
        const body = deviceUpdate;
        const parameters = {
            device_id: device_id,
            changedUrl: options?.changedUrl,
            deletedUrl: options?.deletedUrl,
        };
        const query = [];
        if (parameters['changedUrl'])
            query.push(['changedUrl', parameters['changedUrl'].toString()]);
        if (parameters['deletedUrl'])
            query.push(['deletedUrl', parameters['deletedUrl'].toString()]);
        if (!RequestValidation.validateUpdateDeviceInput(parameters, body))
            throw new ValidationError('Request validation failed!', RequestValidation.validateUpdateDeviceInput.errors);
        const authorization = `Bearer ${this.accessToken}`;
        const response = await this.fetch(new URL(url).toString().replace(this.baseUrl, this.serviceUrl) +
            '?' +
            new URLSearchParams(query), {
            method: 'PATCH',
            headers: [
                ['Content-Type', 'application/json'],
                ['Authorization', authorization],
                ...this.fixedHeaders,
                ...(options?.headers ?? []),
            ],
            body: JSON.stringify(body),
        });
        if (!RequestValidation.validateUpdateDeviceOutput(response))
            throw new ValidationError('Response validation failed!', RequestValidation.validateUpdateDeviceOutput.errors);
        if (Types.isErrorResponse(response))
            throw new UnsuccessfulRequestError(`Server returned response with status ${response.status}`, response);
        return response.body;
    }
    /**
     * Delete a registered device
     *
     * @param url
     * Url of the resource to be accessed.
     *
     * @throws {@link FetchError | FetchError }
     * Thrown if fetch fails.
     * @throws {@link ValidationError | ValidationError }
     * Thrown if the request/response validation fails.
     * @throws {@link InvalidUrlError | InvalidUrlError }
     * Thrown if the provided url is not valid for this request.
     * @throws {@link UnsuccessfulRequestError | UnsuccessfulRequestError }
     * Thrown if response is validated but has status greater than or equal to 400.
     *
     * @returns
     * The device was deleted.
     */
    async deleteDevice(url, options) {
        const urlSuffix = '/devices/{}'.split('{}').at(-1) ?? '';
        if (urlSuffix && !url.endsWith(urlSuffix))
            url = appendToUrl(url, urlSuffix);
        const [device_id] = validateUrl(new URL(url).toString(), '/devices/{}');
        const parameters = {
            device_id: device_id,
        };
        if (!RequestValidation.validateDeleteDeviceInput(parameters))
            throw new ValidationError('Request validation failed!', RequestValidation.validateDeleteDeviceInput.errors);
        const authorization = `Bearer ${this.accessToken}`;
        const response = await this.fetch(new URL(url).toString().replace(this.baseUrl, this.serviceUrl), {
            method: 'DELETE',
            headers: [
                ['Content-Type', 'application/json'],
                ['Authorization', authorization],
                ...this.fixedHeaders,
                ...(options?.headers ?? []),
            ],
        });
        if (!RequestValidation.validateDeleteDeviceOutput(response))
            throw new ValidationError('Response validation failed!', RequestValidation.validateDeleteDeviceOutput.errors);
        if (Types.isErrorResponse(response))
            throw new UnsuccessfulRequestError(`Server returned response with status ${response.status}`, response);
    }
    /**
     * Instantiate a cloud instantiable device
     *
     * @param url
     * Url of the resource to be accessed.
     * @param options.changedUrl
     * **An URL that will be called once the device changes.**
     *
     * Once the device was given a changedUrl parameter the contained URL will be called every time a device is changed
     * as long as every callback resolves with a successful status code.
     *
     * If the callback fails the url MIGHT not be called in the future.
     *
     * There can be multiple callbacks registered with the same device.
     *
     * @throws {@link FetchError | FetchError }
     * Thrown if fetch fails.
     * @throws {@link ValidationError | ValidationError }
     * Thrown if the request/response validation fails.
     * @throws {@link InvalidUrlError | InvalidUrlError }
     * Thrown if the provided url is not valid for this request.
     * @throws {@link UnsuccessfulRequestError | UnsuccessfulRequestError }
     * Thrown if response is validated but has status greater than or equal to 400.
     *
     * @returns
     * The JSON Representation of the created instance.
     */
    async instantiateDevice(url, options) {
        const urlSuffix = '/devices/{}'.split('{}').at(-1) ?? '';
        if (urlSuffix && !url.endsWith(urlSuffix))
            url = appendToUrl(url, urlSuffix);
        const [device_id] = validateUrl(new URL(url).toString(), '/devices/{}');
        const parameters = {
            device_id: device_id,
            changedUrl: options?.changedUrl,
        };
        const query = [];
        if (parameters['changedUrl'])
            query.push(['changedUrl', parameters['changedUrl'].toString()]);
        if (!RequestValidation.validateInstantiateDeviceInput(parameters))
            throw new ValidationError('Request validation failed!', RequestValidation.validateInstantiateDeviceInput.errors);
        const authorization = `Bearer ${this.accessToken}`;
        const response = await this.fetch(new URL(url).toString().replace(this.baseUrl, this.serviceUrl) +
            '?' +
            new URLSearchParams(query), {
            method: 'POST',
            headers: [
                ['Content-Type', 'application/json'],
                ['Authorization', authorization],
                ...this.fixedHeaders,
                ...(options?.headers ?? []),
            ],
        });
        if (!RequestValidation.validateInstantiateDeviceOutput(response))
            throw new ValidationError('Response validation failed!', RequestValidation.validateInstantiateDeviceOutput.errors);
        if (Types.isErrorResponse(response))
            throw new UnsuccessfulRequestError(`Server returned response with status ${response.status}`, response);
        return response.body;
    }
    /**
     * Get the availability of a device
     *
     * @param url
     * Url of the resource to be accessed.
     * @param options.startTime
     * Start time of the requested availability
     * @param options.endTime
     * End time of the requested availability
     *
     * @throws {@link FetchError | FetchError }
     * Thrown if fetch fails.
     * @throws {@link ValidationError | ValidationError }
     * Thrown if the request/response validation fails.
     * @throws {@link InvalidUrlError | InvalidUrlError }
     * Thrown if the provided url is not valid for this request.
     * @throws {@link UnsuccessfulRequestError | UnsuccessfulRequestError }
     * Thrown if response is validated but has status greater than or equal to 400.
     *
     * @returns
     * The JSON Representation of the availability of the device.
     */
    async getDeviceAvailability(url, options) {
        const urlSuffix = '/devices/{}/availability'.split('{}').at(-1) ?? '';
        if (urlSuffix && !url.endsWith(urlSuffix))
            url = appendToUrl(url, urlSuffix);
        const [device_id] = validateUrl(new URL(url).toString(), '/devices/{}/availability');
        const parameters = {
            device_id: device_id,
            startTime: options?.startTime,
            endTime: options?.endTime,
        };
        const query = [];
        if (parameters['startTime'])
            query.push(['startTime', parameters['startTime'].toString()]);
        if (parameters['endTime'])
            query.push(['endTime', parameters['endTime'].toString()]);
        if (!RequestValidation.validateGetDeviceAvailabilityInput(parameters))
            throw new ValidationError('Request validation failed!', RequestValidation.validateGetDeviceAvailabilityInput.errors);
        const authorization = `Bearer ${this.accessToken}`;
        const response = await this.fetch(new URL(url).toString().replace(this.baseUrl, this.serviceUrl) +
            '?' +
            new URLSearchParams(query), {
            method: 'GET',
            headers: [
                ['Content-Type', 'application/json'],
                ['Authorization', authorization],
                ...this.fixedHeaders,
                ...(options?.headers ?? []),
            ],
        });
        if (!RequestValidation.validateGetDeviceAvailabilityOutput(response))
            throw new ValidationError('Response validation failed!', RequestValidation.validateGetDeviceAvailabilityOutput.errors);
        if (Types.isErrorResponse(response))
            throw new UnsuccessfulRequestError(`Server returned response with status ${response.status}`, response);
        return response.body;
    }
    /**
     * Delete the availability rules of a device
     *
     * @param url
     * Url of the resource to be accessed.
     *
     * @throws {@link FetchError | FetchError }
     * Thrown if fetch fails.
     * @throws {@link ValidationError | ValidationError }
     * Thrown if the request/response validation fails.
     * @throws {@link InvalidUrlError | InvalidUrlError }
     * Thrown if the provided url is not valid for this request.
     * @throws {@link UnsuccessfulRequestError | UnsuccessfulRequestError }
     * Thrown if response is validated but has status greater than or equal to 400.
     *
     * @returns
     * The availability rules of the device were deleted successfully.
     */
    async deleteDeviceAvailabilityRules(url, options) {
        const urlSuffix = '/devices/{}/availability'.split('{}').at(-1) ?? '';
        if (urlSuffix && !url.endsWith(urlSuffix))
            url = appendToUrl(url, urlSuffix);
        const [device_id] = validateUrl(new URL(url).toString(), '/devices/{}/availability');
        const parameters = {
            device_id: device_id,
        };
        if (!RequestValidation.validateDeleteDeviceAvailabilityRulesInput(parameters))
            throw new ValidationError('Request validation failed!', RequestValidation.validateDeleteDeviceAvailabilityRulesInput.errors);
        const authorization = `Bearer ${this.accessToken}`;
        const response = await this.fetch(new URL(url).toString().replace(this.baseUrl, this.serviceUrl), {
            method: 'DELETE',
            headers: [
                ['Content-Type', 'application/json'],
                ['Authorization', authorization],
                ...this.fixedHeaders,
                ...(options?.headers ?? []),
            ],
        });
        if (!RequestValidation.validateDeleteDeviceAvailabilityRulesOutput(response))
            throw new ValidationError('Response validation failed!', RequestValidation.validateDeleteDeviceAvailabilityRulesOutput.errors);
        if (Types.isErrorResponse(response))
            throw new UnsuccessfulRequestError(`Server returned response with status ${response.status}`, response);
    }
    /**
     * Add availability rules for a device
     *
     * @param url
     * Url of the resource to be accessed.
     * @param availabilityRules
     * The availability rules to be applied.
     *
     * @throws {@link FetchError | FetchError }
     * Thrown if fetch fails.
     * @throws {@link ValidationError | ValidationError }
     * Thrown if the request/response validation fails.
     * @throws {@link InvalidUrlError | InvalidUrlError }
     * Thrown if the provided url is not valid for this request.
     * @throws {@link UnsuccessfulRequestError | UnsuccessfulRequestError }
     * Thrown if response is validated but has status greater than or equal to 400.
     *
     * @returns
     * The JSON Representation of the changed availability.
     */
    async addDeviceAvailabilityRules(url, availabilityRules, options) {
        const urlSuffix = '/devices/{}/availability'.split('{}').at(-1) ?? '';
        if (urlSuffix && !url.endsWith(urlSuffix))
            url = appendToUrl(url, urlSuffix);
        const [device_id] = validateUrl(new URL(url).toString(), '/devices/{}/availability');
        const body = availabilityRules;
        const parameters = {
            device_id: device_id,
        };
        if (!RequestValidation.validateAddDeviceAvailabilityRulesInput(parameters, body))
            throw new ValidationError('Request validation failed!', RequestValidation.validateAddDeviceAvailabilityRulesInput.errors);
        const authorization = `Bearer ${this.accessToken}`;
        const response = await this.fetch(new URL(url).toString().replace(this.baseUrl, this.serviceUrl), {
            method: 'POST',
            headers: [
                ['Content-Type', 'application/json'],
                ['Authorization', authorization],
                ...this.fixedHeaders,
                ...(options?.headers ?? []),
            ],
            body: JSON.stringify(body),
        });
        if (!RequestValidation.validateAddDeviceAvailabilityRulesOutput(response))
            throw new ValidationError('Response validation failed!', RequestValidation.validateAddDeviceAvailabilityRulesOutput.errors);
        if (Types.isErrorResponse(response))
            throw new UnsuccessfulRequestError(`Server returned response with status ${response.status}`, response);
        return response.body;
    }
    /**
     * Create new websocket token for device
     *
     * @param url
     * Url of the resource to be accessed.
     *
     * @throws {@link FetchError | FetchError }
     * Thrown if fetch fails.
     * @throws {@link ValidationError | ValidationError }
     * Thrown if the request/response validation fails.
     * @throws {@link InvalidUrlError | InvalidUrlError }
     * Thrown if the provided url is not valid for this request.
     * @throws {@link UnsuccessfulRequestError | UnsuccessfulRequestError }
     * Thrown if response is validated but has status greater than or equal to 400.
     *
     * @returns
     * The newly generated websocket token for the device.
     */
    async createWebsocketToken(url, options) {
        const urlSuffix = '/devices/{}/websocket'.split('{}').at(-1) ?? '';
        if (urlSuffix && !url.endsWith(urlSuffix))
            url = appendToUrl(url, urlSuffix);
        const [device_id] = validateUrl(new URL(url).toString(), '/devices/{}/websocket');
        const parameters = {
            device_id: device_id,
        };
        if (!RequestValidation.validateCreateWebsocketTokenInput(parameters))
            throw new ValidationError('Request validation failed!', RequestValidation.validateCreateWebsocketTokenInput.errors);
        const authorization = `Bearer ${this.accessToken}`;
        const response = await this.fetch(new URL(url).toString().replace(this.baseUrl, this.serviceUrl), {
            method: 'POST',
            headers: [
                ['Content-Type', 'application/json'],
                ['Authorization', authorization],
                ...this.fixedHeaders,
                ...(options?.headers ?? []),
            ],
        });
        if (!RequestValidation.validateCreateWebsocketTokenOutput(response))
            throw new ValidationError('Response validation failed!', RequestValidation.validateCreateWebsocketTokenOutput.errors);
        if (Types.isErrorResponse(response))
            throw new UnsuccessfulRequestError(`Server returned response with status ${response.status}`, response);
        return response.body;
    }
    /**
     * Send signaling message to device
     *
     * @param url
     * Url of the resource to be accessed.
     * @param sigMessage
     * The signaling message to be sent.
     *
     * @throws {@link FetchError | FetchError }
     * Thrown if fetch fails.
     * @throws {@link ValidationError | ValidationError }
     * Thrown if the request/response validation fails.
     * @throws {@link InvalidUrlError | InvalidUrlError }
     * Thrown if the provided url is not valid for this request.
     * @throws {@link UnsuccessfulRequestError | UnsuccessfulRequestError }
     * Thrown if response is validated but has status greater than or equal to 400.
     *
     * @returns
     * The signaling message was delivered successfully.
     */
    async sendSignalingMessage(url, sigMessage, options) {
        const urlSuffix = '/devices/{}/signaling'.split('{}').at(-1) ?? '';
        if (urlSuffix && !url.endsWith(urlSuffix))
            url = appendToUrl(url, urlSuffix);
        const [device_id] = validateUrl(new URL(url).toString(), '/devices/{}/signaling');
        const body = sigMessage;
        const parameters = {
            device_id: device_id,
        };
        if (!RequestValidation.validateSendSignalingMessageInput(parameters, body))
            throw new ValidationError('Request validation failed!', RequestValidation.validateSendSignalingMessageInput.errors);
        const authorization = `Bearer ${this.accessToken}`;
        const response = await this.fetch(new URL(url).toString().replace(this.baseUrl, this.serviceUrl), {
            method: 'POST',
            headers: [
                ['Content-Type', 'application/json'],
                ['Authorization', authorization],
                ...this.fixedHeaders,
                ...(options?.headers ?? []),
            ],
            body: JSON.stringify(body),
        });
        if (!RequestValidation.validateSendSignalingMessageOutput(response))
            throw new ValidationError('Response validation failed!', RequestValidation.validateSendSignalingMessageOutput.errors);
        if (Types.isErrorResponse(response))
            throw new UnsuccessfulRequestError(`Server returned response with status ${response.status}`, response);
    }
    /**
     * List Peer Connection
     *
     * @param options.url
     * Url of the  to be used.
     *
     * @throws {@link FetchError | FetchError }
     * Thrown if fetch fails.
     * @throws {@link ValidationError | ValidationError }
     * Thrown if the request/response validation fails.
     * @throws {@link InvalidUrlError | InvalidUrlError }
     * Thrown if the provided url is not valid for this request.
     * @throws {@link UnsuccessfulRequestError | UnsuccessfulRequestError }
     * Thrown if response is validated but has status greater than or equal to 400.
     *
     * @returns
     * The list of all peerconnections.
     */
    async listPeerconnections(options) {
        const url = appendToUrl(options?.url ?? this.baseUrl, '/peerconnections');
        if (!RequestValidation.validateListPeerconnectionsInput())
            throw new ValidationError('Request validation failed!', RequestValidation.validateListPeerconnectionsInput.errors);
        const authorization = `Bearer ${this.accessToken}`;
        const response = await this.fetch(new URL(url).toString().replace(this.baseUrl, this.serviceUrl), {
            method: 'GET',
            headers: [
                ['Content-Type', 'application/json'],
                ['Authorization', authorization],
                ...this.fixedHeaders,
                ...(options?.headers ?? []),
            ],
        });
        if (!RequestValidation.validateListPeerconnectionsOutput(response))
            throw new ValidationError('Response validation failed!', RequestValidation.validateListPeerconnectionsOutput.errors);
        if (Types.isErrorResponse(response))
            throw new UnsuccessfulRequestError(`Server returned response with status ${response.status}`, response);
        return response.body;
    }
    /**
     * Create a new Peer Connection
     *
     * @param peerconnection
     * The peerconnection to be created.
     * @param options.closedUrl
     * An URL that will be called once the peer connection is closed.
     * @param options.statusChangedUrl
     * An URL that will be called if the status of the peerconnection changes.
     * @param options.url
     * Url of the  to be used.
     *
     * @throws {@link FetchError | FetchError }
     * Thrown if fetch fails.
     * @throws {@link ValidationError | ValidationError }
     * Thrown if the request/response validation fails.
     * @throws {@link InvalidUrlError | InvalidUrlError }
     * Thrown if the provided url is not valid for this request.
     * @throws {@link UnsuccessfulRequestError | UnsuccessfulRequestError }
     * Thrown if response is validated but has status greater than or equal to 400.
     *
     * @returns
     * 201: The peerconnection was created. A JSON representation of the new peer connection is returned.
     * 202: The device service will attempt to create the peerconnection as soon as possible.
     */
    async createPeerconnection(peerconnection, options) {
        const url = appendToUrl(options?.url ?? this.baseUrl, '/peerconnections');
        const body = peerconnection;
        const parameters = {
            closedUrl: options?.closedUrl,
            statusChangedUrl: options?.statusChangedUrl,
        };
        const query = [];
        if (parameters['closedUrl'])
            query.push(['closedUrl', parameters['closedUrl'].toString()]);
        if (parameters['statusChangedUrl'])
            query.push(['statusChangedUrl', parameters['statusChangedUrl'].toString()]);
        if (!RequestValidation.validateCreatePeerconnectionInput(parameters, body))
            throw new ValidationError('Request validation failed!', RequestValidation.validateCreatePeerconnectionInput.errors);
        const authorization = `Bearer ${this.accessToken}`;
        const response = await this.fetch(new URL(url).toString().replace(this.baseUrl, this.serviceUrl) +
            '?' +
            new URLSearchParams(query), {
            method: 'POST',
            headers: [
                ['Content-Type', 'application/json'],
                ['Authorization', authorization],
                ...this.fixedHeaders,
                ...(options?.headers ?? []),
            ],
            body: JSON.stringify(body),
        });
        if (!RequestValidation.validateCreatePeerconnectionOutput(response))
            throw new ValidationError('Response validation failed!', RequestValidation.validateCreatePeerconnectionOutput.errors);
        if (Types.isErrorResponse(response))
            throw new UnsuccessfulRequestError(`Server returned response with status ${response.status}`, response);
        return response.body;
    }
    /**
     * View a peer connection
     *
     * @param url
     * Url of the resource to be accessed.
     *
     * @throws {@link FetchError | FetchError }
     * Thrown if fetch fails.
     * @throws {@link ValidationError | ValidationError }
     * Thrown if the request/response validation fails.
     * @throws {@link InvalidUrlError | InvalidUrlError }
     * Thrown if the provided url is not valid for this request.
     * @throws {@link UnsuccessfulRequestError | UnsuccessfulRequestError }
     * Thrown if response is validated but has status greater than or equal to 400.
     *
     * @returns
     * The JSON Representation of the device peer connection.
     */
    async getPeerconnection(url, options) {
        const urlSuffix = '/peerconnections/{}'.split('{}').at(-1) ?? '';
        if (urlSuffix && !url.endsWith(urlSuffix))
            url = appendToUrl(url, urlSuffix);
        const [peerconnection_id] = validateUrl(new URL(url).toString(), '/peerconnections/{}');
        const parameters = {
            peerconnection_id: peerconnection_id,
        };
        if (!RequestValidation.validateGetPeerconnectionInput(parameters))
            throw new ValidationError('Request validation failed!', RequestValidation.validateGetPeerconnectionInput.errors);
        const authorization = `Bearer ${this.accessToken}`;
        const response = await this.fetch(new URL(url).toString().replace(this.baseUrl, this.serviceUrl), {
            method: 'GET',
            headers: [
                ['Content-Type', 'application/json'],
                ['Authorization', authorization],
                ...this.fixedHeaders,
                ...(options?.headers ?? []),
            ],
        });
        if (!RequestValidation.validateGetPeerconnectionOutput(response))
            throw new ValidationError('Response validation failed!', RequestValidation.validateGetPeerconnectionOutput.errors);
        if (Types.isErrorResponse(response))
            throw new UnsuccessfulRequestError(`Server returned response with status ${response.status}`, response);
        return response.body;
    }
    /**
     * Delete a peer connection
     *
     * @param url
     * Url of the resource to be accessed.
     *
     * @throws {@link FetchError | FetchError }
     * Thrown if fetch fails.
     * @throws {@link ValidationError | ValidationError }
     * Thrown if the request/response validation fails.
     * @throws {@link InvalidUrlError | InvalidUrlError }
     * Thrown if the provided url is not valid for this request.
     * @throws {@link UnsuccessfulRequestError | UnsuccessfulRequestError }
     * Thrown if response is validated but has status greater than or equal to 400.
     *
     * @returns
     * 202: The peerconnection will be deleted as soon as it's closed.
     * 204: The peerconnection was deleted successfully.
     */
    async deletePeerconnection(url, options) {
        const urlSuffix = '/peerconnections/{}'.split('{}').at(-1) ?? '';
        if (urlSuffix && !url.endsWith(urlSuffix))
            url = appendToUrl(url, urlSuffix);
        const [peerconnection_id] = validateUrl(new URL(url).toString(), '/peerconnections/{}');
        const parameters = {
            peerconnection_id: peerconnection_id,
        };
        if (!RequestValidation.validateDeletePeerconnectionInput(parameters))
            throw new ValidationError('Request validation failed!', RequestValidation.validateDeletePeerconnectionInput.errors);
        const authorization = `Bearer ${this.accessToken}`;
        const response = await this.fetch(new URL(url).toString().replace(this.baseUrl, this.serviceUrl), {
            method: 'DELETE',
            headers: [
                ['Content-Type', 'application/json'],
                ['Authorization', authorization],
                ...this.fixedHeaders,
                ...(options?.headers ?? []),
            ],
        });
        if (!RequestValidation.validateDeletePeerconnectionOutput(response))
            throw new ValidationError('Response validation failed!', RequestValidation.validateDeletePeerconnectionOutput.errors);
        if (Types.isErrorResponse(response))
            throw new UnsuccessfulRequestError(`Server returned response with status ${response.status}`, response);
    }
    /**
     * Sets the peerconnection status of a single device.
     *
     * @param url
     * Url of the resource to be accessed.
     * @param body
     * The JSON Representation of the device peer connection.
     * @param device_url
     * URL of the device
     *
     * @throws {@link FetchError | FetchError }
     * Thrown if fetch fails.
     * @throws {@link ValidationError | ValidationError }
     * Thrown if the request/response validation fails.
     * @throws {@link InvalidUrlError | InvalidUrlError }
     * Thrown if the provided url is not valid for this request.
     * @throws {@link UnsuccessfulRequestError | UnsuccessfulRequestError }
     * Thrown if response is validated but has status greater than or equal to 400.
     *
     * @returns
     * OK.
     */
    async patchPeerconnectionDeviceStatus(url, body, device_url, options) {
        const urlSuffix = '/peerconnections/{}/device_status'.split('{}').at(-1) ?? '';
        if (urlSuffix && !url.endsWith(urlSuffix))
            url = appendToUrl(url, urlSuffix);
        const [peerconnection_id] = validateUrl(new URL(url).toString(), '/peerconnections/{}/device_status');
        const parameters = {
            peerconnection_id: peerconnection_id,
            device_url: device_url,
        };
        const query = [];
        if (parameters['device_url'])
            query.push(['device_url', parameters['device_url'].toString()]);
        if (!RequestValidation.validatePatchPeerconnectionDeviceStatusInput(parameters, body))
            throw new ValidationError('Request validation failed!', RequestValidation.validatePatchPeerconnectionDeviceStatusInput.errors);
        const authorization = `Bearer ${this.accessToken}`;
        const response = await this.fetch(new URL(url).toString().replace(this.baseUrl, this.serviceUrl) +
            '?' +
            new URLSearchParams(query), {
            method: 'PATCH',
            headers: [
                ['Content-Type', 'application/json'],
                ['Authorization', authorization],
                ...this.fixedHeaders,
                ...(options?.headers ?? []),
            ],
            body: JSON.stringify(body),
        });
        if (!RequestValidation.validatePatchPeerconnectionDeviceStatusOutput(response))
            throw new ValidationError('Response validation failed!', RequestValidation.validatePatchPeerconnectionDeviceStatusOutput.errors);
        if (Types.isErrorResponse(response))
            throw new UnsuccessfulRequestError(`Server returned response with status ${response.status}`, response);
    }
}
//# sourceMappingURL=client.js.map