/// <summary>
        /// Calculates the TSP.
        /// </summary>
        /// <param name="operation">The operation request.</param>
        /// <param name="router">The router.</param>
        /// <param name="matcher">Contains an algorithm to match points to the route network.</param>
        /// <param name="open">Flag indicating the type of TSP problem, open or not.</param>
        /// <returns></returns>
        private RoutingResponse DoTSP(
            RoutingOperation operation, Router<SimpleWeighedEdge> router, IEdgeMatcher matcher, bool open)
        {
            // create the response.
            var response = new RoutingResponse();

            // resolve the points and do the routing.
            var hooksPerRouterPoints = new Dictionary<RouterPoint, List<RoutingHook>>();
            var routerPoints = new List<RouterPoint>();
            var unroutableHooks = new List<RoutingHook>(); // save the unroutable hooks.
            for (int idx = 0; idx < operation.Hooks.Length; idx++)
            {
                // routing hook tags.
                IDictionary<string, string> tags = operation.Hooks[idx].Tags.ConvertToDictionary();

                // resolve the point.
                RouterPoint routerPoint = router.Resolve(operation.Vehicle, new GeoCoordinate(
                    operation.Hooks[idx].Latitude, operation.Hooks[idx].Longitude), matcher, tags);

                // check the result.
                if (routerPoint == null)
                { // this hook is not routable.
                    unroutableHooks.Add(operation.Hooks[idx]);
                }
                else
                { // a point to hook on was found!
                    List<RoutingHook> hooksAtPoint;
                    if (!hooksPerRouterPoints.TryGetValue(routerPoint, out hooksAtPoint))
                    { // the router point does not exist yet.
                        // check if the router point is routable.
                        if (router.CheckConnectivity(operation.Vehicle, routerPoint, 200))
                        {// the point is routable.
                            // create the hooks list at this point.
                            hooksAtPoint = new List<RoutingHook>();
                            hooksPerRouterPoints.Add(routerPoint, hooksAtPoint);

                            // add the new router point to the list.
                            routerPoint.Tags.Add(new KeyValuePair<string, string>("id", routerPoints.Count.ToString(
                                System.Globalization.CultureInfo.InvariantCulture)));
                            routerPoints.Add(routerPoint);

                            // add the hook.
                            hooksAtPoint.Add(operation.Hooks[idx]);
                        }
                        else
                        {// this hook is not routable.
                            unroutableHooks.Add(operation.Hooks[idx]);
                        }
                    }
                    else
                    {
                        // add the hook.
                        hooksAtPoint.Add(operation.Hooks[idx]);
                    }
                }
            }

            // add the unroutable hooks.
            response.UnroutableHooks = unroutableHooks.ToArray();

            // calculate all the weights.
            double[][] weights = router.CalculateManyToManyWeight(operation.Vehicle, routerPoints.ToArray(), routerPoints.ToArray());

            // calculate the TSP.
            var tspSolver = new RouterTSPAEXGenetic(300, 100);
            IRoute tspRoute = tspSolver.CalculateTSP(weights, routerPoints.Select(x => x.Location).ToArray(), 0, !open);

            // calculate the actual route.
            OsmSharpRoute route = null;
            foreach (Edge edge in tspRoute.Edges())
            {
                // calculate the actual edge-route.
                OsmSharpRoute edgeRoute = router.Calculate(operation.Vehicle,
                                                            routerPoints[edge.From], routerPoints[edge.To]);

                // add the routing hook tags.
                List<RoutingHook> fromHooks = hooksPerRouterPoints[routerPoints[edge.From]];
                edgeRoute.Entries[0].Points = new RoutePoint[fromHooks.Count];
                for (int hookIdx = 0; hookIdx < fromHooks.Count; hookIdx++)
                {
                    var hookPoint = new RoutePoint
                                        {
                                            Latitude = fromHooks[hookIdx].Latitude,
                                            Longitude = fromHooks[hookIdx].Longitude,
                                            Tags = fromHooks[hookIdx].Tags.ConvertToList().ConvertFrom()
                                        };

                    edgeRoute.Entries[0].Points[hookIdx] = hookPoint;
                }
                List<RoutingHook> toHooks = hooksPerRouterPoints[routerPoints[edge.To]];
                edgeRoute.Entries[edgeRoute.Entries.Length - 1].Points = new RoutePoint[toHooks.Count];
                for (int hookIdx = 0; hookIdx < toHooks.Count; hookIdx++)
                {
                    var hookPoint = new RoutePoint
                                        {
                                            Latitude = toHooks[hookIdx].Latitude,
                                            Longitude = toHooks[hookIdx].Longitude,
                                            Tags = toHooks[hookIdx].Tags.ConvertToList().ConvertFrom()
                                        };

                    edgeRoute.Entries[edgeRoute.Entries.Length - 1].Points[hookIdx] = hookPoint;
                }

                // concatenate routes.
                if (route == null)
                {
                    route = edgeRoute;
                }
                else
                {
                    route = OsmSharpRoute.Concatenate(route, edgeRoute);
                }
            }

            response.Route = route;

            // set the response as successfull.
            response.Status = OsmSharpServiceResponseStatusEnum.Success;

            return response;
        }
        /// <summary>
        /// Calculates the route from the source to the closest point.
        /// </summary>
        /// <param name="operation">The operation request.</param>
        /// <param name="router">The router.</param>
        /// <param name="matcher">Contains an algorithm to match points to the route network.</param>
        /// <returns></returns>
        private RoutingResponse DoToClosest(
            RoutingOperation operation, Router<SimpleWeighedEdge> router, IEdgeMatcher matcher)
        {
            // create the response.
            var response = new RoutingResponse();

            // resolve the points and do the routing.
            var hooksPerRouterPoints = new Dictionary<RouterPoint, List<RoutingHook>>();
            var routerPoints = new List<RouterPoint>();
            var unroutableHooks = new List<RoutingHook>(); // save the unroutable hooks.
            for (int idx = 0; idx < operation.Hooks.Length; idx++)
            {
                // routing hook tags.
                IDictionary<string, string> tags = operation.Hooks[idx].Tags.ConvertToDictionary();

                // resolve the point.
                RouterPoint routerPoint = router.Resolve(operation.Vehicle, new GeoCoordinate(
                    operation.Hooks[idx].Latitude, operation.Hooks[idx].Longitude), matcher, tags);

                // check the result.
                if (routerPoint == null)
                { // this hook is not routable.
                    if (idx == 0)
                    { // the first point has to be valid!
                        throw new Exception("Cannot resolve source point of a CalculateToClosest() operation.");
                    }
                    unroutableHooks.Add(operation.Hooks[idx]);
                }
                else
                { // a point to hook on was found!
                    List<RoutingHook> hooksAtPoint;
                    if (!hooksPerRouterPoints.TryGetValue(routerPoint, out hooksAtPoint))
                    { // the router point does not exist yet.
                        // check if the router point is routable.
                        if (router.CheckConnectivity(operation.Vehicle, routerPoint, 200))
                        {// the point is routable.
                            // create the hooks list at this point.
                            hooksAtPoint = new List<RoutingHook>();
                            hooksPerRouterPoints.Add(routerPoint, hooksAtPoint);

                            // add the new router point to the list.
                            routerPoint.Tags.Add(new KeyValuePair<string, string>("id", routerPoints.Count.ToString(
                                System.Globalization.CultureInfo.InvariantCulture)));
                            routerPoint.Tags.Add(new KeyValuePair<string, string>("idx", idx.ToString(
                                System.Globalization.CultureInfo.InvariantCulture)));
                            routerPoints.Add(routerPoint);

                            // add the hook.
                            hooksAtPoint.Add(operation.Hooks[idx]);
                        }
                        else
                        {// this hook is not routable.
                            if (idx == 0)
                            { // the first point has to be valid!
                                throw new Exception("Cannot resolve source point of a CalculateToClosest() operation.");
                            }
                            unroutableHooks.Add(operation.Hooks[idx]);
                        }
                    }
                    else
                    {
                        // add the hook.
                        hooksAtPoint.Add(operation.Hooks[idx]);
                    }
                }
            }

            // add the unroutable hooks.
            response.UnroutableHooks = unroutableHooks.ToArray();

            // extract the first point.
            RouterPoint first = routerPoints[0];
            routerPoints.RemoveAt(0);

            // calculate all the weights.
            OsmSharpRoute route = router.CalculateToClosest(operation.Vehicle, first, routerPoints.ToArray());

            if (route != null)
            {
                // add the routerpoint tags.
                string idxClosestString = route.Entries[route.Entries.Length - 1].Points[0].Tags[1].Value;
                int idxClosest = int.Parse(idxClosestString);

                // get the closest point.
                RoutingHook pointClosest = operation.Hooks[idxClosest];

                // get the routerpoint.
                RoutePoint routePoint = route.Entries[route.Entries.Length - 1].Points[0];

                // add the closest point tags.
                routePoint.Latitude = pointClosest.Latitude;
                routePoint.Longitude = pointClosest.Longitude;
                List<KeyValuePair<string, string>> tags = pointClosest.Tags.ConvertToList();
                tags.Add(new KeyValuePair<string, string>("id", pointClosest.Id.ToString())); // add the id-tag.
                routePoint.Tags = tags.ConvertFrom();

                response.Route = route;

                // set the response as successfull.
                response.Status = OsmSharpServiceResponseStatusEnum.Success;
            }

            return response;
        }
        /// <summary>
        /// Calculates a matrix of weights between all given points.
        /// </summary>
        /// <param name="operation">The operation request.</param>
        /// <param name="router">The router.</param>
        /// <param name="matcher">Contains an algorithm to match points to the route network.</param>
        /// <returns></returns>
        private RoutingResponse DoManyToMany(
            RoutingOperation operation, Router<SimpleWeighedEdge> router, IEdgeMatcher matcher)
        {
            // create the response.
            var response = new RoutingResponse();

            // resolve the points and do the routing.
            var routerPoints = new List<RouterPoint>();
            var unroutableHooks = new List<RoutingHook>(); // save the unroutable hooks.
            for (int idx = 0; idx < operation.Hooks.Length; idx++)
            {
                // routing hook tags.
                IDictionary<string, string> tags = operation.Hooks[idx].Tags.ConvertToDictionary();

                // resolve the point.
                RouterPoint routerPoint = router.Resolve(operation.Vehicle, new GeoCoordinate(
                    operation.Hooks[idx].Latitude, operation.Hooks[idx].Longitude), matcher, tags);

                // check the result.
                if (routerPoint == null)
                {
                    // this hook is not routable.
                    unroutableHooks.Add(operation.Hooks[idx]);
                }
                else
                {
                    // a point to hook on was found!
                    // check if the router point is routable.
                    if (router.CheckConnectivity(operation.Vehicle, routerPoint, 200))
                    {
                        // the point is routable.

                        // add the new router point to the list.
                        routerPoint.Tags.Add(new KeyValuePair<string, string>("id", routerPoints.Count.ToString(
                            System.Globalization.CultureInfo.InvariantCulture)));
                        routerPoints.Add(routerPoint);
                    }
                    else
                    {
                        // this hook is not routable.
                        unroutableHooks.Add(operation.Hooks[idx]);
                    }
                }
            }

            // add the unroutable hooks.
            response.UnroutableHooks = unroutableHooks.ToArray();

            // calculate and fill the response.
            response.Weights = router.CalculateManyToManyWeight(operation.Vehicle, routerPoints.ToArray(),
                routerPoints.ToArray());

            // report succes!
            response.Status = OsmSharpServiceResponseStatusEnum.Success;
            response.StatusMessage = string.Empty;

            return response;
        }
        /// <summary>
        /// Calculates a regular route.
        /// </summary>
        /// <param name="operation">The operation request.</param>
        /// <param name="router">The router.</param>
        /// <param name="matcher">Contains an algorithm to match points to the route network.</param>
        /// <returns></returns>
        private RoutingResponse DoRegular(
            RoutingOperation operation, Router<SimpleWeighedEdge> router, IEdgeMatcher matcher)
        {
            // create the response.
            var response = new RoutingResponse();

            OsmSharpRoute route = null;
            RouterPoint previous = null;
            var unroutableHooks = new List<RoutingHook>(); // keep a list of unroutable hooks.
            for (int idx = 0; idx < operation.Hooks.Length - 1; idx++)
            {
                // resolve the next point.
                RouterPoint next = router.Resolve(operation.Vehicle,
                                                  new GeoCoordinate(operation.Hooks[idx].Latitude,
                                                                    operation.Hooks[idx].Longitude), matcher,
                                                  operation.Hooks[idx].Tags.ConvertToDictionary());

                // check the routability.
                if (next != null &&
                    router.CheckConnectivity(operation.Vehicle, next, 200))
                { // the next point is routable.
                    if (previous != null)
                    {
                        // calculate the next part of the route.
                        OsmSharpRoute routePart = router.Calculate(operation.Vehicle,
                                                                 previous, next);
                        // concatenate the route part.
                        if (route == null)
                        {
                            route = routePart;
                        }
                        else
                        {
                            route = OsmSharpRoute.Concatenate(route, routePart);
                        }
                    }

                    // set the next to the previous.
                    previous = next;
                }
                else
                { // add the hook to the unroutable hooks list.
                   unroutableHooks.Add(operation.Hooks[idx]);
                }
            }

            // add the unroutable hooks.
            response.UnroutableHooks = unroutableHooks.ToArray();

            // set the response route.
            response.Route = route;

            // report succes!
            response.Status = OsmSharpServiceResponseStatusEnum.Success;
            response.StatusMessage = string.Empty;

            return response;
        }
        /// <summary>
        /// Processes a routing operation.
        /// </summary>
        /// <param name="operation"></param>
        /// <returns></returns>
        public object ProcessRoutingOperation(RoutingOperation operation)
        {
            // create the response object.
            RoutingResponse response;

            if (!this.IsReady())
            { // return that the service is not ready.
                response = new RoutingResponse
                               {
                                   Status = OsmSharpServiceResponseStatusEnum.Failed,
                                   StatusMessage = "Service is not ready!"
                               };

                return response;
            }

            if (operation.Hooks == null || operation.Hooks.Length == 0)
            { // there are no hooks!
                response = new RoutingResponse
                               {
                                   Status = OsmSharpServiceResponseStatusEnum.Failed,
                                   StatusMessage = "No hooks found!"
                               };

                return response;
            }

            try
            {
                // create the default edge matcher.
                IEdgeMatcher matcher = new LevenshteinEdgeMatcher();

                // create the router.
                var router = new Router<SimpleWeighedEdge>(
                    _data, _interpreter, new DykstraRoutingLive(
                        _data.TagsIndex));

                // execute the requested operation.
                switch (operation.Type)
                {
                    case RoutingOperationType.ManyToMany:
                        response = this.DoManyToMany(operation, router, matcher);
                        break;
                    case RoutingOperationType.Regular:
                        response = this.DoRegular(operation, router, matcher);
                        break;
                    case RoutingOperationType.TSP:
                        response = this.DoTSP(operation, router, matcher, false);
                        break;
                    case RoutingOperationType.OpenTSP:
                        response = this.DoTSP(operation, router, matcher, true);
                        break;
                    case RoutingOperationType.ToClosest:
                        response = this.DoToClosest(operation, router, matcher);
                        break;
                    default:
                        throw new Exception(string.Format("Invalid operation type:{0}",
                            operation.Type));
                }
            }
            catch (Exception ex)
            { // any exception was thrown.
                // create the response.
                response = new RoutingResponse
                               {
                                   Status = OsmSharpServiceResponseStatusEnum.Failed,
                                   StatusMessage = ex.Message
                               };
            }
            return response;
        }