<commit_before>﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using VORBS.DAL.Repositories;
using VORBS.Models;
using VORBS.Models.DTOs;
using VORBS.Models.ViewModels;
using VORBS.Security;
using VORBS.Utils;
using static VORBS.Models.User;

namespace VORBS.Services
{
    public class BookingsService
    {
        private IBookingRepository _bookingsRepository;
        private IRoomRepository _roomsRepository;
        private ILocationRepository _locationsRepository;
        private AvailabilityService _availabilityService;

        private Utils.EmailHelper _emailHelper;

        private IDirectoryService _directoryService;

        private NLog.Logger _logger;

        public BookingsService(IBookingRepository bookingRepository, IRoomRepository roomRepository, ILocationRepository locationRepository, IDirectoryService directoryService, Utils.EmailHelper emailHelper)
        {
            _logger = NLog.LogManager.GetCurrentClassLogger();

            _bookingsRepository = bookingRepository;
            _roomsRepository = roomRepository;
            _locationsRepository = locationRepository;

            _directoryService = directoryService;
            _availabilityService = new AvailabilityService(_bookingsRepository, _roomsRepository, _locationsRepository);

            _emailHelper = emailHelper;

            _logger.Trace(LoggerHelper.InitializeClassMessage());
        }

        public void DeleteExistingBooking(Booking booking, bool? recurrence, User user, NameValueCollection appSettings)
        {
            int? recurringBookingId = null;
            if (recurrence.Value)
                recurringBookingId = booking.RecurrenceId;

            List<Booking> allBookings = (recurringBookingId == null) ? new List<Booking> { booking } : _bookingsRepository.GetBookingsInRecurrence(recurringBookingId.Value);

            bool success = _bookingsRepository.Delete(allBookings);
            if (!success)
                throw new DeletionException();
            else
                _logger.Info("Booking(s) successfully cancelled: " + String.Join(", ", allBookings.Select(x => x.ID)));

            if (!bool.Parse(appSettings["sendEmails"].ToString()))
            {
                _logger.Trace(LoggerHelper.ExecutedFunctionMessage(LoggerHelper.VOID_TYPE, booking, recurrence, user, appSettings));
                _logger.Debug($"SendEmails setting is false or empty - Skipping email sending");
                return;
            }

            string fromEmail = appSettings["fromEmail"];

            Room locationRoom = _roomsRepository.GetRoomById(booking.RoomID);
            allBookings.ForEach(x => x.Room = locationRoom);

            if (booking.PID.ToUpper() != user.PayId.Identity.ToUpper())
                SendEmailToOwnerForAdminDelete(fromEmail, booking, user, allBookings);
            else
                SendEmailToOwnerForDelete(fromEmail, booking, user, allBookings);
            if (booking.Flipchart || booking.Projector)
                SendEmailToFacilitiesForDelete(fromEmail, booking, allBookings);
            if (booking.DssAssist)
                SendEmailToDSSForDelete(fromEmail, booking, allBookings);

            _logger.Trace(LoggerHelper.ExecutedFunctionMessage(LoggerHelper.VOID_TYPE, booking, recurrence, user, appSettings));
        }

