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 RoutingAroundRoadblocks : UserControl
    {
        private SimpleMarkerOverlay markerOverlay;
        private SimpleMarkerOverlay roadblockOverlay;
        private InMemoryFeatureLayer routeLayer;
        private bool IsAddingRoadblocks;
        private ObservableCollection avoidablePoints;

        public RoutingAroundRoadblocks()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(RoutingAroundRoadblocks_Loaded);
        }

        void RoutingAroundRoadblocks_Loaded(object sender, RoutedEventArgs e)
        {
            Map1.MapUnit = GeographyUnit.DecimalDegree;
            avoidablePoints = new ObservableCollection();

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

            markerOverlay = new SimpleMarkerOverlay();
            Map1.Overlays.Add("SimpleMarkerOverlay", markerOverlay);

            // Add the start and end flag
            string[] startPointString = startCoordinate.Text.Split(',');
            RendMarker(new PointShape(double.Parse(startPointString[0], CultureInfo.InvariantCulture), double.Parse(startPointString[1], CultureInfo.InvariantCulture)), "start");
            string[] endPointString = endCoordinate.Text.Split(',');
            RendMarker(new PointShape(double.Parse(endPointString[0], CultureInfo.InvariantCulture), double.Parse(endPointString[1], CultureInfo.InvariantCulture)), "end");

            roadblockOverlay = new SimpleMarkerOverlay();
            Map1.Overlays.Add("roadblockOverlay", roadblockOverlay);

            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.723061113001549, 30.279563862407535, -97.7011528297679, 30.26396413477692);

            Route();
        }

        private void btnAddRoadblock_Click(object sender, RoutedEventArgs e)
        {
            IsAddingRoadblocks = true;
        }

        private void btnStopAdding_Click(object sender, RoutedEventArgs e)
        {
            IsAddingRoadblocks = false;
        }

        private void btnRemove_Click(object sender, RoutedEventArgs e)
        {
            int count = roadblockOverlay.Markers.Count;
            if (count > 0)
            {
                roadblockOverlay.Markers.RemoveAt(count - 1);
                avoidablePoints.RemoveAt(count - 1);
                Route();
            }
        }

        private void btnClear_Click(object sender, RoutedEventArgs e)
        {
            roadblockOverlay.Markers.Clear();
            avoidablePoints.Clear();
            Route();
        }

        private void Map1_Click(object sender, MapClickEventArgs e)
        {
            if (IsAddingRoadblocks)
            {
                string position = String.Format("{0},{1}", e.WorldPointShape.X.ToString(CultureInfo.InvariantCulture), e.WorldPointShape.Y.ToString(CultureInfo.InvariantCulture));
                avoidablePoints.Add(position);
                GetclosestPointOnline(e.WorldPointShape);
                Route();
            }
        }

        private void GetRoute_Click(object sender, RoutedEventArgs e)
        {
            Route();
        }

        private void Route()
        {
            RouteAroundRoadblockService.RouteAroundRoadblocksClient client = new RouteAroundRoadblockService.RouteAroundRoadblocksClient();
            client.GetRouteCompleted += new EventHandler(client_GetRouteCompleted);
            client.GetRouteAsync(startCoordinate.Text, endCoordinate.Text, avoidablePoints);
        }

        void client_GetRouteCompleted(object sender, RouteAroundRoadblockService.GetRouteCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                string wkt = e.Result;
                routeLayer.InternalFeatures.Clear();
                if (!String.IsNullOrEmpty(wkt))
                {
                    LineShape route = LineShape.CreateShapeFromWellKnownData(wkt) as LineShape;
                    routeLayer.InternalFeatures.Add(new Feature(route));
                }
                else
                {
                    MessageBox.Show("No Route Exist!");
                }
                Map1.Refresh();
            }
        }

        private void GetclosestPointOnline(PointShape point)
        {
            GeoDataService.GeoDataGettingClient client = new CSharp_Silverlight_HowDoISamples.GeoDataService.GeoDataGettingClient();
            client.GetCenterPointOnLineCompleted += new EventHandler(client_GetCenterPointOnLineCompleted);
            string pointInString = String.Format("{0},{1}", point.X.ToString(CultureInfo.InvariantCulture), point.Y.ToString(CultureInfo.InvariantCulture));
            client.GetCenterPointOnLineAsync(pointInString);
        }

        void client_GetCenterPointOnLineCompleted(object sender, CSharp_Silverlight_HowDoISamples.GeoDataService.GetCenterPointOnLineCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                PointShape point = ConvertStringToPointShape(e.Result);
                RendRoadblock(point);
                Map1.Refresh();
            }
        }

        private void RendRoadblock(PointShape pointShape)
        {
            Marker marker = new Marker(pointShape);
            marker.ImageSource = new BitmapImage(new Uri("/theme/roadblock.png", UriKind.RelativeOrAbsolute));
            marker.ImageOffsetX = -10;
            marker.ImageOffsetY = -15;
            roadblockOverlay.Markers.Add(marker);
        }

        private void RendMarker(PointShape pointShape, string renderTag)
        {
            Marker marker = new Marker(pointShape);
            if (renderTag == "start")
            {
                marker.ImageSource = new BitmapImage(new Uri("/theme/StartpointMarker.png", UriKind.RelativeOrAbsolute));
            }
            else if (renderTag == "end")
            {
                marker.ImageSource = new BitmapImage(new Uri("/theme/EndpointMarker.png", UriKind.RelativeOrAbsolute));
            }
            marker.ImageOffsetY = -10;
            marker.ImageOffsetY = -10;
            markerOverlay.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);
        }
    }
}