"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "FloorService", {
    enumerable: true,
    get: function() {
        return FloorService;
    }
});
const _baseservice = require("./base.service");
const _entities = require("../../entities");
const _floordto = require("../interfaces/floor.dto");
const _validators = require("../../handlers/validators");
const _floorservicevalidation = require("../validators/floor-service.validation");
const _runtimeexceptions = require("../../exceptions/runtime.exceptions");
class FloorService extends (0, _baseservice.BaseService)(_entities.Floor, _floordto.FloorDto, _floordto.CreateFloorDto, _floordto.UpdateFloorDto) {
    typeormService;
    floorPositionService;
    constructor(typeormService, floorPositionService){
        super(typeormService), this.typeormService = typeormService, this.floorPositionService = floorPositionService;
    }
    async list(options) {
        return super.list(Object.assign(options || {}, {
            relations: [
                "printers"
            ]
        }));
    }
    async get(id, options) {
        return super.get(id, Object.assign(options || {}, {
            relations: [
                "printers"
            ]
        }));
    }
    async create(dto) {
        const outcome = await (0, _validators.validateInput)(dto, _floorservicevalidation.createOrUpdateFloorSchema);
        const floor = await super.create({
            name: outcome.name,
            order: outcome.order,
            printers: []
        });
        if (outcome.printers?.length) {
            for (const position of outcome.printers){
                await this.addOrUpdatePrinter(floor.id, position);
            }
        }
        return this.get(floor.id);
    }
    toDto(floor) {
        return {
            id: floor.id,
            name: floor.name,
            order: floor.order,
            printers: floor.printers.map((p)=>({
                    printerId: p.printerId,
                    floorId: p.floorId,
                    x: p.x,
                    y: p.y
                }))
        };
    }
    async update(floorId, update) {
        const existingFloor = await this.get(floorId);
        const floorUpdate = {
            ...existingFloor,
            name: update.name,
            printers: update.printers,
            order: update.order
        };
        const validatedFloor = await (0, _validators.validateInput)(floorUpdate, _floorservicevalidation.createOrUpdateFloorSchema);
        const desiredPositions = validatedFloor.printers;
        if (desiredPositions?.length) {
            for (const printer of desiredPositions){
                await this.addOrUpdatePrinter(existingFloor.id, printer);
            }
            const undesiredPositions = existingFloor.printers.filter((pos)=>!desiredPositions.find((dp)=>dp.printerId === pos.printerId));
            if (undesiredPositions?.length) {
                await this.floorPositionService.deleteMany(undesiredPositions.map((pos)=>pos.id));
            }
        }
        delete floorUpdate.printers;
        return super.update(floorId, floorUpdate);
    }
    async updateName(floorId, floorName) {
        const { name } = await (0, _validators.validateInput)({
            name: floorName
        }, _floorservicevalidation.updateFloorNameSchema);
        const floor = await this.get(floorId);
        floor.name = name;
        return this.update(floorId, floor);
    }
    async updateOrder(floorId, order) {
        const { order: validOrder } = await (0, _validators.validateInput)({
            order
        }, _floorservicevalidation.updateFloorOrderSchema);
        const floor = await this.get(floorId);
        floor.order = validOrder;
        return await this.update(floorId, floor);
    }
    async addOrUpdatePrinter(floorId, positionDto) {
        await this.get(floorId);
        positionDto.floorId = floorId;
        const validInput = await (0, _validators.validateInput)(positionDto, _floorservicevalidation.printerInFloorSchema);
        const position = await this.floorPositionService.findPrinterPosition(validInput.printerId);
        if (position?.floorId === floorId && position.x === validInput.x && position.y === validInput.y && position.printerId === validInput.printerId) {
            return this.get(floorId);
        }
        if (position) {
            await this.floorPositionService.delete(position.id);
        }
        const xyPosition = await this.floorPositionService.findPosition(floorId, validInput.x, validInput.y);
        if (xyPosition) {
            await this.floorPositionService.delete(xyPosition.id);
        }
        const newPosition = new _entities.FloorPosition();
        Object.assign(newPosition, {
            x: validInput.x,
            y: validInput.y,
            printerId: validInput.printerId,
            floorId
        });
        await this.floorPositionService.create(newPosition);
        return this.get(floorId);
    }
    async removePrinter(floorId, printerId) {
        const position = await this.floorPositionService.findPrinterPositionOnFloor(floorId, printerId);
        if (!position) {
            throw new _runtimeexceptions.NotFoundException("This printer was not found on this floor");
        }
        await this.floorPositionService.delete(position.id);
        return await this.get(floorId);
    }
    async deletePrinterFromAnyFloor(printerId) {
        await this.floorPositionService.deletePrinterPositionsByPrinterId(printerId);
    }
}

//# sourceMappingURL=floor.service.js.map