using System;
using System.IO;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Controls;
using System.Collections.Generic;

namespace SalesDashboard
{
    /// <summary>
    /// General and map utilities.
    /// </summary>
    public static class Util
    {
        // gets a Stream from an embedded resource
        public static Stream GetResourceStream(string name)
        {
            var asm = Application.Current.GetType().Assembly;
            foreach (var rn in asm.GetManifestResourceNames())
            {
                if (rn.EndsWith(name))
                {
                    return asm.GetManifestResourceStream(rn);
                }
            }
            return null;
        }

        // gets a string from an embedded resource
        public static string GetResourceString(string name)
        {
            using (var stream = GetResourceStream(name))
            {
                if (stream != null) // can fail at design time...
                {
                    using (var sr = new StreamReader(stream))
                    {
                        return sr.ReadToEnd();
                    }
                }
            }
            return null;
        }

        // create a brush with opacity
        public static Brush CreateBrush(Color color, double opacity)
        {
            var brush = new SolidColorBrush(color);
            brush.Opacity = opacity;
            return brush;
        }

        #region ** ESRI map utilities

        // convert geo coordinates (lat/lon) to and from map coordinates
        // (assuming WebMercator projection).
        static ESRI.ArcGIS.Client.Projection.WebMercator _wm = new ESRI.ArcGIS.Client.Projection.WebMercator();
        public static ESRI.ArcGIS.Client.Geometry.MapPoint GeoToMap(Point point)
        {
            var mapPoint = new ESRI.ArcGIS.Client.Geometry.MapPoint(point.X, point.Y);
            return _wm.FromGeographic(mapPoint) as ESRI.ArcGIS.Client.Geometry.MapPoint;
        }
        public static Point MapToGeo(ESRI.ArcGIS.Client.Geometry.MapPoint mapPoint)
        {
            mapPoint = _wm.ToGeographic(mapPoint) as ESRI.ArcGIS.Client.Geometry.MapPoint;
            return new Point(mapPoint.X, mapPoint.Y);
        }

        // hit testing
        public static object HitTestMap(ESRI.ArcGIS.Client.Map map, MouseButtonEventArgs e)
        {
            var pt = e.GetPosition(null);
            for (int i = map.Layers.Count - 1; i >= 0; i--)
            {
                var gl = map.Layers[i] as ESRI.ArcGIS.Client.GraphicsLayer;
                if (gl != null)
                {
                    foreach (var g in gl.FindGraphicsInHostCoordinates(pt))
                    {
                        var dataItem = g.Attributes["DataContext"];
                        if (dataItem != null)
                        {
                            return dataItem;
                        }
                    }
                }
            }
            return null;
        }
        #endregion
    }
    /// <summary>
    /// Provides an attached behavior to clip elements to their bounds.
    /// </summary>
    /// <remarks>
    /// To use this class, add the Clip.ToBounds property to any control in XAML. For example:
    /// <code>
    /// &lt;c1:C1Chart 
    ///   Name="_chart"
    ///   local:Clip.ToBounds="True" /&gt;
    /// </code>
    /// (from http://www.scottlogic.co.uk/blog/colin/2009/05/silverlight-cliptobounds-can-i-clip-it-yes-you-can/)
    /// </remarks>
    public class Clip
    {
        /// <summary>
        /// Gets the value of the <b>ToBounds</b> attached property.
        /// </summary>
        public static bool GetToBounds(DependencyObject depObj)
        {
            return (bool)depObj.GetValue(ToBoundsProperty);
        }
        /// <summary>
        /// Sets the value of the <b>ToBounds</b> attached property.
        /// </summary>
        public static void SetToBounds(DependencyObject depObj, bool clipToBounds)
        {
            depObj.SetValue(ToBoundsProperty, clipToBounds);
        }
        /// <summary>
        /// Identifies the ToBounds Dependency Property.
        /// <summary>
        public static readonly DependencyProperty ToBoundsProperty =
            DependencyProperty.RegisterAttached("ToBounds", typeof(bool),
            typeof(Clip), new PropertyMetadata(false, OnToBoundsPropertyChanged));
        static void OnToBoundsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var fe = d as FrameworkElement;
            if (fe != null)
            {
                ClipToBounds(fe);
                fe.Loaded += (ss, ee) => { ClipToBounds(ss as FrameworkElement); };
                fe.SizeChanged += (ss, ee) => { ClipToBounds(ss as FrameworkElement); };
            }
        }
        /// <summary>
        /// Creates a rectangular clipping geometry which matches the geometry of the
        /// passed element
        /// </summary>
        private static void ClipToBounds(FrameworkElement fe)
        {
            if (GetToBounds(fe))
            {
                var rg = new RectangleGeometry();
                rg.Rect = new Rect(0, 0, fe.ActualWidth, fe.ActualHeight);
                fe.Clip = rg;
            }
            else
            {
                fe.Clip = null;
            }
        }
    }
}
