using System;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using ThinkGeo.MapSuite.SilverlightCore;
using ThinkGeo.MapSuite.SilverlightEdition;

namespace CSharp_Silverlight_HowDoISamples.Samples
{
    public partial class TravelingSalesman : UserControl
    {
        private SimpleMarkerOverlay markerOverlay;
        private SimpleMarkerOverlay stopLocationsOverlay;
        private InMemoryFeatureLayer routeLayer;
        private ObservableCollection stopLocationsInString;
        private Collection stops;

        public TravelingSalesman()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(TravelingSalesman_Loaded);
        }

        void TravelingSalesman_Loaded(object sender, RoutedEventArgs e)
        {
            Map1.MapUnit = GeographyUnit.DecimalDegree;

            WorldMapKitWmsSilverlightOverlay baseOverlay = new WorldMapKitWmsSilverlightOverlay();
            Map1.Overlays.Add(baseOverlay);

            markerOverlay = new SimpleMarkerOverlay();
            Map1.Overlays.Add("SimpleMarkerOverlay", markerOverlay);
            // Add the start flag
            PointShape pointShape = ConvertStringToPointShape(txtStartPoint.Text);
            Marker marker = new Marker(pointShape);
            marker.ImageSource = new BitmapImage(new Uri("/theme/StartpointMarker.png", UriKind.RelativeOrAbsolute));
            markerOverlay.Markers.Add(marker);

            stopLocationsOverlay = new SimpleMarkerOverlay();
            Map1.Overlays.Add("stopLocationsOverlay", stopLocationsOverlay);
            stopLocationsInString = new ObservableCollection();
            stops = new Collection();
            RenderStopLocations();

            LayerOverlay routeOverlay = new LayerOverlay();
            Map1.Overlays.Add("RouteOverlay", routeOverlay);
            routeLayer = new InMemoryFeatureLayer();
            routeLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = new LineStyle(new GeoPen(GeoColor.FromArgb(100, GeoColor.StandardColors.Purple), 5));
            routeLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle.OuterPen.LineJoin = DrawingLineJoin.Round;
            routeLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle.OuterPen.StartCap = GeoDashCap.Round;
            routeLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle.OuterPen.EndCap = GeoDashCap.Round;
            routeLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
            routeOverlay.Layers.Add("routeLayer", routeLayer);

            Map1.CurrentExtent = new RectangleShape(-97.7319606824951, 30.2922109418945, -97.7002033277588, 30.269551640136);
        }

        private void GetRoute_Click(object sender, RoutedEventArgs e)
        {
            GeoDataService.GeoDataGettingClient client = new GeoDataService.GeoDataGettingClient();
            client.GetRouteViaStopsCompleted += new EventHandler(client_GetRouteViaStopsCompleted);
            client.GetRouteViaStopsAsync(txtStartPoint.Text, stopLocationsInString, int.Parse(txtIterations.Text, CultureInfo.InvariantCulture));
        }

        void client_GetRouteViaStopsCompleted(object sender, CSharp_Silverlight_HowDoISamples.GeoDataService.GetRouteViaStopsCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                string[] results = e.Result.Split('&');
                string wkt = results[0];
                string[] visitSequence = results[1].Split('-');

                LineShape route = LineShape.CreateShapeFromWellKnownData(wkt) as LineShape;
                routeLayer.InternalFeatures.Clear();
                routeLayer.InternalFeatures.Add(new Feature(route));
                Map1.Refresh();

                // Render the informations
                txtDistance.Text = route.GetLength(GeographyUnit.DecimalDegree, DistanceUnit.Kilometer).ToString(CultureInfo.InvariantCulture);
                // Refresh stop markers
                stopLocationsOverlay.Markers.Clear();
                for (int i = 0; i < visitSequence.Length; i++)
                {
                    int sequence = int.Parse(visitSequence[i]);
                    RenderStop(stops[sequence], (i + 1).ToString(CultureInfo.InvariantCulture));
                }
            }
            Map1.Refresh();
        }

        private void RenderStopLocations()
        {
            foreach (ListBoxItem item in lsbVisitList.Items)
            {
                string point = item.Content.ToString();
                stopLocationsInString.Add(point);
                PointShape pointShape = ConvertStringToPointShape(point);
                stops.Add(pointShape);

                RenderStop(pointShape, string.Empty);
            }
        }

        private void RenderStop(PointShape pointShape, string markerText)
        {
            Marker marker = new Marker(pointShape);
            marker.ImageSource = new BitmapImage(new Uri("/theme/StopMarker.png", UriKind.RelativeOrAbsolute));
            marker.TextOffsetX = -5.0;
            marker.TextOffsetY = -23.0;
            marker.ImageOffsetX = -10.0;
            marker.ImageOffsetY = -25.0;
            marker.ImageWidth = 17.0;
            marker.ImageHeight = 25.0;
            if (!String.IsNullOrEmpty(markerText))
            {
                marker.Text = markerText;
            }
            stopLocationsOverlay.Markers.Add(marker);
        }

        private PointShape ConvertStringToPointShape(string point)
        {
            string[] coordinates = point.Split(',');
            double x = double.Parse(coordinates[0], CultureInfo.InvariantCulture);
            double y = double.Parse(coordinates[1], CultureInfo.InvariantCulture);

            return new PointShape(x, y);
        }
    }
}