public static List <TimeSpan> GetOptionalHoursPerDay(int serviceId, DateTime date)
        {
            List <activityTime> activityTimes = ActivityTimeDal.GetActivityTimesByDay(serviceId, (int)date.DayOfWeek + 1);
            List <TimeSpan>     optionalHours = new List <TimeSpan>();
            int activityTimeIndex             = 0;
            int index = 0;

            activityTimes.OrderBy(a => a.startTime);
            while (activityTimeIndex < activityTimes.Count())
            {
                activityTime           activityTime = activityTimes[activityTimeIndex];
                List <customersInLine> line         = TurnDal.GetLinePerActivityTime(activityTime.activityTimeId);
                double   durationOfService          = activityTime.avgServiceDuration.Value;
                TimeSpan ts = TimeSpan.FromMinutes(durationOfService);
                for (TimeSpan hour = activityTime.startTime; hour < activityTime.endTime; hour = hour.Add(ts))
                {
                    if (TurnBL.IsAvailableHour(ref index, activityTime.numOfWorkers, hour.Add(ts), line))
                    {
                        if (!date.Equals(DateTime.Today) || hour.Add(ts) > DateTime.Now.TimeOfDay)
                        {
                            optionalHours.Add(hour);
                        }
                    }
                    index++;
                }
                activityTimeIndex++;
            }
            return(optionalHours);
        }
        public static string BookAppointment(TurnDetailsDTO appointment)
        {
            try
            {
                ActivityTimeDTO activityTime = ActivityTimeBL.GetActivityTime(appointment.EstimatedHour, appointment.ServiceId);

                customersInLine turn = new customersInLine()
                {
                    activityTimeId = activityTime.ActivityTimeId,
                    custId         = appointment.CustId,
                    estimatedHour  = appointment.EstimatedHour,
                    preAlert       = appointment.PreAlert,
                    statusTurn     = (int)eStatus.ADVANCE,
                    enterHour      = ConfigureHour(appointment.EstimatedHour, activityTime),
                    isActive       = true
                };
                turn.TurnId = TurnDal.AddAppointment(turn);
                string verificationCode = TurnBL.CreateVerificationCode(turn);
                turn.verificationCode = verificationCode;
                TurnDal.UpdateTurn(turn);
                return(verificationCode);
            }
            catch (Exception)
            {
                throw;
            }
        }
