/// <summary>
        /// Get the hall state which is a collection of occupied seats. 
        /// </summary>
        /// <param name="eventID"></param>
        /// <returns></returns>
        public SeatIndex[] GetHallState(Guid eventID)
        {

            LoggingManager.Logger.Log(LoggingCategory.Info,
                 string.Format(StringsResource.AsyncExecution, "GetHallState", Thread.CurrentThread.ManagedThreadId));
 
           var result = new List<SeatIndex>();
           List<Contracts.Reservation> reservations;
           
            //If the hall state is in the cache read it from the cache.   
           rwl.AcquireReaderLock(new TimeSpan(1, 0, 0));
                reservations = (HallCache.Get(eventID.ToString()) as List<Contracts.Reservation>);
            rwl.ReleaseReaderLock();
           
           // if the info is not in the cache read it from the database and put it in the cache.
           if (reservations == null)
           {
              
               ReservationDal Dal = new ReservationDal();
               reservations = Dal.GetReservationsByCriteria(
                   new ReservationCriteria() { EventID = eventID }).ToList();

               rwl.AcquireWriterLock(new TimeSpan(1,0,0));
            		HallCache[eventID.ToString()] = reservations;
               rwl.ReleaseWriterLock();
           }

           foreach (var rs in reservations)
           {
               foreach (var si in rs.Seats)
               {
                   result.Add(si);
               } 
           }
                  
       
           return result.ToArray();
        }
        public Contracts.Reservation[] FindReservations(ReservationCriteria criteria)
        {
            ReservationDal reservationDal = new ReservationDal();

            return reservationDal.GetReservationsByCriteria(criteria);
        }
        public void UpdateResrvation(Contracts.Reservation newReservation)
        {
            ReservationDal reservationDal = new ReservationDal();
            
            // validate
            Contracts.Reservation OldRersevation = reservationDal.GetEntity(newReservation.ID);
            if (OldRersevation == null)
                throw new HallStateException(string.Format(StringsResource.ReservationNotFound, newReservation.ID));
            
            var oldseats = OldRersevation.Seats;
           
            foreach (var si in newReservation.Seats)
            {
                if ((si.Row < 0) || (si.Seat < 0))
                    throw new ArgumentException(StringsResource.InvalidSeatOrRow);

                //Check that there is no other reservation for the same seats               
                var takenSeats = GetHallState(newReservation.EventID);
                foreach (var item in newReservation.Seats)
                {
                    if (takenSeats.Contains(item) && (!oldseats.Contains(item)))
                        throw new ReservationException(StringsResource.SeatAlreadyTaken);
                }

            }

            rwl.AcquireWriterLock(new TimeSpan(1, 0, 0));

            //Update the database          
            reservationDal.UpdateEntity(newReservation);

            //2. Upfdate the cache
            var cache = HallCache[newReservation.EventID.ToString()] as List<Contracts.Reservation>;
            var reservationToUpdate = cache.Where(res => res.ID == newReservation.ID).FirstOrDefault();
            reservationToUpdate = newReservation;

            rwl.ReleaseWriterLock();
        }
        public void DeleteResrvation(Guid reservationID)
        {
            ReservationDal reservationDal = new ReservationDal();
            var entity = reservationDal.GetEntity(reservationID);
            if (entity != null)
            {

                rwl.AcquireWriterLock(new TimeSpan(1,0,0));
                var reservationsInCache = (HallCache[entity.EventID.ToString()] as List<Contracts.Reservation>);
                if (reservationsInCache != null)
                    reservationsInCache.RemoveAll(rv => (SeatIndex.CreateSeatsString(rv.Seats) == SeatIndex.CreateSeatsString(entity.Seats)) || 
                                                             ((rv.ID == entity.ID)));                

                reservationDal.DeleteEntity(reservationID);
                rwl.ReleaseWriterLock();
            }
        }
        /// <summary>
        /// Submit a new reservation
        /// </summary>
        /// <param name="reservation"></param>
        /// <returns></returns>
        public Guid CreateResrvation(Contracts.Reservation reservation)
        {
            // Create the event in the database
            ReservationDal reservationDal = new ReservationDal();
            TheaterDal theaterDal = new TheaterDal();

            //1. validate
            foreach (var si in reservation.Seats)
            {
                if ((si.Row < 0) || (si.Seat < 0))
                    throw new ArgumentException(StringsResource.InvalidSeatOrRow);

                //Check that there is no other reservation for the same seats               
                var takenSeats = GetHallState(reservation.EventID);
                foreach (var item in reservation.Seats)
            	{
            		 if (takenSeats.Contains(item))
                         throw new ReservationException(StringsResource.SeatAlreadyTaken);
            	}
               
            }

            //2. Create an ID if needed. 
            if (reservation.ID == Guid.Empty)
                reservation.ID = Guid.NewGuid(); 
            
            //3. Create the reservation
            Guid id = reservationDal.CreateEntity(reservation);

            //4. Add it to the cache.
           rwl.AcquireWriterLock(new TimeSpan(1,0,0));

                if (HallCache[reservation.EventID.ToString()] == null)
                    HallCache.Add(reservation.EventID.ToString(), new List<Contracts.Reservation>() { reservation },
                         null,DateTime.Now.AddDays(30),TimeSpan.FromHours(5),CacheItemPriority.Normal,null);
                 else
                    (HallCache[reservation.EventID.ToString()] as List<Contracts.Reservation>).Add(reservation);
           
            rwl.ReleaseWriterLock();

            return id;
        }