using System;
//using ESRI.ArcGIS.Client;
//using Vishcious.ArcGIS.SLContrib;
//using ESRI.ArcGIS.Client.Geometry;
//using ESRI.ArcGIS.Client.Symbols;
using System.Windows.Media;
using System.Collections.Generic;
using System.Windows.Threading;
using System.Windows.Media.Animation;
using System.Collections;
using System.Linq;
using System.Windows.Input;
using System.Windows;
using Telerik.Windows.Controls.Map;
using System.Windows.Controls;
using Vishcious.ArcGIS.SLContrib;

namespace Demo.RadMap.UI
{
    public static class MapShapeHelper
    {
        public static IList<FrameworkElement> ToMapElements(this IEnumerable<ShapeFileRecord> records)
        {
            IList<FrameworkElement> elements = new List<FrameworkElement>();

            foreach (var record in records)
            {
                if (record == null)
                    continue;

                switch (record.ShapeType)
                {
                    case (int)ShapeType.Multipoint:
                        CreatePoints(record, elements);
                     break;
                    case (int)ShapeType.Point:
                        CreatePoint(record, elements);
                     break;
                    case (int)ShapeType.Polygon:
                        CreatePolygon(record, elements);
                     break;
                    case (int)ShapeType.PolyLine:
                        CreatePolyline(record, elements);
                     break;
                    default:
                        break;
                }
            }

            return elements;
        }

        private static void CreatePoints(ShapeFileRecord record, IList<FrameworkElement> mapObjects)
        {

            for (int i = 0; i < record.Points.Count; i+=10)
            {
                double longitude = record.Points[i].X;
                double latitude = record.Points[i].Y;

                MapPinPoint point = CreatePoint(record, latitude, longitude);

                mapObjects.Add(point);
            }
        }

        private static void CreatePoint(ShapeFileRecord record, IList<FrameworkElement> mapObjects)
        {
            double longitude = record.Points[0].X;
            double latitude = record.Points[0].Y;

            MapPinPoint point = CreatePoint(record, latitude, longitude);

            mapObjects.Add(point);
        }

        private static MapPinPoint CreatePoint(ShapeFileRecord record, double latitude, double longitude)
        {
            MapPinPoint point = new MapPinPoint();
            MapLayer.SetLocation(point, new Location(latitude, longitude));

            point.Tag = record;

            return point;
        }

        private static void CreateMapPath(ShapeFileRecord record, IList<LocationCollection> locations, IList<FrameworkElement> mapObjects)
        {
            MapPathGeometry geometry = CreateMapPathGeometry(locations[0]);
            locations.RemoveAt(0);
            foreach (LocationCollection subLocations in locations)
            {
                AddFigure(geometry, subLocations);
            }

            MapPath path = new MapPath();
            path.Tag = record;

            path.Data = geometry;

            mapObjects.Add(path);
        }

        private static void AddFigure(MapPathGeometry geometry, LocationCollection locations)
        {
            MapPolyLineSegment segment = new MapPolyLineSegment();
            segment.Points = locations;

            MapPathFigure figure = new MapPathFigure();
            if (segment.Points != null && segment.Points.Count > 0)
            {
                figure.StartPoint = segment.Points[0];
            }
            figure.Segments.Add(segment);
            geometry.Figures.Add(figure);

            // add empty figure to correct odd position for each inner polygon
            figure = new MapPathFigure();
            if (segment.Points != null && segment.Points.Count > 0)
            {
                figure.StartPoint = segment.Points[segment.Points.Count - 1];
            }
            geometry.Figures.Add(figure);
        }

        private static MapPathGeometry CreateMapPathGeometry(LocationCollection locations)
        {
            MapPolyLineSegment polyline = new MapPolyLineSegment();
            polyline.Points = locations;

            MapPathFigure figure = new MapPathFigure();
            figure.StartPoint = locations[0];
            figure.Segments.Add(polyline);

            MapPathGeometry geometry = new MapPathGeometry();
            geometry.FillRule = FillRule.EvenOdd;
            geometry.Figures.Add(figure);

            return geometry;
        }

        private static void CreatePolygon(ShapeFileRecord record, IList<FrameworkElement> mapObjects)
        {
            IList<LocationCollection> points = GetPoints(record);
            if (points.Count < 2)
            {
                var polygon = new MapPolygon();
               
                polygon.Points = points[0];

                polygon.Tag = record;

                mapObjects.Add(polygon);
            }
            else
            {
                CreateMapPath(record, points, mapObjects );
            }
        }

        private static void CreatePolyline(ShapeFileRecord record, IList<FrameworkElement> mapObjects)
        {
            IList<LocationCollection> points = GetPoints(record);
            foreach (LocationCollection locations in points)
            {
                var polyline = new MapPolyline();
                polyline.Points = locations;
                polyline.Tag = record;

                mapObjects.Add(polyline);
            }
        }

        private static IList<LocationCollection> GetPoints(ShapeFileRecord record)
        {
            List<LocationCollection> pointsCollection = new List<LocationCollection>();

            for (int i = 0; i < record.NumberOfParts; i++)
            {
                LocationCollection points = new LocationCollection();

                // Determine the starting index and the end index
                // into the points array that defines the figure.
                int start = record.Parts[i];
                int end;
                if (record.NumberOfParts > 1 && i != (record.NumberOfParts - 1))
                    end = record.Parts[i + 1];
                else
                    end = record.NumberOfPoints;

                //LocationCollection points = new LocationCollection();
                // Add line segments to the polyline
                for (int j = start; j < end; j++)
                {
                    System.Windows.Point point = record.Points[j];
                    points.Add(new Location(point.Y, point.X));
                }

                pointsCollection.Add(points);
            }

            return pointsCollection;
        }
    }
}