/*
 * Queue - A Queueing system that can be used to handle labs in higher education
 * Copyright (C) 2016-2024  Delft University of Technology
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package nl.tudelft.queue.dto.create.requests;

import java.util.List;
import java.util.Objects;

import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.*;
import lombok.experimental.SuperBuilder;
import nl.tudelft.librador.dto.DTOConverter;
import nl.tudelft.queue.dto.create.RequestCreateDTO;
import nl.tudelft.queue.dto.id.TimeSlotIdDTO;
import nl.tudelft.queue.model.LabRequest;
import nl.tudelft.queue.model.embeddables.AllowedRequest;
import nl.tudelft.queue.model.enums.Language;
import nl.tudelft.queue.model.enums.OnlineMode;
import nl.tudelft.queue.model.enums.RequestType;
import nl.tudelft.queue.model.labs.Lab;
import nl.tudelft.queue.model.labs.SlottedLab;

@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class LabRequestCreateDTO extends RequestCreateDTO<LabRequest, Lab> {

	@NotNull
	private RequestType requestType;

	@Size(max = 250)
	private String comment;

	@Size(max = 500)
	private String question;

	private TimeSlotIdDTO timeSlot;

	@NotNull
	private Long assignment;

	private Long room;

	private OnlineMode onlineMode;

	@Builder.Default
	private Language language = Language.ANY;

	private transient Lab session;

	private transient DTOConverter converter;

	@Override
	public void validate() {
		if (requestType == RequestType.QUESTION) {
			nonEmpty("question", question);
		}

		if ((room == null) == (onlineMode == null)) {
			errors.rejectValue("room", "Room or online mode not selected");
			errors.rejectValue("onlineMode", "Room or online mode not selected");
		}

		if (!this.session.getAllowedRequests().contains(new AllowedRequest(assignment, requestType))) {
			errors.rejectValue("assignment", "Incompatible assignment for request type " + requestType);
		}

		if (this.session instanceof SlottedLab &&
				(timeSlot == null
						|| !Objects.equals(converter.apply(timeSlot).getLab().getId(), this.session.getId())
						|| converter.apply(timeSlot).isFull())) {
			errors.rejectValue("slot", "No time slot selected for request");
		}
	}

	public void validateRooms(List<Long> validRoomIds) {
		if (room != null && !validRoomIds.contains(room)) {
			errors.rejectValue("room", "A room with id " + room + " is not available in the lab.");
		}
	}

	@Override
	public LabRequest apply(DTOConverter converter) {
		this.converter = converter;
		return super.apply(converter);
	}

	@Override
	public Class<LabRequest> clazz() {
		return LabRequest.class;
	}
}
