using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Shapes;
using System.Windows.Input;
using System.Windows.Media;
using GMapNET;
using System.Xml.Linq;

namespace System.Windows.Controls
{
    public class GMapKmlPlacemark : GMapOverlay
    {

        
        public Brush MouseOverFill { get; set; }
        public Brush MouseOverStroke { get; set; }
        public Double MouseOverStrokeThickness { get; set; }
        public Double MouseOverOpacity { get; set; }

        private Brush _fill;
        private Brush _stroke;
        private Double _strokeThickness;
        public Brush Fill
        {
            get
            {
                return _fill;
            }
            set
            {
                _fill = value;
                OverlayPath.Fill = _fill;
            }
        }
        public Brush Stroke
        {
            get
            {
                return _stroke;
                //return OverlayGeometry.Pen.Brush;
            }
            set
            {
                _stroke = value;
                OverlayPath.Stroke = _stroke;
                //OverlayGeometry.Pen.Brush = value;
            }
        }
        public Double StrokeThickness
        {
            get
            {
                return _strokeThickness;
            }
            set
            {
                _strokeThickness = value;
                OverlayPath.StrokeThickness = _strokeThickness;
            }
        }

        public override FrameworkElement MarkerElement
        {
            get
            {
                return OverlayPath;
            }
        }

        public KmlPlacemark Placemark { get; set; }
        public List<KmlGeometry> LocalGeometries { get; set; }
        public XElement KMLPlacemarkElement { get; set; }

        public Path OverlayPath = new Path();
        private Rect GeometryRect;

        public GMapKmlPlacemark(GMap Map, String kmlPlacemarkElement)
        {
            this.Map = Map;
            KMLPlacemarkElement = XElement.Parse(kmlPlacemarkElement);
            DoStartupTasks();
        }

        public GMapKmlPlacemark(GMap Map, XElement kmlPlacemarkElement)
        {
            this.Map = Map;
            KMLPlacemarkElement = kmlPlacemarkElement;
            DoStartupTasks();
        }


        private void DoStartupTasks()
        {
            base.SetMarkerMouseEvents(); // don't do standard Overlay events
           
            OverlayPath.MouseEnter += new MouseEventHandler(OverlayPath_MouseEnter);
            OverlayPath.MouseLeave += new MouseEventHandler(OverlayPath_MouseLeave);
            Opacity = 0.4d;
            MouseOverOpacity = Opacity;
            
            //BrushConverter conv = new BrushConverter();
            Fill = Brushes.Yellow;//conv.ConvertFromString("#64FFEE00") as SolidColorBrush;
            Stroke = Brushes.Black;
            StrokeThickness = 2d;

            MouseOverFill = Brushes.Goldenrod;//conv.ConvertFromString("#64FFEE00") as SolidColorBrush;
            MouseOverStroke = Brushes.Red;
            MouseOverStrokeThickness = 4d;

            OverlayPath.SnapsToDevicePixels = true;
            OverlayPath.HorizontalAlignment = HorizontalAlignment.Left;
            OverlayPath.VerticalAlignment = VerticalAlignment.Top;

           // OverlayImage.IsHitTestVisible = false;

            LoadKml();

            SetShapeCenter();
        }

        private void LoadKml()
        {
            LocalGeometries = new List<KmlGeometry>();
            Placemark = new KmlPlacemark(KMLPlacemarkElement);



        }

