<commit_before>package fr.wseduc.rbs.controllers;

import static fr.wseduc.rbs.BookingStatus.*;

import static org.entcore.common.http.response.DefaultResponseHandler.defaultResponseHandler;
import static org.entcore.common.sql.SqlResult.validUniqueResultHandler;

import org.entcore.common.controller.ControllerHelper;
import org.entcore.common.sql.Sql;
import org.entcore.common.sql.SqlConf;
import org.entcore.common.sql.SqlConfs;
import org.entcore.common.user.UserInfos;
import org.entcore.common.user.UserUtils;
import org.vertx.java.core.Handler;
import org.vertx.java.core.http.HttpServerRequest;
import org.vertx.java.core.json.JsonArray;
import org.vertx.java.core.json.JsonObject;

import fr.wseduc.rs.ApiDoc;
import fr.wseduc.rs.Delete;
import fr.wseduc.rs.Post;
import fr.wseduc.rs.Put;
import fr.wseduc.webutils.http.Renders;
import fr.wseduc.webutils.request.RequestUtils;

public class BookingController extends ControllerHelper {

	@Post("/resource/:resourceId/booking")
	@ApiDoc("Create booking of a given resource")
	// @SecuredAction(value = "rbs.contrib", type= ActionType.RESOURCE)
	public void createBooking(final HttpServerRequest request) {

		UserUtils.getUserInfos(eb, request, new Handler<UserInfos>() {
			@Override
			public void handle(final UserInfos user) {
				if (user != null) {
					RequestUtils.bodyToJson(request, pathPrefix + "createBooking", new Handler<JsonObject>() {
						@Override
						public void handle(JsonObject object) {
							final String id = request.params().get("resourceId");
							long resourceId = 0;
							try {
								resourceId = Long.parseLong(id);
							} catch (NumberFormatException e) {
								log.error("Invalid resourceId", e);
								Renders.badRequest(request, "Invalid resourceId");
							}

							object.putNumber("status", CREATED.status());
							SqlConf conf = SqlConfs.getConf(BookingController.class.getName());

							/* Query :
							 * Unix timestamps are converted into postgresql timestamps.
							 * Check that there does not exist a validated booking that overlaps the new booking.
							 */
							StringBuilder query = new StringBuilder();
							query.append("INSERT INTO ")
									.append(conf.getSchema())
									.append(conf.getTable())
									.append("(resource_id, owner, booking_reason, status, start_date, end_date)")
									.append(" SELECT  ?, ?, ?, ?, to_timestamp(?), to_timestamp(?)");
							query.append(" WHERE NOT EXISTS (")
									.append("SELECT id FROM ")
									.append(conf.getSchema())
									.append(conf.getTable())
									.append(" WHERE resource_id = ?")
									.append(" AND status = " + VALIDATED.status())
									.append(" AND (")
									.append("( start_date >= to_timestamp(?) AND start_date < to_timestamp(?) )")
									.append(" OR ( end_date > to_timestamp(?) AND end_date <= to_timestamp(?) )")
									.append("));");

							Object startDate = object.getValue("start_date");
							Object endDate = object.getValue("end_date");
							
							JsonArray values = new JsonArray();
							// Values for the INSERT clause
							values.add(resourceId)
									.add(object.getValue("owner"))
									.add(object.getValue("booking_reason"))
									.add(object.getValue("status"))
									.add(startDate)
									.add(endDate);
							// Values for the NOT EXISTS clause
							values.add(resourceId)
									.add(startDate)
									.add(endDate)
									.add(startDate)
									.add(endDate);

							// Execute
							Sql.getInstance()
									.prepared(
											query.toString(),
											values,
											validUniqueResultHandler(defaultResponseHandler(request)));
						}
					});
				} else {
					log.debug("User not found in session.");
					Renders.unauthorized(request);
				}
			}
		});
	}

	// @Post("/resource/:resourceId/booking/periodic")
	// @ApiDoc("Create periodic booking of a given resource")
	// @SecuredAction(value = "rbs.contrib", type= ActionType.RESOURCE)<commit_msg>Webservice to create booking : return proper values<commit_after>package fr.wseduc.rbs.controllers;

import static fr.wseduc.rbs.BookingStatus.*;
import static org.entcore.common.http.response.DefaultResponseHandler.defaultResponseHandler;
import static org.entcore.common.sql.SqlResult.validUniqueResultHandler;

import org.entcore.common.controller.ControllerHelper;
import org.entcore.common.sql.Sql;
import org.entcore.common.sql.SqlConf;
import org.entcore.common.sql.SqlConfs;
import org.entcore.common.user.UserInfos;
import org.entcore.common.user.UserUtils;
import org.vertx.java.core.Handler;
import org.vertx.java.core.http.HttpServerRequest;
import org.vertx.java.core.json.JsonArray;
import org.vertx.java.core.json.JsonObject;

import fr.wseduc.rs.ApiDoc;
import fr.wseduc.rs.Delete;
import fr.wseduc.rs.Post;
import fr.wseduc.rs.Put;
import fr.wseduc.webutils.Either;
import fr.wseduc.webutils.http.Renders;
import fr.wseduc.webutils.request.RequestUtils;

public class BookingController extends ControllerHelper {

