/// <summary>
        /// Create Times Ranges for Bookings Logic
        /// </summary>
        /// <param name="filter"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        public static  List<Booking> BuildTimes(FilterOptionModel filter, int limit = 4)
        {
            // TODO take user Hour
            
            var firstHour = (filter.date.HasValue ? RoundUp( filter.date.Value,TimeSpan.FromMinutes(60)) :  RoundUp( DateTime.Now,TimeSpan.FromMinutes(60)));
            DateTime time;
            if (DateTime.TryParse(filter.time, out time))
            {
                firstHour = new DateTime(firstHour.Year,firstHour.Month,firstHour.Day,time.Hour,time.Minute,time.Second);
                firstHour = RoundUp(firstHour, TimeSpan.FromMinutes(60));
            };

            var ranges = new List<Booking>();

            for (int index=0;index<limit;index++)
            {
                ranges.Add(new Booking()
                {
                    Start = firstHour,
                    End = firstHour= firstHour.AddHours(1),
                });
                
            }

            return ranges;
        }
        private IQueryable<ApplicationUser> CommonSearch(FilterOptionModel filter, bool onlyUsers = false)
        {
            IQueryable<ApplicationUser> users = Context.Users.Include(i => i.Roles).Include(u => u.Claims);

            //if (TokenExtensions.IsInRole("Manager"))
            //{
            //    var id = ClaimsPrincipal.Current.UserId();
            //   // if(!filter.centerid.HasValue)  filter.centerid = Context.Users.Where(u => u.Id == id).Select(u=> u.CenterId).FirstOrDefault();
            //}

            if (!string.IsNullOrEmpty(filter.role))
            {

                var roleId = Context.Roles.FirstOrDefault(r => r.Name == filter.role).Id;
                users = (from user in Context.Users
                         join roles in Context.UserRoles.Where(r => r.RoleId == roleId) on user.Id equals roles.UserId
                         select user);
            }
            //To Exclude any types of admin
            // los usuarios que no tienen rol asignado es para el cliente final que hace reservas.
            if (string.IsNullOrEmpty(filter.role) && onlyUsers)
            {
                users = (from user in users
                         join userRole in Context.UserRoles on user.Id equals userRole.UserId
                         into gu
                         from defaultUserRole in gu.DefaultIfEmpty()
                         where defaultUserRole == null
                         select user);
            }

            if (TokenExtensions.IsInRole("Manager"))
            {

                users = onlyUsers? (from user in users
                         join userRole in Context.UserRoles on user.Id equals userRole.UserId
                         into gu
                         from defaultUserRole in gu.DefaultIfEmpty()
                         join access in Context.AccountAccess on user.Id equals access.UserId
                         where defaultUserRole==null// single users has no any role
                         select user):
                         (from user in users   
                          join access in Context.AccountAccess on user.Id equals access.UserId   
                          select user) ;
              

            }
            filter.SearchKeys.ForEach(key =>
                         users = users.Where(u => u.UserName.ToLower().Contains(key)
                                             || u.ADDRESS.ToLower().Contains(key)
                                             || u.FirstName.ToLower().Contains(key)
                                             || u.LastName.ToLower().Contains(key)
                                             || u.DUI.ToLower().Contains(key)
                                             || u.Email.ToLower().Contains(key)));

            return users;
        }
 /// <summary>
 /// Pagination For Grids
 /// </summary>
 /// <param name="filter"></param>
 /// <param name="context"></param>
 /// <returns></returns>
 public  async Task<int> GetPageLimit(FilterOptionModel filter)
 {
     return (await CommonSearch(filter).CountAsync()) / filter.Limit + 1;
 }
        public async Task<List<ApplicationUser>> GetUsersAsync(FilterOptionModel filter, bool onlyUsers = false)
        {

            IQueryable<ApplicationUser> users = CommonSearch(filter, onlyUsers);


            var accounts = await users.Include(u => u.Claims).OrderBy(u => u.UserName).Skip(filter.Skip).Take(filter.Limit).ToListAsync();

            //refresh profile pictures from extenal login

            foreach (var account in accounts.Where(a => a.Claims.Any()))
            {
                var claim = account.Claims.FirstOrDefault(c => c.ClaimType == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier");

                if (claim != null)
                {
                    account.ProfilePicture = TokenExtensions.FaceBookProfilePictureFormat(claim.ClaimValue);
                }

                var claimName = account.Claims.FirstOrDefault(c => c.ClaimType == ClaimTypes.Name);
                var givenName = account.Claims.FirstOrDefault(c => c.ClaimType == ClaimTypes.GivenName);
                var phone = account.Claims.FirstOrDefault(c => c.ClaimType == ClaimTypes.MobilePhone);
                if (claimName != null && string.IsNullOrEmpty(account.FirstName)) account.FirstName = claimName.ClaimValue;
                if (givenName != null && string.IsNullOrEmpty(account.LastName)) account.LastName = givenName.ClaimValue;
                if (phone != null && string.IsNullOrEmpty(account.PhoneNumber)) account.PhoneNumber = phone.ClaimValue;

                await Context.SaveChangesAsync();
            }

            return accounts;
        }
 public IQueryable<IdentityUserViewModel> SearchUsers(FilterOptionModel filter, bool onlyUsers=false)
 {
     return CommonSearch(filter, onlyUsers)
         .Select(u => new Identity.IdentityUserViewModel()
         {
             Id = u.Id,
             Email= u.Email,
             PHONE_2 = u.PHONE_2,
             AccessFailedCount = u.AccessFailedCount,
             FirstName = u.FirstName,
             LastName =u.LastName,
             DUI = u.DUI,
             ADDRESS = u.ADDRESS,
             UserName = u.UserName,
             ProfilePicture= u.ProfilePicture,
             CenterId = u.CenterId,  
             Claims = u.Claims.ToList(),
         }).OrderBy(o=>o.FirstName).ThenBy(o=>o.LastName);
 }
 /// <summary>
 ///  Common Filter 
 /// </summary>
 /// <param name="searchKeys"></param>
 /// <returns></returns>
 public async Task<List<Guid>> FilterUsers(FilterOptionModel filter)
 {
     var ids = await CommonSearch(filter).Select(u => u.Id).ToListAsync();
     return ids.Select(i => new Guid(i)).ToList();
 }
        //[Authorize(Roles = "Admin,Manager")]
        public ActionResult SearchAccounts(FilterOptionModel filter)
        {           
            var users = IdentityManagerService.SearchUsers(filter);

            ViewBag.FilterModel = filter.Serialize();

            return PartialView("Partials/UsersManageGrid", users.ToPagedList(filter.page == 0 ? 1 : filter.page, filter.Limit));
        }
        //[AllowAnonymous]
        public ActionResult AccountMangement()
        {
            
            var filter = new FilterOptionModel() { Limit= 8};
            var users =   IdentityManagerService.SearchUsers(filter);
            
            ViewBag.FilterModel = filter.Serialize();

            return View(users.ToPagedList(filter.page == 0 ? 1 : filter.page, filter.Limit));
        }
        private IQueryable<ApplicationUser> CommonSearch(FilterOptionModel filter, AccessContext Context, bool onlyUsers = false)
        {
            IQueryable<ApplicationUser> users = identityContex.Users.Include(i => i.Roles).Include(u => u.Claims);


            identityContex.Users.Add(new ApplicationUser()
            {
                Id=Guid.NewGuid().ToString(),
                UserName="******",
                Email ="TestEmail"
            });

            if (!string.IsNullOrEmpty(filter.role))
            {

                var roleId = identityContex.Roles.FirstOrDefault(r => r.Name == filter.role).Id;
                users = (from user in identityContex.Users
                         join roles in identityContex.UserRoles.Where(r => r.RoleId == roleId) on user.Id equals roles.UserId
                         select user);
            }
            //To Exclude any types of admin
            // los usuarios que no tienen rol asignado es para el cliente final que hace reservas.
            if (string.IsNullOrEmpty(filter.role) && onlyUsers)
            {
                users = (from user in users
                         join userRole in identityContex.UserRoles on user.Id equals userRole.UserId
                         into gu
                         from defaultUserRole in gu.DefaultIfEmpty()
                         where defaultUserRole == null
                         select user);
            }

            if (filter.centerid.HasValue && filter.centerid != 0)
            {
                var idsToFilter =
                  // TODO verificar si el rendimiento es impactado al hacer QUerys separadaas.
                  (Context.AccountAccess.Where(al => al.CenterId == filter.centerid)
                                 .Select(c => c.UserId.ToString()).ToList());
                if (onlyUsers)
                {
                    if (idsToFilter.Any()) users = users.Where(u => idsToFilter.Contains(u.Id));
                }

                else
                {
                    users = users.Where(u =>
                         idsToFilter.Contains(u.Id) ||
                         (u.CenterId.HasValue && u.CenterId == filter.centerid.Value));
                }

            }
            filter.SearchKeys.ForEach(key =>
                         users = users.Where(u => u.UserName.ToLower().Contains(key)
                                             || u.ADDRESS.ToLower().Contains(key)
                                             || u.FirstName.ToLower().Contains(key)
                                             || u.LastName.ToLower().Contains(key)
                                             || u.DUI.ToLower().Contains(key)
                                             || u.Email.ToLower().Contains(key)));

            return users;
        }
 /// <summary>
 /// Pagination For Grids
 /// </summary>
 /// <param name="filter"></param>
 /// <param name="context"></param>
 /// <returns></returns>
 public  async Task<int> GetPageLimit(FilterOptionModel filter, AccessContext context)
 {
     return (await CommonSearch(filter, context).CountAsync()) / filter.Limit + 1;
 }