import { AbstractRepository, InvalidValueError } from '@crosslab/service-common';
import { In } from 'typeorm';
export class DeviceRepository extends AbstractRepository {
    dependencies = {};
    constructor() {
        super('Device');
    }
    dependenciesMet() {
        if (!this.dependencies.deviceOverview)
            return false;
        if (!this.dependencies.concreteDevice)
            return false;
        if (!this.dependencies.deviceGroup)
            return false;
        if (!this.dependencies.instantiableBrowserDevice)
            return false;
        if (!this.dependencies.instantiableCloudDevice)
            return false;
        return true;
    }
    initialize(_entityManager) {
        return;
    }
    /**
     * This function is used to replace the standard isInitialized()-method. Since we
     * don't have a repository for the type DeviceModel we don't want to falsely
     * claim that we have it and that it is initialized.
     */
    _isInitialized() {
        if (!this.dependenciesMet())
            return false;
        return true;
    }
    async create(data) {
        if (!this._isInitialized())
            this.throwUninitializedRepositoryError();
        switch (data.type) {
            case 'cloud instantiable':
                return await this.dependencies.instantiableCloudDevice.create(data);
            case 'device':
                return await this.dependencies.concreteDevice.create(data);
            case 'edge instantiable':
                return await this.dependencies.instantiableBrowserDevice.create(data);
            case 'group':
                return await this.dependencies.deviceGroup.create(data);
        }
    }
    async write(model, data) {
        if (!this._isInitialized())
            this.throwUninitializedRepositoryError();
        switch (model.type) {
            case 'cloud instantiable':
                if (data.type !== model.type)
                    throw new InvalidValueError(`Model of type ${model.type} cannot be updated with data of type ${data.type}`, 400);
                return await this.dependencies.instantiableCloudDevice.write(model, data);
            case 'device':
                if (data.type !== model.type)
                    throw new InvalidValueError(`Model of type ${model.type} cannot be updated with data of type ${data.type}`, 400);
                return await this.dependencies.concreteDevice.write(model, data);
            case 'edge instantiable':
                if (data.type !== model.type)
                    throw new InvalidValueError(`Model of type ${model.type} cannot be updated with data of type ${data.type}`, 400);
                return await this.dependencies.instantiableBrowserDevice.write(model, data);
            case 'group':
                if (data.type !== model.type)
                    throw new InvalidValueError(`Model of type ${model.type} cannot be updated with data of type ${data.type}`, 400);
                return await this.dependencies.deviceGroup.write(model, data);
        }
    }
    async format(model) {
        if (!this._isInitialized())
            this.throwUninitializedRepositoryError();
        switch (model.type) {
            case 'cloud instantiable':
                return await this.dependencies.instantiableCloudDevice.format(model);
            case 'device':
                return await this.dependencies.concreteDevice.format(model);
            case 'edge instantiable':
                return await this.dependencies.instantiableBrowserDevice.format(model);
            case 'group':
                return await this.dependencies.deviceGroup.format(model);
        }
    }
    async save(model) {
        if (!this._isInitialized())
            this.throwUninitializedRepositoryError();
        switch (model.type) {
            case 'cloud instantiable':
                return await this.dependencies.instantiableCloudDevice.save(model);
            case 'device':
                return await this.dependencies.concreteDevice.save(model);
            case 'edge instantiable':
                return await this.dependencies.instantiableBrowserDevice.save(model);
            case 'group':
                return await this.dependencies.deviceGroup.save(model);
        }
    }
    async find(options) {
        if (!this._isInitialized())
            this.throwUninitializedRepositoryError();
        const foundDevices = [];
        const deviceOverviews = await this.dependencies.deviceOverview.find(options);
        const deviceTypes = [
            'device',
            'group',
            'edge instantiable',
            'cloud instantiable',
        ];
        const repositoryMapping = {
            device: this.dependencies.concreteDevice,
            group: this.dependencies.deviceGroup,
            'edge instantiable': this.dependencies.instantiableBrowserDevice,
            'cloud instantiable': this.dependencies.instantiableCloudDevice,
        };
        for (const type of deviceTypes) {
            const devices = deviceOverviews.filter(device => device.type === type);
            if (devices.length > 0) {
                foundDevices.push(...(await repositoryMapping[type].find({
                    where: {
                        uuid: In(devices.map(concreteDevice => concreteDevice.uuid)),
                    },
                })));
            }
        }
        return foundDevices;
    }
    async findOne(options) {
        if (!this._isInitialized())
            this.throwUninitializedRepositoryError();
        const deviceOverview = await this.dependencies.deviceOverview.findOne(options);
        if (!deviceOverview)
            return null;
        switch (deviceOverview.type) {
            case 'cloud instantiable':
                return await this.dependencies.instantiableCloudDevice.findOne({
                    where: { uuid: deviceOverview.uuid },
                });
            case 'device':
                return await this.dependencies.concreteDevice.findOne({
                    where: { uuid: deviceOverview.uuid },
                });
            case 'edge instantiable':
                return await this.dependencies.instantiableBrowserDevice.findOne({
                    where: { uuid: deviceOverview.uuid },
                });
            case 'group':
                return await this.dependencies.deviceGroup.findOne({
                    where: { uuid: deviceOverview.uuid },
                });
        }
    }
    async findOneOrFail(options) {
        if (!this._isInitialized())
            this.throwUninitializedRepositoryError();
        const deviceOverview = await this.dependencies.deviceOverview.findOneOrFail(options);
        switch (deviceOverview.type) {
            case 'cloud instantiable':
                return await this.dependencies.instantiableCloudDevice.findOneOrFail({
                    where: { uuid: deviceOverview.uuid },
                });
            case 'device':
                return await this.dependencies.concreteDevice.findOneOrFail({
                    where: { uuid: deviceOverview.uuid },
                });
            case 'edge instantiable':
                return await this.dependencies.instantiableBrowserDevice.findOneOrFail({
                    where: { uuid: deviceOverview.uuid },
                });
            case 'group':
                return await this.dependencies.deviceGroup.findOneOrFail({
                    where: { uuid: deviceOverview.uuid },
                });
        }
    }
    async remove(model) {
        if (!this._isInitialized())
            this.throwUninitializedRepositoryError();
        switch (model.type) {
            case 'cloud instantiable':
                return await this.dependencies.instantiableCloudDevice.remove(model);
            case 'device':
                return await this.dependencies.concreteDevice.remove(model);
            case 'edge instantiable':
                return await this.dependencies.instantiableBrowserDevice.remove(model);
            case 'group':
                return await this.dependencies.deviceGroup.remove(model);
        }
    }
}
//# sourceMappingURL=device.js.map