	@Post("/resource/:resourceId/booking")
	@ApiDoc("Create booking of a given resource")
	// @SecuredAction(value = "rbs.contrib", type= ActionType.RESOURCE)
	public void createBooking(final HttpServerRequest request) {

		UserUtils.getUserInfos(eb, request, new Handler<UserInfos>() {
			@Override
			public void handle(final UserInfos user) {
				if (user != null) {
					RequestUtils.bodyToJson(request, pathPrefix + "createBooking", new Handler<JsonObject>() {
						@Override
						public void handle(JsonObject object) {
							final String id = request.params().get("resourceId");
							long resourceId = 0;
							try {
								resourceId = Long.parseLong(id);
							} catch (NumberFormatException e) {
								log.error("Invalid resourceId", e);
								Renders.badRequest(request, "Invalid resourceId");
							}

							object.putNumber("status", CREATED.status());
							SqlConf conf = SqlConfs.getConf(BookingController.class.getName());

							/* Query :
							 * Unix timestamps are converted into postgresql timestamps.
							 * Check that there does not exist a validated booking that overlaps the new booking.
							 */
							StringBuilder query = new StringBuilder();
							query.append("INSERT INTO ")
									.append(conf.getSchema())
									.append(conf.getTable())
									.append("(resource_id, owner, booking_reason, status, start_date, end_date)")
									.append(" SELECT  ?, ?, ?, ?, to_timestamp(?), to_timestamp(?)");
							query.append(" WHERE NOT EXISTS (")
									.append("SELECT id FROM ")
									.append(conf.getSchema())
									.append(conf.getTable())
									.append(" WHERE resource_id = ?")
									.append(" AND status = " + VALIDATED.status())
									.append(" AND (")
									.append("( start_date >= to_timestamp(?) AND start_date < to_timestamp(?) )")
									.append(" OR ( end_date > to_timestamp(?) AND end_date <= to_timestamp(?) )")
									.append(")) RETURNING id;");

							Object startDate = object.getValue("start_date");
							Object endDate = object.getValue("end_date");
							
							JsonArray values = new JsonArray();
							// Values for the INSERT clause
							values.add(resourceId)
									.add(object.getValue("owner"))
									.add(object.getValue("booking_reason"))
									.add(object.getValue("status"))
									.add(startDate)
									.add(endDate);
							// Values for the NOT EXISTS clause
							values.add(resourceId)
									.add(startDate)
									.add(endDate)
									.add(startDate)
									.add(endDate);

							
							Handler<Either<String, JsonObject>> handler = new Handler<Either<String, JsonObject>>() {
								@Override
								public void handle(Either<String, JsonObject> event) {
									if (event.isRight()) {
										if (event.right().getValue() != null && event.right().getValue().size() > 0) {
											Renders.renderJson(request, event.right().getValue(), 200);
										} else {
											JsonObject error = new JsonObject()
												.putString("error", "A validated booking overlaps the booking you tried to create.");
											Renders.renderError(request, error);
										}
									} else {
										JsonObject error = new JsonObject()
												.putString("error", event.left().getValue());
										Renders.renderJson(request, error, 400);
									}
								}
							};
							
							// Execute
							Sql.getInstance()
									.prepared(
											query.toString(),
											values,
											validUniqueResultHandler(handler));
						}
					});
				} else {
					log.debug("User not found in session.");
					Renders.unauthorized(request);
				}
			}
		});
	}

	// @Post("/resource/:resourceId/booking/periodic")
	// @ApiDoc("Create periodic booking of a given resource")
	// @SecuredAction(value = "rbs.contrib", type= ActionType.RESOURCE)
{'fraction_non_alphanumeric': 0.13076049943246312, 'fraction_numerical': 0.0010215664018161181, 'mean_word_length': 2.9021257750221436, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3018802', 'n_tokens_mistral': 3621, 'n_tokens_neox': 2549, 'n_words': 539}