/// <summary>
        /// Delete a location
        /// </summary>
        /// <param name="location">Location</param>
        public void DeleteLocation(Location location)
        {
            if (location == null)
                throw new ArgumentNullException("location");

            if (location.Deleted)
                return;

            _locationRepository.Delete(location);

            ClearCache();
        }
        private SiteMapModel PopulateSiteMap(Location location)
        {
            var model = new SiteMapModel
            {
                Locations = _locationService.GetAllChildLocations(location == null ? 0 : location.Id).OrderBy(x => x.Name).Select(x => x.ToModel()).ToList(),
                Pages = _pageService.GetAllPages(1, -1).Select(x => x.ToModel()).ToList(),
                TitleName = location == null ? "Site Map" : location.Name + " Site Map",
                MetaTitle = location == null ? "Sitemap - #WeWillGather" : "Sitemap for " + location.Name + " | Voluntary projects in " + location.Name,
                MetaDescription = location == null ? "Use the #WeWillGather sitemap to quickly track down the community projects that are taking place in your area." : "",
                NoIndex = location != null
            };

            AddHomeBreadcrumb();
            Location parentLocation = null;
            if (location != null)
            {
                parentLocation = location.ParentLocation;
                AddBreadcrumb(model.TitleName, Url.RouteUrl("SiteMapLocation", new { locationSeoName = location.SeoName }));
            }

            while (parentLocation != null)
            {
                AddBreadcrumb(parentLocation.Name + " Site Map", Url.RouteUrl("SiteMapLocation", new { locationSeoName = parentLocation.SeoName }), 1);
                parentLocation = parentLocation.ParentLocation;
            }

            AddBreadcrumb("Site Map", Url.RouteUrl("SiteMap"), 1);

            var projects = _projectService.GetAllProjectsByLocation(location);

            model.BaseLocation = model.Locations.Count == 0;

            if (!model.BaseLocation)
            {
                foreach (var loc in model.Locations)
                    loc.ProjectCount = projects.Count(p => p.Locations.Any(l => l.LocationId == loc.Id));
            }
            else
            {
                 model.Projects = projects.Select(x => x.ToModel()).ToList();
            }

            return model;
        }
        /// <summary>
        /// Updates the Location
        /// </summary>
        /// <param name="location">Location</param>
        public void UpdateLocation(Location location)
        {
            if (location == null)
                throw new ArgumentNullException("location");

            location.LastModifiedDate = DateTime.Now;

            _locationRepository.Update(location);

            ClearCache();
        }
        /// <summary>
        /// Get a list of child location ids
        /// </summary>
        /// <param name="parent">Parent location</param>
        /// <returns>Collection of child ids</returns>
        public IList<int> GetLocationChildIds(Location parent)
        {
            IList<int> childrenLocations = new List<int>();

            if (parent.ChildLocations.Count == 0)
            {
                childrenLocations.Add(parent.Id);
                return childrenLocations;
            }

            return parent.ChildLocations.Aggregate(childrenLocations, (current, child) => current.Union(GetLocationChildIds(child)).ToList());
        }
        private LocationFilterModel PrepareLocationFilters(IList<BaseProject> projects, Location location = null)
        {
            if (location == null)
            {
                var topLocations = _locationService.GetAllChildLocations();
                LocationFilterModel allRegionFilter;

                if (topLocations.Count > 1)
                {
                    allRegionFilter = new LocationFilterModel { Name = "All Regions", ProjectCount = projects.Count };
                    foreach (var topLocation in topLocations)
                        allRegionFilter.ChildrenLocations.Add(PrepareLocationFilters(projects.Where(p => p.Locations.Any(l => l.LocationId == topLocation.Id)).ToList(), topLocation));
                }
                else
                {
                    allRegionFilter = PrepareLocationFilters(projects, topLocations.First());
                }

                return allRegionFilter;
            }

            var locationFilter = location.ToFilterModel();
            locationFilter.Link = GetPageLink(location.SeoName, location.ParentLocation != null ? location.ParentLocation.SeoName : null).ToString();
            locationFilter.ProjectCount = projects.Count(p => p.Locations.Any(l => l.LocationId == location.Id));

            foreach (var child in location.ChildLocations)
            {
                int projectCount = projects.Count(p => p.Locations.Any(l => l.LocationId == child.Id));
                if (projectCount > 0)
                {
                    var childFilter = child.ToFilterModel();
                    childFilter.Link = GetPageLink(child.SeoName, child.ParentLocation != null ? child.ParentLocation.SeoName : null).ToString();
                    childFilter.ProjectCount = projectCount;
                    locationFilter.ChildrenLocations.Add(childFilter);
                }
            }

            var parentLocation = location.ParentLocation;
            while (parentLocation != null)
            {
                var parentLocationFilter = parentLocation.ToFilterModel();
                parentLocationFilter.ChildrenLocations.Add(locationFilter);
                parentLocationFilter.Link = GetPageLink(parentLocation.SeoName, parentLocation.ParentLocation != null ? parentLocation.ParentLocation.SeoName :  null).ToString();
                parentLocationFilter.ProjectCount = projects.Count(p => p.Locations.Any(l => l.LocationId == parentLocation.Id));

                locationFilter = parentLocationFilter;
                parentLocation = parentLocation.ParentLocation;
            }

            return locationFilter;
        }
        private void PrepareListingResults(int? locationId = null, bool buildLocationFilters = true)
        {
            // Build non-javascript refinement links
            SetPageLink();
            SetPageLink(true);

            var sortTypeEnum = (ProjectSortType) _sortType;
            var sortDirectionEnum = (ProjectSortDirection) _sortDirection;

            // Build the category meta title
            if (_categories != null && _categories.Count > 0)
                _metaTitle = "Volunteer to do a good thing | {0} projects";

            // Start by getting all the projects and locations
            // based on how you're entering the page
            if (!string.IsNullOrEmpty(_query))
            {
                // Work out how far we should zoom in
                switch (_radius)
                {
                    case (int)ProjectSearchRadius.FiveMiles:
                        _mapZoomLevel = 12;
                        break;
                    case (int)ProjectSearchRadius.TenMiles:
                        _mapZoomLevel = 11;
                        break;
                    case (int)ProjectSearchRadius.FifteenMiles:
                        _mapZoomLevel = 10;
                        break;
                    case (int)ProjectSearchRadius.FiftyMiles:
                        _mapZoomLevel = 8;
                        break;
                }

                // If we have a search query, the user must have come from the search form
                // Get the lat/lng of their search query
                _geolocationService.GetLatLng(_query, out _mapLatitude, out _mapLongitude);

                // Get all the projects within a given radius of the search query
                _projects = _projectService.GetAllProjectsByCoords(_mapLatitude, _mapLongitude, _categories, (ProjectSearchRadius)_radius, (ProjectSearchStart)_start, (ProjectChildFriendly)_childFriendly);
                var locationProjects = _projects;

                // If we have an additional location filter, remove projects not in the location
                if ((locationId != null && locationId > 0) || !string.IsNullOrEmpty(_locationSeoName))
                {
                    if (locationId != null && locationId > 0)
                        _location = _locationService.GetLocationById((int)locationId);
                    else
                        _location = _locationService.GetLocationBySeoName(_locationSeoName, _parentSeoName);

                    _projects = _projects.Where(x => x.Locations.Any(l => l.LocationId == _location.Id)).ToList();

                    int parentCount = 0;
                    var parentLocation = _location.ParentLocation;
                    while (parentLocation != null)
                    {
                        parentCount++;
                        parentLocation = parentLocation.ParentLocation;
                    }

                    _mapLatitude = _location.Latitude;
                    _mapLongitude = _location.Longitude;
                    _mapZoomLevel = 7 + (int)Math.Round(parentCount * 1.5);
                }

                // Build location filters
                if (buildLocationFilters && _projects.Count > 0)
                {
                    var topLocation = _projects[0].Locations.ToList().FirstOrDefault(x => _projects.All(y => y.Locations.Any(z => z.LocationId == x.LocationId)));
                    if (topLocation != null)
                    {
                        _locationFilters = PrepareLocationFilters(locationProjects, topLocation.Location);
                    }
                }
            }
            else if ((locationId != null && locationId > 0) || !string.IsNullOrEmpty(_locationSeoName))
            {
                // If we are on a location project listing page
                // Get the location entity based on the location seo name in the URL
                if (locationId != null && locationId > 0)
                    _location = _locationService.GetLocationById((int)locationId);
                else
                    _location = _locationService.GetLocationBySeoName(_locationSeoName, _parentSeoName);

                // If we couldn't find a location matching the seo name, redirect to the main project listing page
                if (_location == null)
                {
                    var httpContextWrapper = new HttpContextWrapper(System.Web.HttpContext.Current);
                    var urlHelper = new UrlHelper(new RequestContext(httpContextWrapper, new RouteData()));
                    System.Web.HttpContext.Current.Response.Redirect(urlHelper.RouteUrl("ProjectListing"), true);
                    return;
                }

                // Build the breadcrumbs based on the location
                var parentLocation = _location.ParentLocation;
                int parentCount = 0;

                // Build the breadcrumb hierarchy
                while (parentLocation != null)
                {
                    parentCount++;
                    AddBreadcrumb(parentLocation.Name, Url.RouteUrl("ProjectListingLocation", new { locationSeoName = parentLocation.SeoName }), 0);
                    parentLocation = parentLocation.ParentLocation;
                }

                AddBreadcrumb(_location.Name, Url.RouteUrl("ProjectListingLocation", new { locationSeoName = _location.SeoName }));

                // Change the map lat/lng and zoom based on the current location and number of parents
                _mapLatitude = _location.Latitude;
                _mapLongitude = _location.Longitude;
                _mapZoomLevel = 7 + (int)Math.Round(parentCount * 1.5);

                // Check if we need to build the location filters
                if (buildLocationFilters)
                {
                    // Get all the projects, regardless of location
                    _projects = _projectService.GetAllProjectsByLocation(null, _categories, sortTypeEnum, sortDirectionEnum);

                    // Build all the location filters, passing across the project list so we can populate location counts
                    _locationFilters = PrepareLocationFilters(_projects, _location);
                }
                else
                {
                    // Get all the projects, regardless of location
                    _projects = _projectService.GetAllProjectsByLocation(_location, _categories, sortTypeEnum, sortDirectionEnum);
                }

                // Filter the projects down to the location we need for presentation
                _projects = _projects.Where(p => p.Locations.Any(l => l.LocationId == _location.Id)).ToList();

                // Build the meta title
                string projectCountTitle = _projects.Count > 0 ? " - " + _projects.Count + " Projects" : "";
                _metaTitle = string.Format("{0} Opportunities in {1}{2} - #WeWillGather", _categories != null && _categories.Count > 0 ? "{0} " : "Volunteering ", _location.Name, projectCountTitle);
            }
            else
            {
                // We must be on the main projecting listing page
                // Get all projects, regardless of location
                _projects = _projectService.GetAllProjectsByLocation(null, _categories, sortTypeEnum, sortDirectionEnum);

                // Check if we need to build the location filters
                if (buildLocationFilters)
                    _locationFilters = PrepareLocationFilters(_projects);
            }
        }
        public static Location ToEntity(this LocationModel model)
        {
            if (model == null)
                return null;

            var entity = new Location
            {
                Active = model.Active,
                CreatedDate = model.CreatedDate,
                Deleted = model.Deleted,
                LastModifiedBy = model.LastModifiedBy,
                LastModifiedDate = model.LastModifiedDate,
                HashTag = model.HashTag,
                Id = model.Id,
                ParentLocation = model.ParentLocation.ToEntity(),
                Name = model.Name
            };

            return entity;
        }
        /// <summary>
        /// Get all projects assigned to a location
        /// </summary>
        /// <param name="location">Location</param>
        /// <param name="categories">Selected categories</param>
        /// <param name="sortType">Sort by type</param>
        /// <param name="sortDirection">Sort by direction</param>
        /// <returns>Base project query</returns>
        private IEnumerable<BaseProject> GetAllProjectsByLocationQuery(Location location = null,
            IList<int> categories = null,
            ProjectSortType sortType = ProjectSortType.StartDate,
            ProjectSortDirection sortDirection = ProjectSortDirection.Ascending)
        {
            var query = GetAllCachedProjects();

            if (location != null)
                query = query.Where(p => p.Locations.Any(l => l.LocationId == location.Id));

            if (categories != null && categories.Count > 0)
                query = query.Where(p => categories.All(x => p.Categories.Any(c => c.Id == x)));

            switch (sortDirection)
            {
                case ProjectSortDirection.Descending:

                    switch (sortType)
                    {
                        case ProjectSortType.CreatedDate:
                            query = query.OrderByDescending(x => x.CreatedDate);
                            break;
                        case ProjectSortType.Volunteers:
                            query = query.OrderByDescending(x => x.Volunteers.Count);
                            break;
                        default:
                            query = query.OrderByDescending(x => x.StartDate);
                            break;
                    }

                    break;
                default:

                    switch (sortType)
                    {
                        case ProjectSortType.CreatedDate:
                            query = query.OrderBy(x => x.CreatedDate);
                            break;
                        case ProjectSortType.Volunteers:
                            query = query.OrderBy(x => x.Volunteers.Count);
                            break;
                        default:
                            query = query.OrderBy(x => x.StartDate);
                            break;
                    }

                    break;
            }

            return query;
        }
        /// <summary>
        /// Get all projects assigned to a location
        /// </summary>
        /// <param name="location">Location</param>
        /// <param name="pageIndex">page index</param>
        /// <param name="pageSize">page size</param>
        /// <param name="categories">Selected categories</param>
        /// <param name="sortType">Sort by type</param>
        /// <param name="sortDirection">Sort by direction</param>
        /// <returns>Base project collection</returns>
        public IPaginatedList<Project> GetAllProjectsByLocationPaged(Location location = null,
            int pageIndex = 0, int pageSize = -1,
            IList<int> categories = null,
            ProjectSortType sortType = ProjectSortType.StartDate,
            ProjectSortDirection sortDirection = ProjectSortDirection.Ascending)
        {
            // Get the base projects
            var baseProjects = GetAllProjectsByLocationQuery(location, categories, sortType, sortDirection);

            var query = from p in _projectRepository.Table
                        join b in baseProjects on p.Id equals b.Id
                        orderby 1 ascending // needs order to paginate
                        select p;

            var projects = new PaginatedList<Project>(query, pageIndex, pageSize);
            return projects;
        }
 /// <summary>
 /// Get all projects assigned to a location
 /// </summary>
 /// <param name="location">Location</param>
 /// <param name="categories">Selected categories</param>
 /// <param name="sortType">Sort by type</param>
 /// <param name="sortDirection">Sort by direction</param>
 /// <returns>Base project collection</returns>
 public IList<BaseProject> GetAllProjectsByLocation(Location location = null,
     IList<int> categories = null,
     ProjectSortType sortType = ProjectSortType.StartDate,
     ProjectSortDirection sortDirection = ProjectSortDirection.Ascending)
 {
     return GetAllProjectsByLocationQuery(location, categories, sortType, sortDirection).ToList();
 }
        private LocationModel PrepareListLocationModel(Location location)
        {
            var model = location.ToModel();

            model.Actions.Add(new ModelActionLink
            {
                Alt = "Edit",
                Icon = Url.Content("~/Areas/Admin/Content/images/icon-edit.png"),
                Target = Url.Action("edit", new { id = location.Id })
            });

            if (location.ChildLocations.Count > 0)
            {
                model.Actions.Add(new ModelActionLink
                {
                    Alt = "Delete",
                    Icon = Url.Content("~/Areas/Admin/Content/images/sitemap-application-blue.png"),
                    Target = Url.Action("list", new { id = location.Id })
                });
            }

            return model;
        }