/// <summary>
        /// Create booking event
        /// </summary>
        /// <param name="bookingEventDto">BookingEventDto</param>
        /// <returns>BookingEvent</returns>
        private BookingEvent CreateBookingEventEntity(BookingEventDto bookingEventDto)
        {
            // Convert to UTC Time
            bookingEventDto.CreatedDate = bookingEventDto.CreatedDate.ConvertToUTCTime();
            bookingEventDto.ModifiedDate = bookingEventDto.ModifiedDate.ConvertToUTCTime();

            // Set IsRead default is false
            bookingEventDto.IsRead = false;

            BookingEvent bookingEvent = bookingEventDto.ExposedAs<BookingEvent>(Repository);
            Repository.Insert<BookingEvent>(bookingEvent);
            UnitOfWork.Save();

            bookingEventDto.Id = bookingEvent.Id;
            return bookingEvent;
        }
        /// <summary>
        /// Update a booking event
        /// </summary>
        /// <param name="bookingEvent"></param>
        /// <returns></returns>
        public BookingEventDto UpdateBookingEvent(BookingEventDto bookingEvent)
        {
            Repository.Update<BookingEvent>(bookingEvent.ExposedAs<BookingEvent>(Repository));
            UnitOfWork.Save();

            return bookingEvent;
        }
        /// <summary>
        /// Create a booking event
        /// </summary>
        /// <param name="bookingEvent"></param>
        /// <param name="type">AlertDescription</param>
        /// <returns></returns>
        public BookingEventDto CreateBookingEvent(BookingEventDto bookingEvent)
        {
            try
            {
                CreateBookingEventEntity(bookingEvent);
                bookingEvent.Description = CreateBookingEventDescription(bookingEvent);

                System.Threading.Tasks.Task.Factory.StartNew(() =>
                {
                    // Send email and SMS to notify
                    new MailService().SendMail(
                        ConstEmailTemplateKey.BookingEventTemplate,
                        bookingEvent.TargetUser.Email,
                        string.Format(bookingEvent.EmailAlertSubject, bookingEvent.Booking.ReferenceNo),
                            new
                            {
                                BaseUrl = AppSettings.BaseUrl,
                                content = bookingEvent.EmailAlertDetail.Replace("\n", "<br/>")
                            }, "", null);

                    new CommonService().SendSMS(bookingEvent.TargetUser.MobileCountryCode + bookingEvent.TargetUser.MobilePhone, bookingEvent.SMSAlertDetail);
                });

                return bookingEvent;
            }
            catch (Exception e)
            {
                Log.Error("BookingService_CreateBookingEvent. Error: {0}", e);
                return null;
            }
        }
        /// <summary>
        /// create booking event description base on the type of alert
        /// Using only in send email as soon as creating the Booking Event
        /// We dont use this description for showing in popup in the future.
        /// </summary>
        /// <param name="typeOfAlert">AlertDescription</param>
        public string CreateBookingEventDescription(BookingEventDto bookingEvent)
        {
            string name = "";
            DateTime? startDate = bookingEvent.Booking.StartTime;
            DateTime? endDate = bookingEvent.Booking.EndTime;
            string userTimeZone = string.Empty;
            string path = AppSettings.BaseUrl + "/Booking/ListBooking?id=" + bookingEvent.Booking.Id
                    + "&status=" + (int)bookingEvent.Booking.Status;
            string url = "<a href=" + path + ">here</a>";

            switch (bookingEvent.Description)
            {
                case AlertDescription.BookingRequestMade:
                case AlertDescription.SpecialistActionRequiredOnBookingRequest:
                case AlertDescription.BookingTimeApproachForConsult:
                case AlertDescription.BookingRequestConfirmedToConsult:
                case AlertDescription.SpecialistsProposedScheduleDeclined:
                case AlertDescription.ConfirmedBookingTimeApproachToSpecialist:
                case AlertDescription.ConfirmedBookingIsCancelledByCustomer:
                case AlertDescription.EndOfConsultationWindow:
                    name = bookingEvent.Booking.Customer.Name;
                    userTimeZone = bookingEvent.Booking.Customer.Locations[0].TimeZone;
                    break;

                case AlertDescription.FileUploadedToBookingByCustomer:
                    name = bookingEvent.Booking.Customer.Name;
                    userTimeZone = bookingEvent.Booking.Customer.Locations[0].TimeZone;
                    path = AppSettings.BaseUrl + "/Booking/FileUpload?id=" + bookingEvent.Booking.Id
                        + "&name=" + bookingEvent.Booking.DocumentPath;
                    url = "<a href=" + path + ">here</a>";
                    break;

                case AlertDescription.CustomerActionRequiredOnBookingRequest:
                case AlertDescription.ConfirmedBookingTimeApproachToCustomer:
                case AlertDescription.BookingRequestConfirmedToCustomer:
                case AlertDescription.BookingRequestDeclined:
                case AlertDescription.CustomersProposedScheduleDeclined:
                case AlertDescription.BookingTimeApproachForCustomer:
                case AlertDescription.ConfirmedBookingIsCancelledBySpecialist:
                case AlertDescription.FailedConferenceAttemptAtFirst:
                case AlertDescription.FailedConferenceAttemptAtSecond:
                case AlertDescription.FailedAttemptsCancellation:
                    name = bookingEvent.Booking.Specialist.Name;
                    userTimeZone = bookingEvent.Booking.Specialist.Locations[0].TimeZone;
                    break;

                case AlertDescription.FileUploadedToBookingBySpecialist:
                    name = bookingEvent.Booking.Specialist.Name;
                    userTimeZone = bookingEvent.Booking.Specialist.Locations[0].TimeZone;
                    path = AppSettings.BaseUrl + "/Booking/FileUpload?id=" + bookingEvent.Booking.Id
                        + "&name=" + bookingEvent.Booking.DocumentPath;
                    url = "<a href=" + path + ">here</a>";
                    break;
            }
            string cost = Role.Specialist.Equals(bookingEvent.TargetUser.Role)
                            ? bookingEvent.Booking.RatePerMinute.ToString("n2")
                            : bookingEvent.Booking.CostPerMinute.ToString("n2");
            if (endDate != null)
            {
                TimeZoneInfo destinationTimeZone = TimeZoneInfo.FindSystemTimeZoneById(Utilities.GetTimeZoneIdByName(userTimeZone));
                startDate = TimeZoneInfo.ConvertTime(
                    bookingEvent.Booking.StartTime.Value, TimeZoneInfo.Utc, destinationTimeZone);
                endDate = TimeZoneInfo.ConvertTime(
                    bookingEvent.Booking.EndTime.Value, TimeZoneInfo.Utc, destinationTimeZone);
            }

            if (bookingEvent.EmailAlertDetail != null)
            {
                bookingEvent.EmailAlertDetail = string.Format(bookingEvent.EmailAlertDetail,
                        bookingEvent.Booking.ReferenceNo,
                        name,
                        bookingEvent.Booking.Type == BookingType.ASAP
                        && !BookingStatus.Confirmed.Equals(bookingEvent.Booking.Status) //check booking confirm will send time
                        && !(Role.Specialist.Equals(bookingEvent.TargetUser.Role)
                        && BookingStatus.SpecialistRescheduled.Equals(bookingEvent.Booking.Status)) //check booking request just confirm and send for specialist, we will send time
                        ? "ASAP"
                        : "from " + startDate.Value.ToString(DateTimeHelper.GlobalDateTimeFormat)
                            + " to " + endDate.Value.ToString(DateTimeHelper.GlobalDateTimeFormat),
                        cost,
                        url);
            }
            if (bookingEvent.SMSAlertDetail != null)
            {
                bookingEvent.SMSAlertDetail = string.Format(bookingEvent.SMSAlertDetail,
                        bookingEvent.Booking.ReferenceNo,
                        name,
                        bookingEvent.Booking.Type == BookingType.ASAP
                        && !BookingStatus.Confirmed.Equals(bookingEvent.Booking.Status) //check booking confirm will send time
                        && !(Role.Specialist.Equals(bookingEvent.TargetUser.Role)
                        && BookingStatus.SpecialistRescheduled.Equals(bookingEvent.Booking.Status))
                        ? "ASAP"
                        : "from " + startDate.Value.ToString(DateTimeHelper.GlobalDateTimeFormat)
                            + " to " + endDate.Value.ToString(DateTimeHelper.GlobalDateTimeFormat),
                        cost,
                        path);
            }
            return string.Format(bookingEvent.Description,
                bookingEvent.Booking.ReferenceNo,
                name,
                bookingEvent.Booking.Type == BookingType.ASAP
                && !BookingStatus.Confirmed.Equals(bookingEvent.Booking.Status) //check booking confirm will send time
                && !(Role.Specialist.Equals(bookingEvent.TargetUser.Role)
                && BookingStatus.SpecialistRescheduled.Equals(bookingEvent.Booking.Status))
                ? "ASAP"
                : "from " + startDate.Value.ToString(DateTimeHelper.GlobalDateTimeFormat)
                    + " to " + endDate.Value.ToString(DateTimeHelper.GlobalDateTimeFormat),
                cost,
                url);
        }
        // -------------------- .GET -------------------- //
        // -------------------- CREATE -------------------- //
        /// <summary>
        /// Create a booking
        /// </summary>
        /// <param name="booking"></param>
        /// <returns></returns>
        public BookingDto Create(BookingDto booking)
        {
            // IRepository repository = Repository;
            var book = booking.ExposedAs<Booking>(Repository);
            book.ReferenceNo = GetBookingReferenceNo();
            // Convert date time to UTC
            book.CreatedDate = DateTime.UtcNow;
            book.ModifiedDate = DateTime.UtcNow;

            Repository.Insert<Booking>(book);
            UnitOfWork.Save();

            booking = book.ExposedAs<BookingDto>();

            // Add to booking event for consultant
            if (booking.Type != BookingType.TalkNow)
            {
                var bookingEventDto = new BookingEventDto
                {
                    Booking = booking,
                    SourceUser = booking.Customer,
                    TargetUser = booking.Specialist,
                    ShortDescription = AlertShortDescription.BookingRequestMade,
                    Description = AlertDescription.BookingRequestMade,
                    CreatedDate = DateTime.UtcNow,
                    ModifiedDate = DateTime.UtcNow,
                    IsRead = false,
                    EmailAlertSubject = EmailAlertSubject.BookingRequestMade,
                    EmailAlertDetail = EmailAlertDetail.BookingRequestMade,
                    SMSAlertDetail = SMSAlertDetail.BookingRequestMade
                };

                CreateBookingEvent(bookingEventDto);
            }

            return booking;
        }