using System.Collections.Generic;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using GMapNET;

namespace System.Windows.Controls
{
    public abstract class GMapOverlay : MapObject
    {
        private MapObject _linkedObject;
        public MapObject LinkedObject
        {
            get
            {
                return _linkedObject;
            }
            set
            {
                _linkedObject = value;
                if (_linkedObject != null)
                    _linkedObject.OnPositionChanged += new PositionChanged(_linkedObject_OnPositionChanged);
            }
        }

        void _linkedObject_OnPositionChanged(PointLatLng position)
        {
            // Move me based on my linked object
            this.Position = position;
            if (Map != null)
            {
                UpdateLocalPosition(Map);
            }
        }

        public readonly Popup Popup = new Popup();
        public readonly Label Label = new Label();
        public bool ShowTooltip = true;
        private ContextMenu _contextMenu;
        public ContextMenu ContextMenu
        {
            get
            {
                return _contextMenu;
            }
            set
            {
                _contextMenu = value;
                if (MarkerElement != null)
                    MarkerElement.ContextMenu = _contextMenu;
            }
        }

        public Double Opacity
        {
            get
            {
                if (MarkerElement != null)
                    return MarkerElement.Opacity;
                else
                    return 0d;
            }
            set
            {
                if (MarkerElement != null)
                    MarkerElement.Opacity = value;
            }
        }

        public abstract FrameworkElement MarkerElement
        {
            get;
        }

        public GMap Map;
        public readonly Dictionary<UIElement, Point> Objects = new Dictionary<UIElement, Point>();

        public int MinZoom = 1;
        public int MaxZoom = 19;

        public int X
        {
            get
            {
                return (int)Canvas.GetLeft(MarkerElement);
            }
        }

        public int Y
        {
            get
            {
                return (int)Canvas.GetTop(MarkerElement);
            }
        }

        public int ZIndex
        {
            get
            {
                return (int)Canvas.GetZIndex(MarkerElement);
            }

            set
            {
                Canvas.SetZIndex(MarkerElement, value);
            }
        }


        private int _mapIndex = -1;
        /// <summary>
        /// returns the index of this Overlay in the Maps MapOverlay collection
        /// </summary>
        public int MapIndex
        {
            get
            {
                if (Map != null && _mapIndex == -1)
                {
                    _mapIndex = Map.GetMapOverlayIndex(this);
                    return _mapIndex;
                }
                else
                    return _mapIndex;
            }
        }

        public GMapOverlay()
        {
            Popup.AllowsTransparency = true;
            Popup.Child = Label;
            Popup.Placement = PlacementMode.Mouse;
        }

        public void SetMarkerMouseEvents()
        {
            MarkerElement.MouseEnter += new MouseEventHandler(MarkerElement_MouseEnter);
            MarkerElement.MouseLeave += new MouseEventHandler(MarkerElement_MouseLeave);
            MarkerElement.MouseWheel += new MouseWheelEventHandler(MarkerElement_MouseWheel);

            MarkerElement.MouseDown += new MouseButtonEventHandler(MarkerElement_MouseDown);
            MarkerElement.MouseUp += new MouseButtonEventHandler(MarkerElement_MouseUp);
        }

        void MarkerElement_MouseUp(object sender, MouseButtonEventArgs e)
        {

        }

        void MarkerElement_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (ShowTooltip)
            {
                Popup.IsOpen = false;
            }

        }

        void MarkerElement_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            // if (MarkerElement.IsMouseDirectlyOver)
            // {
            if (e.Delta > 0)
            {
                Map.Zoom += 1;
            }
            else
            {
                Map.Zoom -= 1;
            }
            // }
        }

        void MarkerElement_MouseLeave(object sender, MouseEventArgs e)
        {
            if (ShowTooltip)
            {
                Popup.IsOpen = false;
            }
            //  Canvas.SetZIndex(MarkerElement, MapIndex-1000);
        }

        void MarkerElement_MouseEnter(object sender, MouseEventArgs e)
        {
            if (ShowTooltip && Label.Content != null)
            {
                Popup.IsOpen = true;
            }
            //  Canvas.SetZIndex(MarkerElement, MapIndex+1000);
        }

        public abstract void SetShapeCenter();

        public void UpdateLocalPosition(IGControl map)
        {
            SetShapeCenter();

            if (Position != PointLatLng.Empty)
            {
                GMapNET.Point p = map.FromLatLngToLocal(Position);
                foreach (KeyValuePair<UIElement, Point> e in Objects)
                {
                    GMapNET.Point t = p;
                    t.Offset((int)e.Value.X, (int)e.Value.Y);

                    Canvas.SetTop(e.Key, t.Y);
                    Canvas.SetLeft(e.Key, t.X);
                }
            }
            else
            {
                foreach (KeyValuePair<UIElement, Point> e in Objects)
                {
                    Canvas.SetTop(e.Key, 0);
                    Canvas.SetLeft(e.Key, 0);
                }
            }

        }
    }
}