        public void EditExistingBooking(Booking existingBooking, Booking editBooking, bool? recurrence, User user, NameValueCollection appSettings)
        {
            int? recurringBookingId = null;
            if (recurrence.Value)
                recurringBookingId = existingBooking.RecurrenceId;

            List<Booking> allBookings = (recurringBookingId == null) ? new List<Booking> { existingBooking } : _bookingsRepository.GetBookingsInRecurrence(recurringBookingId.Value);
            List<Booking> originalBookings = (recurringBookingId == null) ? new List<Booking> { existingBooking } : _bookingsRepository.GetBookingsInRecurrence(recurringBookingId.Value, true);

            _logger.Debug($"AllBookings count: {allBookings.Count()}, OriginalBookings count: {originalBookings.Count()}");

            List<Booking> editBookings = new List<Booking>();

            for (int i = 0; i < allBookings.Count; i++)
            {
                Booking currentBooking = allBookings[i];
                currentBooking.DssAssist = editBooking.DssAssist;
                if (editBooking.ExternalAttendees != null && editBooking.ExternalAttendees.Count > 0)
                {
                    foreach (ExternalAttendees attendee in editBooking.ExternalAttendees)
                    {
                        currentBooking.ExternalAttendees.Add(new ExternalAttendees()
                        {
                            BookingID = currentBooking.ID,
                            FullName = attendee.FullName,
                            CompanyName = attendee.CompanyName,
                            PassRequired = attendee.PassRequired
                        });
                    }
                }

                currentBooking.Flipchart = editBooking.Flipchart;
                currentBooking.NumberOfAttendees = editBooking.NumberOfAttendees;
                currentBooking.StartDate = currentBooking.StartDate.Date + new TimeSpan(editBooking.StartDate.Hour, editBooking.StartDate.Minute, editBooking.StartDate.Second);
                currentBooking.EndDate = currentBooking.EndDate.Date + new TimeSpan(editBooking.EndDate.Hour, editBooking.EndDate.Minute, editBooking.EndDate.Second);
                currentBooking.Projector = editBooking.Projector;
                currentBooking.Subject = editBooking.Subject;

                editBookings.Add(currentBooking);
                _logger.Debug($"Added booking: {currentBooking.ID} to list of Editbookings");
            }

            var updatedBookings = _bookingsRepository.UpdateExistingBookings(allBookings, editBookings);
            if (updatedBookings == null)
            {
                _logger.Debug("UpdatedBookings from repository is null");
                _logger.Fatal("Unable to edit booking(s): " + editBooking.ID);

                UnableToEditBookingException exn = new UnableToEditBookingException();
                _logger.Trace(LoggerHelper.ExecutedFunctionMessage(exn, existingBooking, editBooking, recurrence, user, appSettings));
                throw exn;
            }
            else
                _logger.Info("Booking(s) successfully editted: " + String.Join(", ", editBookings.Select(x => x.ID)));

            if (!bool.Parse(appSettings["sendEmails"].ToString()))
            {
                _logger.Debug("SendEmails config is false or empty - Skipping email sending");
                _logger.Trace(LoggerHelper.ExecutedFunctionMessage(LoggerHelper.VOID_TYPE, existingBooking, editBooking, recurrence, user, appSettings));
                return;
            }

            string fromEmail = appSettings["fromEmail"];

            if (
                editBookings.Select(x => (x.Flipchart != originalBookings.Where(y => y.ID == x.ID).First().Flipchart)).Count() > 0
                || editBookings.Select(x => (x.Projector != originalBookings.Where(y => y.ID == x.ID).First().Projector)).Count() > 0)
            {
                SendEmailToFacilitiesForEdit(fromEmail, editBooking, editBookings, originalBookings);
            }

            if (editBookings.Select(x => (x.DssAssist != originalBookings.Where(y => y.ID == x.ID).First().DssAssist)).Count() > 0)
                SendEmailToDSSForEdit(fromEmail, editBooking, editBookings, originalBookings);


            Func<Booking, Booking, bool> attendeeCompare = delegate (Booking newBooking, Booking currentBooking)
            {
                return !(new HashSet<string>(currentBooking.ExternalAttendees.Select(x => x.FullName)).SetEquals(newBooking.ExternalAttendees.Select(x => x.FullName)));
            };
            if (editBookings.Select(x => attendeeCompare(x, originalBookings.Where(y => y.ID == x.ID).First())).Count() > 0)
                SendEmailToSecurityForEdit(fromEmail, editBooking, editBookings, originalBookings);

            if (existingBooking.PID.ToUpper() != user.PayId.Identity.ToUpper())
                SendEmailToOwnerForAdminEdit(fromEmail, existingBooking, editBookings);
            else
                SendEmailToOwnerForEdit(fromEmail, existingBooking, editBookings, user);

        }

