public static void LogAddReservation(this UsersContext db, Reservation reservation, UserProfile loginUser, UserProfile pinUser)
        {
            string comment;
            var audit = new ReservationAudit();

            if (pinUser != null)
            {
                comment = string.Format(ReservationComments.Added_New_Reservation_UsingPIN,
                    loginUser.FirstName + " " + loginUser.LastName,
                    pinUser.UserCode);

                audit.PinUserId = pinUser.Id;
            }
            else
                comment = string.Format(ReservationComments.Added_New_Reservation,
                    loginUser.FirstName + " " + loginUser.LastName);

            audit.Comment = comment;
            audit.ReservationId = reservation.ReservationId;
            audit.LoginUserId = loginUser.Id;
            audit.CreatedOn = DateTime.UtcNow;
            audit.Action = "Created";
            audit.TimeForm = reservation.TimeForm;
            audit.TableName = reservation.FloorTableId > 0 ? db.tabFloorTables.Find(reservation.FloorTableId).TableName : db.tabMergedFloorTables.Find(reservation.MergedFloorTableId).TableName;
            audit.Covers = reservation.Covers;
            audit.Notes = reservation.ReservationNote ?? string.Empty;
            audit.TimeTo = reservation.TimeTo;
            audit.StatusId = (int)reservation.StatusId.Value;

            db.tabReservationAudits.Add(audit);
        }
        /// <summary>
        /// Sends a success message to customer
        /// </summary>
        /// <param name="reservation">Resrervation</param>
        public virtual void SendCustomerBookingSuccess(UrlHelper urlHelper, Reservation reservation, UsersContext db)
        {
            if (reservation == null)
                throw new ArgumentNullException("reseravation");

            if (reservation.Customers.Emails == null)
                return;

            var customerEmail = reservation.Customers.Emails.LastOrDefault();
            if (customerEmail == null)
                return;

            var messageTemplate = GetActiveMessageTemplate("Customer.OnlineBookingSucceed", db);
            if (messageTemplate == null)
                return;

            //tokens
            var tokens = new List<Token>();
            tokens.Add(new Token("ReservationId", reservation.ReservationId.ToString()));
            tokens.Add(new Token("ReservationDate", reservation.ReservationDate.ToString("ddd, MMM dd, yyyy")));
            tokens.Add(new Token("TimeForm", reservation.TimeForm.ToString("h:mm tt")));
            tokens.Add(new Token("Covers", reservation.Covers.ToString()));
            //tokens.Add(new Token("FullName", reservation.Customers.FirstName + " " +
            //    ((reservation.Customers.LastName.Length > 1) ? reservation.Customers.LastName.Remove(1) : reservation.Customers.LastName)));
            tokens.Add(new Token("FullName", reservation.Customers.FirstName));
            //tokens.Add(new Token("EditUrl", System.Web.HttpContext.Current.Request.Url.Host + "/Online/ReserveSuccess/" + reservation.ReservationId));
            tokens.Add(new Token("EditUrl", urlHelper.EncodedUrl("ReserveSuccess", "Online", new { id = reservation.ReservationId })));
            tokens.Add(new Token("CancelUrl", urlHelper.EncodedUrl("ReserveSuccess", "Online", new { id = reservation.ReservationId })));
            //tokens.Add(new Token("AppUrl", System.Web.HttpContext.Current.Request.Url.Host));
            tokens.Add(new Token("AppUrl", "http://media.vanfish.com/reservation_email"));

            var fromAddress = (string)ConfigurationManager.AppSettings["Email_To"];
            var fromName = (string)ConfigurationManager.AppSettings["Email_To"];

            var toEmail = customerEmail.Email;
            var toName = reservation.Customers.FirstName;

            this.SendNotification(messageTemplate, fromAddress, fromName,
                tokens, toEmail, toName);
        }
        public ActionResult ReservationSave(DateTime date, string fname, string lname, string shift, string mobileNo, string email, int cover, string time, Int64 tableId, Int64 floorId, string TopTablePosition, string LeftTablePosition)
        {
            email = email.Trim();
            mobileNo = mobileNo.Trim();
            shift = shift.Trim();

            var tt = time.Split('-');

            var startTime = date.Add(DateTime.ParseExact(tt[0].Trim(), "ddMMyyyyhhmmtt", CultureInfo.InvariantCulture).TimeOfDay);
            var endTime = date.Add(DateTime.ParseExact(tt[1].Trim(), "ddMMyyyyhhmmtt", CultureInfo.InvariantCulture).TimeOfDay);

            var customer = Db.tabCustomers.Where(c => c.PhoneNumbers.Any(cn => cn.PhoneNumbers.Contains(mobileNo))).FirstOrDefault();

            int shiftId = Convert.ToInt32(tt[2]);
            //if (shift == "All")
            //{
            //    var sh = Db.tabMenuShiftHours.AsEnumerable();

            //    if (endTime.Date == startTime.AddDays(1).Date)
            //    {
            //        DateTime openAt = new DateTime();
            //        DateTime closeAt = new DateTime();

            //        //var shifts = sh.Where(s => (DateTime.TryParse(s.OpenAt, out openAt) && (startTime.TimeOfDay >= openAt.TimeOfDay)) && (DateTime.TryParse(s.CloseAt, out closeAt) && (startTime.TimeOfDay <= closeAt.AddMinutes(-15).TimeOfDay))).FirstOrDefault();
            //        shiftId = 1;
            //    }
            //    else
            //{
            //        DateTime openAt = new DateTime();
            //        DateTime closeAt = new DateTime();
            //        var shifts = sh.Where(s => (DateTime.TryParse(s.OpenAt, out openAt) && (startTime.TimeOfDay >= openAt.TimeOfDay)) && (DateTime.TryParse(s.CloseAt, out closeAt) && (startTime.TimeOfDay <= closeAt.AddMinutes(-15).TimeOfDay))).FirstOrDefault();

            //        shiftId = shifts.FoodMenuShiftId;
            //    }
            //}
            //else
            //{
            //    shiftId = Db.tabFoodMenuShift.Where(s => s.MenuShift.Contains(shift)).Single().FoodMenuShiftId;
            //}

            if (customer != null)
            {
                var reservation = new Reservation()
                {
                    FloorPlanId = floorId,
                    Covers = cover,
                    CustomerId = customer.CustomerId,
                    FoodMenuShiftId = shiftId,
                    ReservationDate = date,
                    TimeForm = startTime,
                    TimeTo = endTime,
                    FloorTableId = tableId,
                    StatusId = 13,
                    UserId = User.Identity.GetUserId<long>(),
                    TablePositionLeft = LeftTablePosition,
                    TablePositionTop = TopTablePosition
                };

                Db.tabReservations.Add(reservation);

            }
            else
            {
                var cust = new Customers()
                {
                    FirstName = fname,
                    LastName = lname,
                    DateCreated = DateTime.UtcNow,
                    DateOfBirth = DateTime.UtcNow,
                    Address1 = "1",
                    Address2 = "2",
                    Anniversary = DateTime.UtcNow,
                };

                Db.tabCustomers.Add(cust);

                if (!string.IsNullOrEmpty(email))
                {
                    var cemail = new CustomersEmails()
                    {
                        CustomerId = cust.CustomerId,
                        Email = email,
                        EmailTypeId = 1
                    };
                    Db.tabCustomersEmails.Add(cemail);
                }

                var cphone = new CustomersPhoneNumbers()
                {
                    CustomerId = cust.CustomerId,
                    PhoneNumbers = mobileNo,
                    PhoneTypeId = 1
                };

                Db.tabCustomersPhoneNumbers.Add(cphone);

                var reservation = new Reservation()
                {
                    FloorPlanId = floorId,
                    Covers = cover,
                    CustomerId = cust.CustomerId,
                    FoodMenuShiftId = shiftId,
                    ReservationDate = date,
                    TimeForm = startTime,
                    TimeTo = endTime,
                    FloorTableId = tableId,
                    StatusId = 13,
                    UserId = User.Identity.GetUserId<long>(),
                    TablePositionLeft = LeftTablePosition,
                    TablePositionTop = TopTablePosition
                };
                Db.tabReservations.Add(reservation);
            }

            Db.SaveChanges();
            return null;
        }
        public ActionResult SaveReservationWithPIN(ReservationVM model)
        {
            try
            {
                var loginUser = db.Users.Find(User.Identity.GetUserId<long>());
                UserProfile pinUser = null;
                Waiting waiting = null;

                if ((model.PIN.HasValue || loginUser.EnablePIN) && !model.MobileNumber.Contains("9999999999"))
                {
                    pinUser = db.Users.Where(u => u.UserCode == model.PIN.Value).FirstOrDefault();

                    if (pinUser == null)
                    {
                        return Json(new
                        {
                            Status = ResponseStatus.Fail,
                            Message = "Please enter a valid user PIN."
                        }, JsonRequestBehavior.AllowGet);
                    }
                }

                FloorTableServer server = null;
                var fTblId = Convert.ToInt64(model.tableIdd);

                if (fTblId == 0 && model.MergeTableId == 0)
                {
                    return Json(new
                    {
                        Status = ResponseStatus.Fail,
                        Message = "Please select a table."
                    }, JsonRequestBehavior.AllowGet);
                }
                else
                {
                    if (fTblId > 0)
                    {
                        var flrTbl = db.tabFloorTables.Find(fTblId);
                        model.FloorPlanId = flrTbl.FloorPlanId;
                        model.MergeTableId = 0;
                        server = flrTbl.FloorTableServer;
                    }
                    else
                    {
                        model.FloorPlanId = db.tabMergedFloorTables.Find(model.MergeTableId.Value).FloorPlanId;
                    }
                }

                double time = 0;
                long resId = 0;
                if (!string.IsNullOrEmpty(model.Email))
                {
                    model.Email = model.Email.Trim();
                }

                model.MobileNumber = model.MobileNumber.Trim();
                // model.ShiftId = model.ShiftId;

                var tt = model.time.Split('-');

                var startTime = model.resDate.Add(DateTime.ParseExact(tt[0].Trim(), "ddMMyyyyhhmmtt", CultureInfo.InvariantCulture).TimeOfDay);
                var endTime = model.resDate.Add(DateTime.ParseExact(tt[1].Trim(), "ddMMyyyyhhmmtt", CultureInfo.InvariantCulture).TimeOfDay);

                bool isFakeMobileNo = long.Parse(model.MobileNumber) == 0L;

                if (model.WaitingId > 0)
                {
                    waiting = db.tabWaitings.Find(model.WaitingId);
                }

                var customer = db.tabCustomers.Where(c => !isFakeMobileNo && c.PhoneNumbers.Any(cn => cn.PhoneNumbers.Contains(model.MobileNumber))).FirstOrDefault();

                if (isFakeMobileNo && waiting != null)
                {
                    customer = waiting.Customer;
                    customer.FirstName = model.FirstName;
                    customer.LastName = model.LastName;
                }

                model.ShiftId = Convert.ToInt32(tt[2]);

                model.Status = (!string.IsNullOrEmpty(model.Status)) ? model.Status : ReservationStatus.Not_confirmed.ToString();

                if (customer != null)
                {
                    var reservation = new Reservation()
                    {
                        FloorPlanId = model.FloorPlanId,
                        Covers = model.Covers,
                        CustomerId = customer.CustomerId,
                        FoodMenuShiftId = model.ShiftId,
                        ReservationDate = model.resDate,
                        TimeForm = startTime,
                        TimeTo = startTime.AddMinutes(model.Duration.GetMinutesFromDuration()),
                        FloorTableId = fTblId,
                        MergedFloorTableId = model.MergeTableId.Value,
                        StatusId = Convert.ToInt64(model.Status),
                        UserId = User.Identity.GetUserId<long>(),
                        TablePositionLeft = model.TablePositionLeft,
                        TablePositionTop = model.TablePositionTop,
                        Duration = model.Duration,
                        ReservationNote = model.ReservationNote,
                        CreatedOn = DateTime.UtcNow,
                        UpdatedBy = User.Identity.GetUserId<long>(),
                        UpdatedOn = DateTime.UtcNow
                    };

                    if (server != null && server.ServerId != null)
                    {
                        reservation.ReservationServer = new ReservationServer() { ServerId = server.ServerId.Value };
                    }

                    db.tabReservations.Add(reservation);

                    if (!string.IsNullOrEmpty(model.GuestNote))
                    {
                        customer.Notes = model.GuestNote;
                    }

                    if (!string.IsNullOrEmpty(model.Email))
                    {
                        if (customer.Emails == null || (customer.Emails != null && !customer.Emails.Any(ce => ce.Email.Contains(model.Email))))
                        {
                            var cemail = new CustomersEmails()
                            {
                                CustomerId = customer.CustomerId,
                                Email = model.Email,
                                EmailTypeId = 1
                            };
                            db.tabCustomersEmails.Add(cemail);
                        }
                    }

                    time = reservation.TimeForm.TimeOfDay.TotalMinutes;

                    db.LogAddReservation(reservation, loginUser, pinUser);
                }
                else
                {
                    var cust = new Customers()
                    {
                        FirstName = model.FirstName,
                        LastName = model.LastName,
                        DateCreated = DateTime.UtcNow.ToDefaultTimeZone(User.Identity.GetDatabaseName()),
                        DateOfBirth = DateTime.UtcNow.ToDefaultTimeZone(User.Identity.GetDatabaseName()),
                        Address1 = "1",
                        Address2 = "2",
                        Anniversary = DateTime.UtcNow.ToDefaultTimeZone(User.Identity.GetDatabaseName()),
                    };

                    db.tabCustomers.Add(cust);

                    if (!string.IsNullOrEmpty(model.Email))
                    {
                        var cemail = new CustomersEmails()
                        {
                            CustomerId = cust.CustomerId,
                            Email = model.Email,
                            EmailTypeId = 1
                        };
                        db.tabCustomersEmails.Add(cemail);
                    }

                    var cphone = new CustomersPhoneNumbers()
                    {
                        CustomerId = cust.CustomerId,
                        PhoneNumbers = model.MobileNumber,
                        PhoneTypeId = 1
                    };

                    db.tabCustomersPhoneNumbers.Add(cphone);

                    var reservation = new Reservation()
                    {
                        FloorPlanId = model.FloorPlanId,
                        Covers = model.Covers,
                        CustomerId = cust.CustomerId,
                        FoodMenuShiftId = model.ShiftId,
                        ReservationDate = model.resDate,
                        TimeForm = startTime,
                        TimeTo = startTime.AddMinutes(model.Duration.GetMinutesFromDuration()),
                        FloorTableId = fTblId,
                        MergedFloorTableId = model.MergeTableId.Value,
                        StatusId = Convert.ToInt64(model.Status),
                        UserId = User.Identity.GetUserId<long>(),
                        TablePositionLeft = model.TablePositionLeft,
                        TablePositionTop = model.TablePositionTop,
                        Duration = model.Duration,
                        ReservationNote = model.ReservationNote,
                        CreatedOn = DateTime.UtcNow,
                        UpdatedBy = User.Identity.GetUserId<long>(),
                        UpdatedOn = DateTime.UtcNow
                    };

                    if (server != null && server.ServerId != null)
                    {
                        reservation.ReservationServer = new ReservationServer() { ServerId = server.ServerId.Value };
                    }

                    db.tabReservations.Add(reservation);

                    if (!string.IsNullOrEmpty(model.GuestNote))
                    {
                        cust.Notes = model.GuestNote;
                    }

                    time = reservation.TimeForm.TimeOfDay.TotalMinutes;

                    db.LogAddReservation(reservation, loginUser, pinUser);
                }

                if (waiting != null)
                {
                    waiting.ReservationId = resId;
                    db.Entry(waiting).State = EntityState.Modified;

                    ClearWaitingCache();
                }

                db.SaveChanges();

                return Json(new
                {
                    Status = ResponseStatus.Success,
                    Message = "Reservation saved successfully.",
                    Time = time
                }, JsonRequestBehavior.AllowGet);
            }
            catch (Exception)
            {
                return Json(new
                {
                    Status = ResponseStatus.Fail,
                    Message = "Failed to save reservation, please try later..."
                }, JsonRequestBehavior.AllowGet);
            }
            finally
            {
                this.ClearReservationCache(model.resDate);
            }
        }
        private bool AnyReservation(long tableId, DateTime startTime, DateTime endTime, Reservation reservation = null)
        {
            var reservations = context.GetReservationByDate(startTime.Date);

            if (reservation != null)
                reservations = reservations.Where(r => r.ReservationId != reservation.ReservationId).ToList();

            return reservations.Any(r => !r.IsDeleted
                && (r.FloorTableId == 0 ? r.MergedFloorTable.OrigionalTables.Any(t => t.FloorTableId == tableId) : r.FloorTableId == tableId)
                && r.ReservationDate == startTime.Date
                //&& (r.TimeForm <= startTime && startTime < r.TimeTo));
                && ((r.TimeForm <= startTime && r.TimeTo >= endTime)
                || (r.TimeForm >= startTime && r.TimeTo <= endTime)
                || (r.TimeForm < startTime && r.TimeTo > startTime)
                || (r.TimeForm < endTime && r.TimeTo > endTime)));
        }
        public ActionResult Reserve(ReservationVM model)
        {
            Reservation reservation = null;

            try
            {
                var onlineUserName = context.Users.Where(c => c.Roles.Any(ur => ur.RoleId == context.Roles.Where(r => r.Name == "Online").FirstOrDefault().Id)).Single().UserName;
                var onlineUser = context.Users.Where(u => u.UserName.Contains(onlineUserName)).First();

                FloorTableServer server = null;
                var fTblId = Convert.ToInt64(model.tableIdd);

                var flrTbl = context.tabFloorTables.Find(fTblId);
                model.FloorPlanId = flrTbl.FloorPlanId;
                model.MergeTableId = 0;
                server = flrTbl.FloorTableServer;

                double time = 0;
                if (!string.IsNullOrEmpty(model.Email))
                {
                    model.Email = model.Email.Trim();
                }

                model.MobileNumber = model.MobileNumber.Trim();
                // model.ShiftId = model.ShiftId;

                var startTime = model.resDate.Add(DateTime.ParseExact(model.time.Trim(), "h:mm tt", CultureInfo.InvariantCulture).TimeOfDay);

                bool isFakeMobileNo = long.Parse(model.MobileNumber) == 0L;

                var customer = context.tabCustomers.Where(c => !isFakeMobileNo && c.PhoneNumbers.Any(cn => cn.PhoneNumbers.Contains(model.MobileNumber))).FirstOrDefault();

                int tShiftId = 0;

                var openTM = new DateTime();
                var closeTM = new DateTime();

                var day = model.resDate.DayOfWeek.ToString();
                var dId = context.GetWeekDays().Single(p => p.DayName.Contains(day)).DayId;

                var aa = context.GetMenuShiftHours().AsEnumerable().Where(p => p.DayId == dId);
                var timeShift = aa.Where(s => (DateTime.TryParse(s.OpenAt, out openTM) && DateTime.TryParse(s.CloseAt, out closeTM)) &&
                    startTime.Date.Add(openTM.TimeOfDay) <= startTime &&
                    startTime.Date.Add(closeTM.TimeOfDay).AddDays(s.IsNext.Value) >= startTime).FirstOrDefault();

                if (timeShift != null)
                {
                    tShiftId = timeShift.FoodMenuShiftId;
                }

                model.ShiftId = tShiftId;

                model.Status = (!string.IsNullOrEmpty(model.Status)) ? model.Status : ReservationStatus.Online_Booking.ToString();

                #region Old Customer
                //if (customer != null)
                //{
                if (customer != null &&
                   StringComparer.OrdinalIgnoreCase.Equals(customer.FirstName.Trim(), model.FirstName.Trim()) &&
                   StringComparer.OrdinalIgnoreCase.Equals(customer.FirstName.Trim(), model.FirstName.Trim()))
                {
                    reservation = new Reservation()
                    {
                        FloorPlanId = model.FloorPlanId,
                        Covers = model.Covers,
                        CustomerId = customer.CustomerId,
                        FoodMenuShiftId = model.ShiftId,
                        ReservationDate = model.resDate,
                        TimeForm = startTime,
                        TimeTo = startTime.AddMinutes(model.Duration.GetMinutesFromDuration()),
                        FloorTableId = fTblId,
                        MergedFloorTableId = model.MergeTableId.Value,
                        StatusId = Convert.ToInt64(model.Status),
                        UserId = onlineUser.Id,
                        TablePositionLeft = model.TablePositionLeft,
                        TablePositionTop = model.TablePositionTop,
                        Duration = model.Duration,
                        ReservationNote = model.ReservationNote,
                        CreatedOn = DateTime.UtcNow,
                        UpdatedBy = onlineUser.Id,
                        UpdatedOn = DateTime.UtcNow
                    };

                    if (server != null && server.ServerId != null)
                    {
                        reservation.ReservationServer = new ReservationServer() { ServerId = server.ServerId.Value };
                    }

                    context.tabReservations.Add(reservation);

                    if (!string.IsNullOrEmpty(model.GuestNote))
                    {
                        customer.Notes = model.GuestNote;
                    }

                    if (!string.IsNullOrEmpty(model.Email))
                    {
                        if (customer.Emails == null || (customer.Emails != null && !customer.Emails.Any(ce => ce.Email.Contains(model.Email))))
                        {
                            var cemail = new CustomersEmails()
                            {
                                CustomerId = customer.CustomerId,
                                Email = model.Email,
                                EmailTypeId = 1
                            };
                            context.tabCustomersEmails.Add(cemail);
                        }
                    }

                    time = reservation.TimeForm.TimeOfDay.TotalMinutes;

                    context.LogAddReservation(reservation, onlineUser, null);
                }
                #endregion
                #region new customer
                else
                {
                    var cust = new Customers()
                    {
                        FirstName = model.FirstName,
                        LastName = model.LastName,
                        DateCreated = DateTime.UtcNow, //.ToClientTime(),
                        DateOfBirth = DateTime.UtcNow, //.ToClientTime(),
                        Address1 = "1",
                        Address2 = "2",
                        Anniversary = DateTime.UtcNow //.ToClientTime(),
                    };

                    context.tabCustomers.Add(cust);

                    if (!string.IsNullOrEmpty(model.Email))
                    {
                        var cemail = new CustomersEmails()
                        {
                            CustomerId = cust.CustomerId,
                            Email = model.Email,
                            EmailTypeId = 1
                        };
                        context.tabCustomersEmails.Add(cemail);
                    }

                    var cphone = new CustomersPhoneNumbers()
                    {
                        CustomerId = cust.CustomerId,
                        PhoneNumbers = model.MobileNumber,
                        PhoneTypeId = 1
                    };

                    context.tabCustomersPhoneNumbers.Add(cphone);

                    reservation = new Reservation()
                    {
                        FloorPlanId = model.FloorPlanId,
                        Covers = model.Covers,
                        CustomerId = cust.CustomerId,
                        FoodMenuShiftId = model.ShiftId,
                        ReservationDate = model.resDate,
                        TimeForm = startTime,
                        TimeTo = startTime.AddMinutes(model.Duration.GetMinutesFromDuration()),
                        FloorTableId = fTblId,
                        MergedFloorTableId = model.MergeTableId.Value,
                        StatusId = Convert.ToInt64(model.Status),
                        UserId = onlineUser.Id,
                        TablePositionLeft = model.TablePositionLeft,
                        TablePositionTop = model.TablePositionTop,
                        Duration = model.Duration,
                        ReservationNote = model.ReservationNote,
                        CreatedOn = DateTime.UtcNow,
                        UpdatedBy = onlineUser.Id,
                        UpdatedOn = DateTime.UtcNow
                    };

                    if (server != null && server.ServerId != null)
                    {
                        reservation.ReservationServer = new ReservationServer() { ServerId = server.ServerId.Value };
                    }

                    context.tabReservations.Add(reservation);

                    if (!string.IsNullOrEmpty(model.GuestNote))
                    {
                        cust.Notes = model.GuestNote;
                    }

                    time = reservation.TimeForm.TimeOfDay.TotalMinutes;

                    context.LogAddReservation(reservation, onlineUser, null);
                }

                #endregion

                context.SaveChanges();

                _wfmService.SendCustomerBookingSuccess(this.Url, reservation,context);

                return Redirect(this.Url.EncodedUrl("ReserveSuccess", "Online", new { id = reservation.ReservationId, company = context.Database.Connection.Database }));
            }
            catch (SmtpException)
            {
                return Redirect(this.Url.EncodedUrl("ReserveSuccess", "Online", new { id = reservation.ReservationId ,company=context.Database.Connection.Database}));
            }
            catch (Exception)
            {
                return RedirectToAction("ReserveFail", new { id = 2, company = context.Database.Connection.Database });
            }
            finally
            {
                this.ClearReservationCache(context.Database.Connection.Database);
            }
        }
        //private OnlineAvailTables GetMatchedAvailabilities(DateTime date, string time, int covers)
        //{
        //    var tt = time.Split('-');
        //    var startTime = date.Add(DateTime.ParseExact(tt[0].Trim(), "ddMMyyyyhhmmtt", CultureInfo.InvariantCulture).TimeOfDay);
        //    var endTime = startTime.AddMinutes(15);
        //    var array = new string[] { "Sofa", "Chair", "SofaTable", "Wall", "SolidWall", "GlassWall", "BarTable", "Fence", "Pillar" };
        //    var tableDB = context.tabFloorTables.Where(p => p.IsDeleted == false).ToList()
        //        .Where(p => !array.Contains(p.TableName.Split('-')[0])
        //         && p.MaxCover >= covers).ToList();
        //    var day = date.DayOfWeek.ToString();
        //    var dId = context.GetWeekDays().Single(p => p.DayName.Contains(day)).DayId;
        //    var availList = context.tabTableAvailabilities
        //        .Include("TableAvailabilityFloorTables")
        //        .Include("TableAvailabilityWeekDays")
        //        .Where(ta => ta.StartDate <= date && date <= ta.EndDate
        //        && ta.TableAvailabilityWeekDays.Any(taw => taw.DayId == dId)).ToList();
        //    var model = new OnlineAvailTables();
        //    var exactMatchedDBTables = tableDB.Where(t => availList.CheckAvailStatus(date, startTime, endTime, t, 1)
        //        && !AnyReservation(t.FloorTableId, startTime, endTime)).ToList();
        //    if (exactMatchedDBTables.Count > 0)
        //    {
        //        model.ExactMatch = new TimeSlotAvailabilities
        //        {
        //            StartTime = startTime,
        //            EndTime = endTime,
        //            AvailableTables = exactMatchedDBTables
        //        };
        //    }
        //    var clientTime = DateTime.UtcNow.ToClientTime();
        //    clientTime = clientTime.AddMinutes(15 - (clientTime.TimeOfDay.Minutes % 15)).AddHours(2);
        //    var dayStartTime = (date == clientTime.Date) ? date.AddHours(clientTime.TimeOfDay.Hours).AddMinutes(clientTime.TimeOfDay.Minutes) : date;
        //    var dayEndTime = date.AddDays(1).AddMinutes(-15);
        //    while (dayStartTime <= dayEndTime)
        //    {
        //        if (dayStartTime != startTime)
        //        {
        //            var otherAvailabilities = tableDB.Where(t => availList.CheckAvailStatus(date, dayStartTime, dayStartTime.AddMinutes(15), t, 1)
        //                && !AnyReservation(t.FloorTableId, dayStartTime, dayStartTime.AddMinutes(15))).ToList();
        //            if (otherAvailabilities.Count > 0)
        //            {
        //                model.OtherMatches.Add(new TimeSlotAvailabilities
        //                {
        //                    StartTime = dayStartTime,
        //                    EndTime = dayStartTime.AddMinutes(15),
        //                    AvailableTables = otherAvailabilities
        //                });
        //            }
        //        }
        //        dayStartTime = dayStartTime.AddMinutes(15);
        //    }
        //    return model;
        //}
        //private OnlineAvailTables GetMatchedAvailabilities20150415(DateTime date, string time, int covers)
        //{
        //    var tt = time.Split('-');
        //    var startTime = date.Add(DateTime.ParseExact(tt[0].Trim(), "ddMMyyyyhhmmtt", CultureInfo.InvariantCulture).TimeOfDay);
        //    var endTime = startTime.AddMinutes(defaultDuration);
        //    var array = new string[] { "Sofa", "Chair", "SofaTable", "Wall", "SolidWall", "GlassWall", "BarTable", "Fence", "Pillar" };
        //    var tableDB = context.tabFloorTables.Where(p => p.IsDeleted == false).ToList()
        //        .Where(p => !array.Contains(p.TableName.Split('-')[0])
        //         && p.MaxCover >= covers).ToList();
        //    int dId;
        //    DateTime openTime;
        //    DateTime closeTime;
        //    GetOpenAndCloseTime(date, out dId, out openTime, out closeTime);
        //    var availList = context.tabTableAvailabilities
        //        .Include("TableAvailabilityFloorTables")
        //        .Include("TableAvailabilityWeekDays")
        //        .Where(ta => ta.StartDate <= date && date <= ta.EndDate
        //        && ta.TableAvailabilityWeekDays.Any(taw => taw.DayId == dId)).ToList();
        //    var model = new OnlineAvailTables();
        //    var exactMatchedDBTables = tableDB.Where(t => availList.CheckAvailStatus(date, startTime, endTime, t, 1)
        //        && !AnyReservation(t.FloorTableId, startTime)).ToList();
        //    if (exactMatchedDBTables.Count > 0)
        //    {
        //        model.ExactMatch = new TimeSlotAvailabilities
        //        {
        //            StartTime = startTime,
        //            EndTime = endTime,
        //            AvailableTables = exactMatchedDBTables
        //        };
        //    }
        //    var clientTime = DateTime.UtcNow.ToClientTime();
        //    clientTime = clientTime.AddMinutes(15 - (clientTime.TimeOfDay.Minutes % 15)).AddHours(2);
        //    var dayStartTime = (date == clientTime.Date) ? date.AddHours(clientTime.TimeOfDay.Hours).AddMinutes(clientTime.TimeOfDay.Minutes) : date;
        //    //var dayEndTime = date.AddDays(1).AddMinutes(-15);
        //    var otherStartTime = startTime.AddMinutes(-30);
        //    otherStartTime = otherStartTime >= dayStartTime ? otherStartTime : dayStartTime;
        //    var otherEndTime = startTime.AddMinutes(+30);
        //    if (otherEndTime > date.Add(closeTime.TimeOfDay).AddDays((closeTime.Day - openTime.Day)).AddMinutes(-1 * defaultDuration))
        //        otherEndTime = date.Add(closeTime.TimeOfDay).AddDays((closeTime.Day - openTime.Day)).AddMinutes(-1 * defaultDuration);
        //    while (otherStartTime <= otherEndTime)
        //    {
        //        var slotEndTime = otherStartTime.AddMinutes(defaultDuration);
        //        var otherAvailabilities = tableDB.Where(t => availList.CheckAvailStatus(date, otherStartTime, slotEndTime, t, 1)
        //            && !AnyReservation(t.FloorTableId, otherStartTime)).ToList();
        //        if (otherAvailabilities.Count > 0)
        //        {
        //            model.OtherMatches.Add(new TimeSlotAvailabilities
        //            {
        //                StartTime = otherStartTime,
        //                EndTime = slotEndTime,
        //                AvailableTables = otherAvailabilities
        //            });
        //        }
        //        otherStartTime = otherStartTime.AddMinutes(15);
        //    }
        //    return model;
        //}
        private OnlineAvailTables GetMatchedAvailabilities20150519(DateTime date, string time, int covers, Reservation reservation = null)
        {
            int dId;
            DateTime openTime;
            DateTime closeTime;
            var model = new OnlineAvailTables();

            var tt = time.Split('-');
            var startTime = date.Add(DateTime.ParseExact(tt[0].Trim(), "ddMMyyyyhhmmtt", CultureInfo.InvariantCulture).TimeOfDay);
            var endTime = startTime.AddMinutes(defaultDuration);

            var array = new string[] { "Sofa", "Chair", "SofaTable", "Wall", "SolidWall", "GlassWall", "BarTable", "Fence", "Pillar" };
            var tableDB = context.tabFloorTables.Where(p => p.IsDeleted == false).ToList()
                .Where(p => !array.Contains(p.TableName.Split('-')[0])
                 && p.MaxCover >= covers && covers >= p.MinCover).ToList();

            GetOpenAndCloseTime(date, out dId, out openTime, out closeTime);

            var availList = context.tabTableAvailabilities
                .Include("TableAvailabilityFloorTables")
                .Include("TableAvailabilityWeekDays")
                .Where(ta => ta.StartDate <= date && date <= ta.EndDate
                && ta.TableAvailabilityWeekDays.Any(taw => taw.DayId == dId)).ToList();

            var clientTime = DateTime.UtcNow.ToDefaultTimeZone(CompanyName); //.ToClientTime();
            clientTime = clientTime.AddMinutes(15 - (clientTime.TimeOfDay.Minutes % 15)).AddHours(2);

            var dayStartTime = (date == clientTime.Date) ? date.AddHours(clientTime.TimeOfDay.Hours).AddMinutes(clientTime.TimeOfDay.Minutes) : date;
            //var dayEndTime = date.AddDays(1).AddMinutes(-15);

            var otherStartTime = startTime.AddMinutes(-30);
            otherStartTime = otherStartTime >= dayStartTime ? otherStartTime : dayStartTime;

            var otherEndTime = startTime.AddMinutes(+30);

            if (otherEndTime > date.Add(closeTime.TimeOfDay).AddDays((closeTime.Day - openTime.Day)).AddMinutes(-1 * defaultDuration))
                otherEndTime = date.Add(closeTime.TimeOfDay).AddDays((closeTime.Day - openTime.Day)).AddMinutes(-1 * defaultDuration);

            while (otherStartTime <= otherEndTime)
            {
                var slotEndTime = otherStartTime.AddMinutes(defaultDuration);

                var otherAvailabilities = tableDB.Where(t => availList.CheckAvailStatus(date, otherStartTime, slotEndTime, t, 1)
                   && !AnyReservation(t.FloorTableId, otherStartTime, slotEndTime, reservation)).OrderBy(t => t.MinCover).ThenBy(t => t.MaxCover).ToList();

                // testing
                //var testResult = otherAvailabilities.Select(t => new { Min = t.MinCover, Max = t.MaxCover }).ToList();

                if (startTime == otherStartTime && endTime == slotEndTime)
                {
                    if (otherAvailabilities.Count > 0)
                    {
                        model.ExactMatch = new TimeSlotAvailabilities
                        {
                            StartTime = startTime,
                            EndTime = endTime,
                            AvailableTables = otherAvailabilities
                        };
                    }
                }

                if (otherAvailabilities.Count > 0)
                {
                    model.OtherMatches.Add(new TimeSlotAvailabilities
                    {
                        StartTime = otherStartTime,
                        EndTime = slotEndTime,
                        AvailableTables = otherAvailabilities
                    });
                }

                otherStartTime = otherStartTime.AddMinutes(15);
            }

            return model;
        }
        public static IEnumerable<FloorTable> GetAvailableFloorTables(this UsersContext db, Reservation reservation,
            out IList<Int64> upcomingTableIds, out IList<Int64> smallTableIds, out ReservationVM model,
            bool considerFloor = false, bool considerCovers = true, long ExceptionalMergeTableId = 0)
        {
            model = new ReservationVM
            {
                ReservationId = reservation.ReservationId,
                resDate = reservation.ReservationDate,
                Duration = reservation.Duration,
                Covers = reservation.Covers,
                time = new DateTime().Add(reservation.TimeForm.TimeOfDay).ToString("ddMMyyyyhhmmtt") +
                           " - " +
                           new DateTime().Add(reservation.TimeForm.AddMinutes(15).TimeOfDay).ToString("ddMMyyyyhhmmtt") +
                           " - " +
                           reservation.FoodMenuShiftId
            };

            return db.GetAvailableFloorTables(model, out upcomingTableIds, out smallTableIds, considerFloor, considerCovers, ExceptionalMergeTableId);
        }
        private bool TryShiftUpcomingReservationToOtherAvailableTable(UsersContext db, Reservation upcomingReservation)
        {
            ReservationVM model;
            IList<Int64> upcomingTableIds;
            IList<Int64> smallTableIds;
            var availableTable = db.GetAvailableFloorTables(upcomingReservation, out upcomingTableIds, out smallTableIds, out model, true, true)
                .Where(t => t.FloorTableId != upcomingReservation.FloorTableId);
            //.FirstOrDefault();

            #region Check for entries in tableavailabilities
            /**** Table availability feature enabled  start here *****/

            var tt = model.time.Split('-');
            var startTm = model.resDate.Add(DateTime.ParseExact(tt[0].Trim(), "ddMMyyyyhhmmtt", CultureInfo.InvariantCulture).TimeOfDay);
            var endTime = new DateTime();
            if (string.IsNullOrEmpty(model.Duration))
            {
                endTime = model.resDate.Add(DateTime.ParseExact(tt[1].Trim(), "ddMMyyyyhhmmtt", CultureInfo.InvariantCulture).TimeOfDay);
            }
            else
            {
                endTime = startTm.AddMinutes(model.Duration.GetMinutesFromDuration());
            }

            var day = upcomingReservation.ReservationDate.DayOfWeek.ToString();
            var dId = db.GetWeekDays().Single(p => p.DayName.Contains(day)).DayId;

            var availList = db.tabTableAvailabilities
                .Include("TableAvailabilityFloorTables")
                .Include("TableAvailabilityWeekDays")
                .Where(ta => ta.StartDate <= model.resDate && model.resDate <= ta.EndDate
                && ta.TableAvailabilityWeekDays.Any(taw => taw.DayId == dId)).ToList();

            var blockList = db.GetFloorTableBlockTimeList(model.resDate);

            availableTable = availableTable.Where(t => availList.CheckAvailStatus(model.resDate, startTm, endTime, t, 1)
                && !blockList.IsTableBlocked(t.FloorTableId, startTm, endTime)).ToList();

            /**** Table availability feature enabled end here *****/
            #endregion

            var firstAvailableTable = availableTable.FirstOrDefault();

            if (firstAvailableTable != null)
            {
                upcomingReservation.FloorTableId = firstAvailableTable.FloorTableId;
                upcomingReservation.TablePositionLeft = firstAvailableTable.TLeft;
                upcomingReservation.TablePositionTop = firstAvailableTable.TTop;
                db.Entry(upcomingReservation).State = System.Data.Entity.EntityState.Modified;
                db.SaveChanges();
                return true;
            }

            return false;
        }
        private void ExtendReservationDuration(int minToAdd, UsersContext db, Reservation res, out string oldDuration)
        {
            oldDuration = res.Duration;
            var newDuration = oldDuration.AddMinutesToDuration(minToAdd);

            res.Duration = newDuration;
            res.TimeTo = res.TimeForm.AddMinutes(newDuration.GetMinutesFromDuration());
            db.Entry(res).State = System.Data.Entity.EntityState.Modified;
            //db.LogEditReservation(reservation, loginUser, null);

            db.SaveChanges();
        }
        private int CheckAvailStatus(DateTime startTime, Reservation res, List<TableAvailability> availablilies, FloorTable table)
        {
            if (res != null)
            {
                return 4;
            }

            if (availablilies != null && availablilies.Count > 0)
            {
                var avails = availablilies.Where(ta =>
                    (ta.StartDate <= ((startTime.TimeOfDay.TotalMinutes < 240) ? startTime.AddDays(-1).Date : startTime.Date) && ta.EndDate >= ((startTime.TimeOfDay.TotalMinutes < 240) ? startTime.AddDays(-1).Date : startTime.Date))
                    && ta.TableAvailabilityFloorTables.Any(t => t.FloorTableId.Equals(table.FloorTableId)))
                    .ToList();

                avails = avails.Where(ta => CheckAvail(ta, startTime)).OrderByDescending(ta => ta.CreatedOn).ToList();

                //foreach (var avail in avails)
                //{
                //    var TAstartTime = startTime.Date.AddTicks(Convert.ToDateTime(avail.StartTime).TimeOfDay.Ticks);
                //    var TAendTime = startTime.Date.AddTicks(Convert.ToDateTime(avail.EndTime).TimeOfDay.Ticks);

                //    if (!(TAstartTime <= startTime && TAendTime > startTime))
                //    {
                //        avails.Remove(avail);
                //    }
                //}

                //avails = avails.Where(ta =>
                //                (startTime.Date.AddTicks(Convert.ToDateTime(ta.StartTime).TimeOfDay.Ticks) <= startTime && startTime.Date.AddTicks(Convert.ToDateTime(ta.EndTime).TimeOfDay.Ticks) > startTime)
                //                && ta.TableAvailabilityWeekDays.Any(w => w.WeekDays.DayName.Equals(startTime.DayOfWeek.ToString()))).ToList();

                if (avails.Any())
                {
                    var availablity = avails.FirstOrDefault();
                    return availablity.AvailablityStatusId;
                }
                else
                {
                    return 0;
                }
            }

            return 0;
        }