private string PrepareQuery(FindMatchingOrganisations query)
        {
            var returnString = query.CompanyName.Trim().ToUpperInvariant();

            foreach (var specialCase in specialCases)
            {
                specialCase.CleanseSpecialCases(ref returnString);
            }

            return(returnString);
        }
        public async Task <IList <OrganisationData> > HandleAsync(FindMatchingOrganisations query)
        {
            var searchTerm = PrepareQuery(query);

            // This search uses the Levenshtein edit distance as a search algorithm.
            var permittedDistance = CalculateMaximumLevenshteinDistance(searchTerm);

            var possibleOrganisations = await GetPossibleOrganisationNames(searchTerm);

            var uppercaseOrganisationNames =
                possibleOrganisations.Select(o => new KeyValuePair <string, Guid>(o.Name.ToUpperInvariant(), o.Id))
                .ToArray();

            // Special cases should be ignored when counting the distance. This loop replaces special cases with string.Empty.
            for (var i = 0; i < possibleOrganisations.Length; i++)
            {
                foreach (var specialCase in specialCases)
                {
                    specialCase.CleanseSpecialCases(ref uppercaseOrganisationNames[i]);
                }
            }

            var matchingIdsWithDistance = new List <KeyValuePair <Guid, int> >();

            for (var i = 0; i < possibleOrganisations.Length; i++)
            {
                var distance = StringSearch.CalculateLevenshteinDistance(searchTerm, uppercaseOrganisationNames[i].Key);

                if (distance <= permittedDistance)
                {
                    matchingIdsWithDistance.Add(new KeyValuePair <Guid, int>(uppercaseOrganisationNames[i].Value,
                                                                             distance));
                }
            }

            matchingIdsWithDistance = matchingIdsWithDistance.OrderBy(m => m.Value).ToList();

            var matchingOrganisations =
                matchingIdsWithDistance.Select(
                    m => possibleOrganisations.Single(o => o.Id == m.Key));

            return(matchingOrganisations.Select(o =>
                                                new OrganisationData
            {
                Id = o.Id,
                Name = o.Name
            }).ToList());
        }