        public void SaveNewBooking(Booking newBooking, User user, NameValueCollection appSettings)
        {
            List<Booking> bookingsToCreate = new List<Booking>();
            List<Booking> clashedBookings = new List<Booking>();
            List<Booking> deletedBookings = new List<Booking>();

            Room bookingRoom = _roomsRepository.GetRoomById(newBooking.RoomID);
            newBooking.RoomID = newBooking.Room.ID;

            newBooking.Owner = user.FullName;
            newBooking.PID = user.PayId.Identity;

            if (newBooking.Recurrence.IsRecurring)
            {<commit_msg>Fix issue with 'On Behalf Of' bookings not assigning to correct user<commit_after>﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using VORBS.DAL.Repositories;
using VORBS.Models;
using VORBS.Models.DTOs;
using VORBS.Models.ViewModels;
using VORBS.Security;
using VORBS.Utils;
using static VORBS.Models.User;

namespace VORBS.Services
{
    public class BookingsService
    {
        private IBookingRepository _bookingsRepository;
        private IRoomRepository _roomsRepository;
        private ILocationRepository _locationsRepository;
        private AvailabilityService _availabilityService;

        private Utils.EmailHelper _emailHelper;

        private IDirectoryService _directoryService;

        private NLog.Logger _logger;

        public BookingsService(IBookingRepository bookingRepository, IRoomRepository roomRepository, ILocationRepository locationRepository, IDirectoryService directoryService, Utils.EmailHelper emailHelper)
        {
            _logger = NLog.LogManager.GetCurrentClassLogger();

            _bookingsRepository = bookingRepository;
            _roomsRepository = roomRepository;
            _locationsRepository = locationRepository;

            _directoryService = directoryService;
            _availabilityService = new AvailabilityService(_bookingsRepository, _roomsRepository, _locationsRepository);

            _emailHelper = emailHelper;

            _logger.Trace(LoggerHelper.InitializeClassMessage());
        }

        public void DeleteExistingBooking(Booking booking, bool? recurrence, User user, NameValueCollection appSettings)
        {
            int? recurringBookingId = null;
            if (recurrence.Value)
                recurringBookingId = booking.RecurrenceId;

            List<Booking> allBookings = (recurringBookingId == null) ? new List<Booking> { booking } : _bookingsRepository.GetBookingsInRecurrence(recurringBookingId.Value);

            bool success = _bookingsRepository.Delete(allBookings);
            if (!success)
                throw new DeletionException();
            else
                _logger.Info("Booking(s) successfully cancelled: " + String.Join(", ", allBookings.Select(x => x.ID)));

            if (!bool.Parse(appSettings["sendEmails"].ToString()))
            {
                _logger.Trace(LoggerHelper.ExecutedFunctionMessage(LoggerHelper.VOID_TYPE, booking, recurrence, user, appSettings));
                _logger.Debug($"SendEmails setting is false or empty - Skipping email sending");
                return;
            }

            string fromEmail = appSettings["fromEmail"];

            Room locationRoom = _roomsRepository.GetRoomById(booking.RoomID);
            allBookings.ForEach(x => x.Room = locationRoom);

            if (booking.PID.ToUpper() != user.PayId.Identity.ToUpper())
                SendEmailToOwnerForAdminDelete(fromEmail, booking, user, allBookings);
            else
                SendEmailToOwnerForDelete(fromEmail, booking, user, allBookings);
            if (booking.Flipchart || booking.Projector)
                SendEmailToFacilitiesForDelete(fromEmail, booking, allBookings);
            if (booking.DssAssist)
                SendEmailToDSSForDelete(fromEmail, booking, allBookings);

            _logger.Trace(LoggerHelper.ExecutedFunctionMessage(LoggerHelper.VOID_TYPE, booking, recurrence, user, appSettings));
        }

        public void EditExistingBooking(Booking existingBooking, Booking editBooking, bool? recurrence, User user, NameValueCollection appSettings)
        {
            int? recurringBookingId = null;
            if (recurrence.Value)
                recurringBookingId = existingBooking.RecurrenceId;

            List<Booking> allBookings = (recurringBookingId == null) ? new List<Booking> { existingBooking } : _bookingsRepository.GetBookingsInRecurrence(recurringBookingId.Value);
            List<Booking> originalBookings = (recurringBookingId == null) ? new List<Booking> { existingBooking } : _bookingsRepository.GetBookingsInRecurrence(recurringBookingId.Value, true);

            _logger.Debug($"AllBookings count: {allBookings.Count()}, OriginalBookings count: {originalBookings.Count()}");

            List<Booking> editBookings = new List<Booking>();

            for (int i = 0; i < allBookings.Count; i++)
            {
                Booking currentBooking = allBookings[i];
                currentBooking.DssAssist = editBooking.DssAssist;
                if (editBooking.ExternalAttendees != null && editBooking.ExternalAttendees.Count > 0)
                {
                    foreach (ExternalAttendees attendee in editBooking.ExternalAttendees)
                    {
                        currentBooking.ExternalAttendees.Add(new ExternalAttendees()
                        {
                            BookingID = currentBooking.ID,
                            FullName = attendee.FullName,
                            CompanyName = attendee.CompanyName,
                            PassRequired = attendee.PassRequired
                        });
                    }
                }

                currentBooking.Flipchart = editBooking.Flipchart;
                currentBooking.NumberOfAttendees = editBooking.NumberOfAttendees;
                currentBooking.StartDate = currentBooking.StartDate.Date + new TimeSpan(editBooking.StartDate.Hour, editBooking.StartDate.Minute, editBooking.StartDate.Second);
                currentBooking.EndDate = currentBooking.EndDate.Date + new TimeSpan(editBooking.EndDate.Hour, editBooking.EndDate.Minute, editBooking.EndDate.Second);
                currentBooking.Projector = editBooking.Projector;
                currentBooking.Subject = editBooking.Subject;

                editBookings.Add(currentBooking);
                _logger.Debug($"Added booking: {currentBooking.ID} to list of Editbookings");
            }

            var updatedBookings = _bookingsRepository.UpdateExistingBookings(allBookings, editBookings);
            if (updatedBookings == null)
            {
                _logger.Debug("UpdatedBookings from repository is null");
                _logger.Fatal("Unable to edit booking(s): " + editBooking.ID);

                UnableToEditBookingException exn = new UnableToEditBookingException();
                _logger.Trace(LoggerHelper.ExecutedFunctionMessage(exn, existingBooking, editBooking, recurrence, user, appSettings));
                throw exn;
            }
            else
                _logger.Info("Booking(s) successfully editted: " + String.Join(", ", editBookings.Select(x => x.ID)));

            if (!bool.Parse(appSettings["sendEmails"].ToString()))
            {
                _logger.Debug("SendEmails config is false or empty - Skipping email sending");
                _logger.Trace(LoggerHelper.ExecutedFunctionMessage(LoggerHelper.VOID_TYPE, existingBooking, editBooking, recurrence, user, appSettings));
                return;
            }

            string fromEmail = appSettings["fromEmail"];

            if (
                editBookings.Select(x => (x.Flipchart != originalBookings.Where(y => y.ID == x.ID).First().Flipchart)).Count() > 0
                || editBookings.Select(x => (x.Projector != originalBookings.Where(y => y.ID == x.ID).First().Projector)).Count() > 0)
            {
                SendEmailToFacilitiesForEdit(fromEmail, editBooking, editBookings, originalBookings);
            }

            if (editBookings.Select(x => (x.DssAssist != originalBookings.Where(y => y.ID == x.ID).First().DssAssist)).Count() > 0)
                SendEmailToDSSForEdit(fromEmail, editBooking, editBookings, originalBookings);


            Func<Booking, Booking, bool> attendeeCompare = delegate (Booking newBooking, Booking currentBooking)
            {
                return !(new HashSet<string>(currentBooking.ExternalAttendees.Select(x => x.FullName)).SetEquals(newBooking.ExternalAttendees.Select(x => x.FullName)));
            };
            if (editBookings.Select(x => attendeeCompare(x, originalBookings.Where(y => y.ID == x.ID).First())).Count() > 0)
                SendEmailToSecurityForEdit(fromEmail, editBooking, editBookings, originalBookings);

            if (existingBooking.PID.ToUpper() != user.PayId.Identity.ToUpper())
                SendEmailToOwnerForAdminEdit(fromEmail, existingBooking, editBookings);
            else
                SendEmailToOwnerForEdit(fromEmail, existingBooking, editBookings, user);

        }

        public void SaveNewBooking(Booking newBooking, User user, NameValueCollection appSettings)
        {
            List<Booking> bookingsToCreate = new List<Booking>();
            List<Booking> clashedBookings = new List<Booking>();
            List<Booking> deletedBookings = new List<Booking>();

            Room bookingRoom = _roomsRepository.GetRoomById(newBooking.RoomID);
            newBooking.RoomID = newBooking.Room.ID;

            /*Apply the current users details as the owner, in the case of no owner set. 
            By default, a filled in owner field means it was booked on behalf of. */
            if (string.IsNullOrEmpty(newBooking.Owner))
            {
                newBooking.Owner = user.FullName;
                newBooking.PID = user.PayId.Identity;
            }

            if (newBooking.Recurrence.IsRecurring)
            {
{'fraction_non_alphanumeric': 0.08979900583531446, 'fraction_numerical': 0.0006483682731791658, 'mean_word_length': 2.515479582146249, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 71, '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': '4717939', 'n_tokens_mistral': 4968, 'n_tokens_neox': 4753, 'n_words': 902}