private void CreateLocalityFiles(IEnumerable<string> localities,
            List<KeyValuePair<string, PageLinkModel>> orgLocalityLinks, Authority authority
            )
        {
            if (localities == null) throw new ArgumentNullException("localities");
            if (orgLocalityLinks == null) throw new ArgumentNullException("orgLocalityLinks");
            if (authority == null) throw new ArgumentNullException("authority");

            // create the locality pages
            foreach (var locality in localities)
            {
                CreateLocalityFile(orgLocalityLinks, locality, authority);
            }
        }
        private List<Authority> CreateRegionHeaderFile(Authority region,
            Int32 orgsInRegionCount)
        {
            // region file needs knowledge of its counties
            // should be list of counties that have ghost pubs?
            // var countiesInRegion = currentRegion.Counties.ToList();

            var inRegion = _queryManager.GetHauntedFirstDescendantAuthoritiesInRegion(region.Id).ToList();

            var regionModel = _queryManager.PrepareRegionModel(region, orgsInRegionCount,
                inRegion);

            WriteFile(regionModel);

            return inRegion;
        }
        private void CreateAuthorityFilesTop(Authority authority)
        {
            if (authority == null) return;

            if (authority.Authoritys != null && authority.Authoritys.Any())
            {
                if (authority.Authoritys == null) return;

                foreach (var district in authority.Authoritys)
                {
                    CreateAuthorityFiles(district);
                }
            }

            CreateAuthorityFiles(authority);
        }
        private void CreateLocalityFile(
            IEnumerable<KeyValuePair<string, PageLinkModel>> orgLocalityLinks,
            string locality,
            Authority authority)
        {
            if (orgLocalityLinks == null) throw new ArgumentNullException("orgLocalityLinks");
            if (locality == null) throw new ArgumentNullException("locality");
            if (authority == null) throw new ArgumentNullException("authority");

            var model = _queryManager.PrepareLocalityModel(orgLocalityLinks, locality,
                authority
                );

            WriteFile(model);
        }
        private void CreateAuthorityFile(Authority authority,
            IEnumerable<string> locations,
            Int32 count)
        {
            if (authority == null) throw new ArgumentNullException("authority");
            if (locations == null) throw new ArgumentNullException("locations");

            var links = locations.Select(locality => new PageLinkModel
            {
                Text = locality,
                Title = locality,
                Filename = authority.IsCounty
                    ? locality.Clean()
                    : locality.In(authority.CleanQualifiedName, true),
                Total = authority.IsCounty
                    ? authority.Authoritys
                        .First(a => a.QualifiedName == locality).HauntedOrgs
                        .Count()
                    : authority.HauntedOrgs
                        .Count(x => x.Locality == locality)
            }).ToList();

            var model = _queryManager.PrepareAuthorityModel(authority,
                links, count);

            WriteFile(model);
        }
        private void CreateAuthorityFiles(Authority authority)
        {
            if (authority == null) throw new ArgumentNullException("authority");

            if (!authority.IsCounty)
            {
                var orgs =
                    authority.HauntedOrgs.Where(org =>
                        org.Authority.Name == authority.Name)
                        .OrderByDescending(org => org.Locality)
                        .ThenByDescending(org => org.TradingName);

                var localities = orgs
                    .Select(p => p.Locality)
                    .Distinct()
                    .OrderBy(o => o)
                    .ToList();

                CreateAuthorityFile(authority, localities,
                    orgs.Count()
                    );

                var links = CreateOrgFiles(orgs);

                CreateLocalityFiles(localities, links, authority);
            }
            else
            {
                var districts = authority.Authoritys
                    .Select(a => a.QualifiedName)
                    .Distinct()
                    .ToList();

                CreateAuthorityFile(authority, districts,
                    authority.HauntedPubCount
                    );
            }
        }
        public OutputViewModel PrepareRegionModel(Authority region,
            int orgsInRegionCount,
            IEnumerable<Authority> hauntedAuthoritiesInRegion)
        {
            if (region == null) throw new ArgumentNullException("region");
            if (hauntedAuthoritiesInRegion == null) throw new ArgumentNullException("hauntedAuthoritiesInRegion");

            var authorityLinks = hauntedAuthoritiesInRegion.Select(authority => new PageLinkModel
            {
                Text = authority.Name,
                Title = authority.Name,
                Filename = authority.CleanQualifiedName,
                Total = authority.HauntedPubCount
            }).ToList();

            var next = region.ExtractNextLink();

            var model = OutputViewModel.CreateRegionOutputViewModel(
                region,
                orgsInRegionCount,
                authorityLinks,
                next,
                "Haunted pubs in {0}"
                );

            return model;
        }
        private void CreateAllFilesForRegion(Authority region, RegionFilterModel filterModel)
        {
            int orgsInRegionCount;

            if (region.IsOutsideUnitedKingdom)
            {
                orgsInRegionCount = region.HauntedPubCount;
            }
            else
            {
                var firstDescendantAuthoritiesInRegion =
                    _queryManager.GetHauntedFirstDescendantAuthoritiesInRegion(region.Id);

                orgsInRegionCount = firstDescendantAuthoritiesInRegion.Sum(x => x.HauntedPubCount);
            }

            if (orgsInRegionCount == 0) return;

            var inRegion = CreateRegionHeaderFile(region, orgsInRegionCount);

            if (!inRegion.Any())
            {
                CreateAuthorityFilesTop(region);
            }
            else
            {
                // todo - work out why filterModel == null?
                var filtered = inRegion.Where(authority => filterModel == null || filterModel.Division.IsNullOrEmpty() ||
                                                    authority.Name == filterModel.Division);

                foreach (var authority in filtered)
                {
                    CreateAuthorityFilesTop(authority);
                }
            }
        }
        public OutputViewModel PrepareLocalityModel(
            IEnumerable<KeyValuePair<string, PageLinkModel>> orgLocalityLinks, string locality,
            Authority authority)
        {
            if (orgLocalityLinks == null) throw new ArgumentNullException("orgLocalityLinks");
            if (locality == null) throw new ArgumentNullException("locality");
            if (authority == null) throw new ArgumentNullException("authority");

            var collection = new PageLinkKeyedCollection(orgLocalityLinks, locality);

            if (collection.NextSibling.Key == null) return null;

            var next = new PageLinkModel
            {
                Text = collection.NextSibling.Key,
                Title = collection.NextSibling.Key,
                Filename = collection.NextSibling.Key.In(authority.CleanQualifiedName, true),
            };

            var model = OutputViewModel.CreateLocalityOutputViewModel(locality, authority,
                collection.Links, next, "{0}, {1}, {2}");

            return model;
        }
        public OutputViewModel PrepareAuthorityModel(Authority authority, List<PageLinkModel> localities, int count)
        {
            if (authority == null) throw new ArgumentNullException("authority");
            if (localities == null) throw new ArgumentNullException("localities");

            var next = authority.ExtractNextLink();

            // dpc - cheshire-west-and-chester-ua.html should contain links to localities, such as: duddon-in-cheshire-west-and-chester-ua.html
            var model = OutputViewModel.CreateAuthorityOutputViewModel(
                authority,
                count,
                localities,
                next,
                "Haunted pubs in {0}"
                );

            return model;
        }
        public static OutputViewModel CreateRegionOutputViewModel(Authority region,
            int count,
            IList<PageLinkModel> authorityLinks,
            PageLinkModel next,
            String descriptionPattern)
        {
            if (region == null) throw new ArgumentNullException("region");
            if (authorityLinks == null) throw new ArgumentNullException("authorityLinks");
            if (next == null) throw new ArgumentNullException("next");

            var lineage = new Breadcrumb
            {
                Region = new PageLinkModel
                {
                    Filename = region.CleanQualifiedName,
                    Id = region.Id,
                    Text = region.Name,
                    Title = region.Name,
                    Total = region.HauntedPubCount
                },
            };

            var pageLinks = authorityLinks.Select(link => link.Text != null
                ? new PageLinkModel
                {
                    Text = link.Text,
                    Title = link.Text,
                    Filename = link.Filename,
                    Total = link.Total
                }
                : null)
                .OrderBy(o => o.Text)
                .ToList();

            var articleDescription = string.Format(descriptionPattern, authorityLinks
                .Select(x => x.Text)
                .OxfordAnd());

            var metaDescription = articleDescription
                .SeoMetaDescriptionTruncate();

            var model = new OutputViewModel
            {
                Filename = region.CleanQualifiedName,
                PageTitle = region.Name,
                JumboTitle = region.Name,
                Action = PageTypeEnum.Region,
                Total = count,
                Priority = PageTypePriority.Region,
                Next = next,
                Lineage = lineage,
                PageLinks = pageLinks,
                MetaDescription = metaDescription,
                ArticleDescription = articleDescription,
                Summary = region.Summary,
                LocalGhostSpecialist = region.IsLocalGhostSpecialistValid
                    ? new PageLinkModel
                    {
                        Text = region.LocalGhostSpecialistName,
                        Title = region.LocalGhostSpecialistName,
                        ExternalUrl = region.LocalGhostSpecialistUrl
                    }
                    : null,
                LocalGhostHunter = region.IsLocalGhostHuntSpecialistValid
                    ? new PageLinkModel
                    {
                        Text = region.LocalGhostHuntSpecialistName,
                        Title = region.LocalGhostHuntSpecialistName,
                        ExternalUrl = region.LocalGhostHuntSpecialistUrl
                    }
                    : null
            };

            return model;
        }
        public static OutputViewModel CreateLocalityOutputViewModel(string locality,
            Authority authority,
            IList<PageLinkModel> orgLinks,
            PageLinkModel next,
            String descriptionPattern)
        {
            if (locality == null) throw new ArgumentNullException("locality");
            if (authority == null) throw new ArgumentNullException("authority");
            if (orgLinks == null) throw new ArgumentNullException("orgLinks");
            if (next == null) throw new ArgumentNullException("next");

            var lineage = new Breadcrumb
            {
                Region = new PageLinkModel
                {
                    Filename = authority.ParentAuthority.CleanQualifiedName,
                    Id = authority.ParentAuthority.Id,
                    Text = authority.ParentAuthority.Name,
                    Title = authority.ParentAuthority.Name,
                    Total = authority.ParentAuthority.HauntedPubCount
                },
                Authority = new PageLinkModel
                {
                    Filename = authority.CleanQualifiedName,
                    Id = authority.Id,
                    Text = authority.Name,
                    Title = authority.Name,
                    Total = authority.HauntedPubCount
                },
                Locality = new PageLinkModel
                {
                    Filename = locality.In(authority.CleanQualifiedName, true),
                    Id = authority.Id,
                    Text = locality,
                    Title = locality
                }
            };

            var adjusted = new Breadcrumb();

            if (authority.IsOutsideUnitedKingdom)
            {
                lineage = adjusted.Swap(lineage);
            }

            var articleDescription = string.Format(descriptionPattern, locality, authority.Name,
                authority.ParentAuthority.Name);

            var metaDescription = articleDescription
                .SeoMetaDescriptionTruncate();

            var pageLinks = orgLinks.Select(link => link.Text != null
                ? new PageLinkModel
                {
                    Text = link.Text,
                    Title = link.Title,
                    // dpc - example: 10930-the-headless-woman-duddon.html
                    Filename = link.Filename
                }
                : null)
                .OrderBy(o => o.Text)
                .ToList();

            var model = new OutputViewModel
            {
                // dpc - example: duddon-in-cheshire-west-and-chester-ua.html
                Filename = locality.In(authority.CleanQualifiedName, true),
                JumboTitle = locality.In(authority.QualifiedName),
                PageTitle = locality.In(authority.QualifiedName),
                Action = PageTypeEnum.Locality,
                Total = orgLinks.Count(),
                Priority = PageTypePriority.Locality,
                Next = next,
                Lineage = lineage,
                MetaDescription = metaDescription,
                ArticleDescription = articleDescription,
                PageLinks = pageLinks
            };

            return model;
        }
        public static OutputViewModel CreateAuthorityOutputViewModel(Authority authority, int count,
            IList<PageLinkModel> locations,
            PageLinkModel next,
            string descriptionPattern
            )
        {
            if (authority == null) throw new ArgumentNullException("authority");
            if (locations == null) throw new ArgumentNullException("locations");
            if (next == null) throw new ArgumentNullException("next");

            var lineage = new Breadcrumb
            {
                Region = new PageLinkModel
                {
                    Filename = authority.ParentAuthority.CleanQualifiedName,
                    Id = authority.ParentAuthority.Id,
                    Text = authority.ParentAuthority.Name,
                    Title = authority.ParentAuthority.Name,
                    Total = authority.ParentAuthority.HauntedPubCount,
                },
                Authority = new PageLinkModel
                {
                    Filename = authority.CleanQualifiedName,
                    Id = authority.Id,
                    Text = authority.Name,
                    Title = authority.Name,
                    Total = authority.HauntedPubCount,
                }
            };

            var adjusted = new Breadcrumb();

            if (authority.IsOutsideUnitedKingdom)
            {
                lineage = adjusted.Swap(lineage);
            }

            var pageLinks = locations.OrderBy(x => x.Text).ToList();

            var articleDescription = string.Format(
                descriptionPattern,
                locations.Select(x => x.Text).OxfordAnd());

            var metaDescription = articleDescription
                .SeoMetaDescriptionTruncate();

            var model = new OutputViewModel
            {
                // this is for example: cheshire-west-and-chester-ua.html
                Filename = authority.CleanQualifiedName,
                JumboTitle = authority.Name,
                PageTitle = authority.Name,
                Action = PageTypeEnum.Authority,
                Total = count,
                Priority = PageTypePriority.Authority,
                Next = next,
                Lineage = lineage,
                MetaDescription = metaDescription,
                ArticleDescription = articleDescription,
                PageLinks = pageLinks,
                Summary = authority.Summary,
                LocalGhostSpecialist = authority.IsLocalGhostSpecialistValid
                    ? new PageLinkModel
                    {
                        Text = authority.LocalGhostSpecialistName,
                        Title = authority.LocalGhostSpecialistName,
                        ExternalUrl = authority.LocalGhostSpecialistUrl
                    }
                    : null,
                LocalGhostHunter = authority.IsLocalGhostHuntSpecialistValid
                    ? new PageLinkModel
                    {
                        Text = authority.LocalGhostHuntSpecialistName,
                        Title = authority.LocalGhostHuntSpecialistName,
                        ExternalUrl = authority.LocalGhostHuntSpecialistUrl
                    }
                    : null
            };

            return model;
        }