        /// <summary>
        /// Takes the PointLatLngs and changes them to local Polygon points
        /// </summary>
        /// <returns></returns>
        private void SetLocalPoints()
        {
            if (Placemark == null) return;
            if (Map.IsDragging)
            {
                
                return;
            }

            if (LocalGeometries.Count > 0 && Placemark.KmlGeometries.Count > 0)
            {
                PointLatLng p = new PointLatLng(Placemark.KmlGeometries[0].OuterBoundry.Points[0]);
                GMapNET.Point test1 = Map.FromLatLngToLocal(p);
                if (LocalGeometries[0].OuterBoundry.Points[0] == new Point(test1.X, test1.Y)) return;
            }

            LocalGeometries.Clear();
            foreach (KmlGeometry geo in Placemark.KmlGeometries)
            {
                KmlGeometry localGeo = new KmlGeometry();
                foreach (Point pnt in geo.OuterBoundry.Points)
                {
                    GMapNET.Point p1 = Map.FromLatLngToLocal(new PointLatLng(pnt));
                    Point localPnt = new Point(p1.X, p1.Y);
                    localGeo.OuterBoundry.Points.Add(localPnt);
                }

                foreach (Polygon mapPoly in geo.InnerBoundries)
                {
                    Polygon localPoly = new Polygon();
                    foreach (Point pnt in mapPoly.Points)
                    {
                        GMapNET.Point p1 = Map.FromLatLngToLocal(new PointLatLng(pnt));
                        Point localPnt = new Point(p1.X, p1.Y);
                        localPoly.Points.Add(localPnt);
                    }
                    localGeo.InnerBoundries.Add(localPoly);
                }
                LocalGeometries.Add(localGeo);
            }

            GeometryGroup combinedGeo = new GeometryGroup();
            foreach (KmlGeometry geo in LocalGeometries)
	        {
                Geometry tmpGeo = GetGeometry(geo.OuterBoundry);

                // remove any innerBoundries
                if (geo.InnerBoundries.Count > 0)
                {
                    foreach (Polygon innerPoly in geo.InnerBoundries)
                    {
                        Geometry innerGeo = GetGeometry(innerPoly);
                        tmpGeo = new CombinedGeometry(GeometryCombineMode.Exclude, tmpGeo, innerGeo);
                    }
                }

                combinedGeo.Children.Add(tmpGeo);
	        }

            OverlayPath.Data = combinedGeo;
            GeometryRect = OverlayPath.Data.GetRenderBounds(new Pen(OverlayPath.Stroke, OverlayPath.StrokeThickness));

            TranslateTransform tt = new TranslateTransform((GeometryRect.Left * -1), (GeometryRect.Top * -1));
            OverlayPath.RenderTransform = tt;

            Point centerPoint = new Point((GeometryRect.Left + (GeometryRect.Width / 2)), (GeometryRect.Top + (GeometryRect.Height / 2)));
            Position = Map.FromLocalToLatLng((int)centerPoint.X,(int)centerPoint.Y);

        }

        private Geometry GetGeometry(Polygon polygon)
        {
            StreamGeometry g = new StreamGeometry();
            using (StreamGeometryContext context = g.Open())
            {
                Point p1 = polygon.Points[0];
                context.BeginFigure(p1, true, true);
                for (int i = 1; i < polygon.Points.Count; i++)
                {
                    context.LineTo(polygon.Points[i], true, true);
                }
            }
            return g;
        }

        public override void SetShapeCenter()
        {
            SetLocalPoints();
            Objects[MarkerElement] = new Point(-GeometryRect.Width / 2, -GeometryRect.Height / 2);
        }

        //void OverlayPath_MouseUp(object sender, MouseButtonEventArgs e)
        //{
        //    if (e.ChangedButton == MouseButton.Middle)
        //    {
        //        base.UpdateLocalPosition(Map);
        //    }
        //}

        void OverlayPath_MouseLeave(object sender, MouseEventArgs e)
        {
            OverlayPath.Opacity = Opacity;
            OverlayPath.Fill = Fill;
            OverlayPath.Stroke = Stroke;
            OverlayPath.StrokeThickness = StrokeThickness;



        }

        void OverlayPath_MouseEnter(object sender, MouseEventArgs e)
        {
            OverlayPath.Opacity = MouseOverOpacity;
            OverlayPath.Fill = MouseOverFill;
            OverlayPath.Stroke = MouseOverStroke;
            OverlayPath.StrokeThickness = MouseOverStrokeThickness;
        }


      
    }
}
