/*
 * Queue - A Queueing system that can be used to handle labs in higher education
 * Copyright (C) 2016-2021  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.view.requests;

import static nl.tudelft.librador.SpringContext.getBean;

import java.util.List;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import nl.tudelft.labracore.api.dto.AssignmentDetailsDTO;
import nl.tudelft.queue.cache.AssignmentCacheManager;
import nl.tudelft.queue.cache.EditionCacheManager;
import nl.tudelft.queue.cache.ModuleCacheManager;
import nl.tudelft.queue.dto.view.RequestViewDTO;
import nl.tudelft.queue.dto.view.events.RequestHandledEventViewDTO;
import nl.tudelft.queue.model.Feedback;
import nl.tudelft.queue.model.LabRequest;
import nl.tudelft.queue.model.TimeSlot;
import nl.tudelft.queue.model.enums.Language;
import nl.tudelft.queue.model.enums.OnlineMode;
import nl.tudelft.queue.model.enums.RequestType;

import org.apache.commons.lang3.ArrayUtils;

@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class LabRequestViewDTO extends RequestViewDTO<LabRequest> {

	private String comment;
	private String question;

	private String jitsiRoom;
	private TimeSlot timeSlot;
	private OnlineMode onlineMode;

	private Language language;

	private RequestType requestType;

	private AssignmentDetailsDTO assignment;

	private List<Feedback> feedbacks;

	private String commentForStudent;

	private String commentForAssistant;

	@Override
	public void postApply() {
		super.postApply();

		if (onlineMode != null) {
			setRoom(null);
		}

		assignment = getBean(AssignmentCacheManager.class).getRequired(data.getAssignment());
		timeSlot = data.getTimeSlot();

		if (super.getEdition() == null) {
			var editionId = getBean(ModuleCacheManager.class).getRequired(assignment.getModule().getId())
					.getEdition().getId();
			super.setEdition(getBean(EditionCacheManager.class).getRequired(editionId));
		}

		var handledEvent = getEvents().stream()
				.filter(e -> e instanceof RequestHandledEventViewDTO<?>)
				.findFirst()
				.map(e -> (RequestHandledEventViewDTO<?>) e);
		if (handledEvent.isPresent()) {
			commentForStudent = handledEvent.get().getReasonForStudent();
			commentForAssistant = handledEvent.get().getReasonForAssistant();
		} else {
			commentForStudent = commentForAssistant = "";
		}
	}

	@Override
	public String toSentence() {
		StringBuilder builder = new StringBuilder(requesterEntityName())
				.append(" ")
				.append(requestType.toSentence())
				.append(" ")
				.append(assignment.getName())
				.append(" (").append(assignment.getModule().getName()).append(")");

		if (timeSlot != null) {
			builder.append(" at ")
					.append(timeSlot.getSlot().toSentence());
		}

		return builder.toString();
	}

	public static String[] csvHeader() {
		return ArrayUtils.addAll(RequestViewDTO.csvHeader(),
				"Comment",
				"Question",
				"Time Slot",
				"Online Mode",
				"Request Type",
				"Assignment",
				"Reason for Student",
				"Reason for Assistant");
	}

	@Override
	public String[] toColumns() {
		return ArrayUtils.addAll(super.toColumns(),
				(comment != null) ? comment : "",
				(question != null) ? question : "",
				(timeSlot != null) ? timeSlot.toString() : "",
				(onlineMode != null) ? onlineMode.getDisplayName() : "",
				requestType.displayName(),
				assignment.getName(),
				commentForStudent,
				commentForAssistant);
	}
}