//totake:
/// <summary>
/// looks for available turn in activityTime,begin to search from the time she got.
/// </summary>
/// <param name="activityTime"></param>
/// <param name="pushFlag"></param>
/// <param name="timeToLookFor"></param>
/// <returns></returns>
        private static TimeSpan?lookForAvailableTurn(ActivityTimeDTO activityTime, ref bool pushFlag, TimeSpan timeToLookFor)
        {
            List <customersInLine> line = TurnDal.GetLinePerActivityTime(activityTime.ActivityTimeId);

            pushFlag = false;
            double durationOfService = (double)activityTime.AvgServiceDuration;
            //מחשב את ההפרש בין זמן התחלת המשמרת לזמן שקבלנו בפרמטר ע"מ למצוא את הזמן שבו יתחיל לחפש תור
            int totalPassedShifts = (int)((timeToLookFor.TotalMinutes - activityTime.StartTime.TotalMinutes) / durationOfService) + 1;
            //  פרמטר של פנוי שיהיה לפי ממוצע זמן ההמתנה
            const int maxStandbyTime = 3;
            const int maxPushedTimes = 2;
            TimeSpan  hour;
            TimeSpan  ts = TimeSpan.FromMinutes(durationOfService * totalPassedShifts);
            int       index = 0, numOfStandbyTime = 0;

            timeToLookFor = activityTime.StartTime.Add(ts);
            line          = line.Where(t => t.estimatedHour.TimeOfDay >= timeToLookFor).ToList();
            //השעה המבוקשת פנויה
            if (line.Count() == 0 && timeToLookFor < activityTime.EndTime)
            {
                return(timeToLookFor);
            }
            ts = TimeSpan.FromMinutes(durationOfService);
            //לולאה המתחילה מהזמן שקבלה ומחפשת תור פנוי
            for (hour = timeToLookFor; numOfStandbyTime < maxStandbyTime && hour < activityTime.EndTime; hour = hour.Add(ts), numOfStandbyTime++)
            {
                if (TurnBL.IsAvailableHour(ref index, activityTime.NumOfWorkers, hour.Add(ts), line))
                {
                    return(hour);
                }
                index++;
            }
            //אם לא נמצא תור פנוי בתוך זמן ההמתנה המקסימלי שמאופשר:
            //אם כבר המשמרת הנוכחית תפוסה לגמרי
            if (hour >= activityTime.EndTime)
            {
                //מחפש את המשמרת הבאה הקרובה ביותר
                activityTime = ActivityTimeBL.GetNearestActivityTime(hour, activityTime.ServiceId);
                if (activityTime == null)
                {
                    return(null);
                }
                //קורא בצורה רקורסיבית לפונקציה הנוכחית ומתחיל את החיפוש תור פנוי במשמרת החדשה מההתחלה
                return(lookForAvailableTurn(activityTime, ref pushFlag, activityTime.StartTime));
            }
            //אם המשמרת עדיין לא נגמרה אבל הזמן המקסימלי להמתנה עבר ואין תור פנוי אז יש צורך לדחוף את  התור בין התורים
            pushFlag = true;
            while (index < line.Count() && line[index].estimatedHour.TimeOfDay == hour && line[index].numOfPushTimes == maxPushedTimes)
            {
                index++;
                hour = hour.Add(ts);
            }

            return(hour);
        }
        /// <summary>
        /// confirm the turn and add it to the table
        /// </summary>
        /// <param name="turn"></param>
        /// <returns></returns>

        public static confirmResponse ConfirmImmediateTurn(TurnDetailsDTO turn)
        {
            List <customersInLine> line = new List <customersInLine>();


            customersInLine newTurn = TurnDal.GetTurnByTurnId(turn.TurnId);

            line = TurnDal.GetLineByCustomer(newTurn.custId).Where(l => l.statusTurn == (int)eStatus.TEMPORARY || l.statusTurn == (int)eStatus.TEMPORARY_WITH_PUSH).ToList();
            var x = line.Remove(line.First(t => t.TurnId == turn.TurnId));

            if (newTurn.statusTurn == (int)eStatus.TEMPORARY_WITH_PUSH)
            {
                pushTurns(TurnDal.GetLinePerActivityTime(newTurn.activityTime.serviceId), newTurn.estimatedHour.TimeOfDay, ActivityTimeConverters.GetActivityTimeDTO(newTurn.activityTime));
            }
            newTurn.statusTurn = (int)eStatus.IMMEDIATELY;
            string verificationCode = TurnBL.CreateVerificationCode(newTurn);

            newTurn.verificationCode = verificationCode;
            newTurn.preAlert         = turn.PreAlert;
            TurnDal.UpdateTurn(newTurn);
            if (line.Count() > 0)
            {
                line.ForEach(a => TurnDal.DeleteTurn(a.TurnId));
            }
            //טיפול במקרי קצה של תורים באותה שעה
            var allTurnsToCus = BL.CustInLineBL.GetTurnsToCustomer(newTurn.custId);

            allTurnsToCus = allTurnsToCus.Where(t => t.FullTime == newTurn.estimatedHour && t.TurnId != newTurn.TurnId).ToList();

            confirmResponse confirmResponse = new DTO.confirmResponse()
            {
                turnId           = turn.TurnId,
                verificationCode = verificationCode,
                isConflict       = allTurnsToCus.Count != 0 ? true : false
            };


            return(confirmResponse);
        }