using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using C1.Silverlight.Extended;
using C1.Silverlight;
using System.Windows.Markup;
using System.Threading;
using System.Windows.Browser;
using System.Globalization;

namespace Olympics
{
    public partial class Page : UserControl
    {
        private const double _margin = 10;
        private const double _bigViewPct = 0.65;
        
        private bool isMoving = false;

        private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            double totalWidth = ActualWidth - (container.Children.Count * _margin * 2);
            double accumulatedX = _margin;
            double bigCellWidth = totalWidth * _bigViewPct;

            foreach (C1HeaderedContentControl view in _orderedElements)
            {
                view.Height =  Math.Max( ActualHeight - 400, 320);
                view.Width = bigCellWidth;

                var elementTranslation = (TranslateTransform)(view.RenderTransform as TransformGroup).Children[1];
                elementTranslation.X = accumulatedX;

                double renderedCellWidth = (view == _front) 
                                        ? bigCellWidth
                                        : (totalWidth - bigCellWidth) / (container.Children.Count - 1);
                accumulatedX += renderedCellWidth + _margin * 2;
            }
        }

        private FrameworkElement CreateOverlayLayer(Action clickHandler, FrameworkElement RealContent) 
        {
            var grid = new Grid();
            grid.Children.Add(RealContent);
            grid.Children.Add(new Grid() { Background = new SolidColorBrush(Colors.Transparent), Cursor = Cursors.Hand });
            grid.MouseLeftButtonDown += (s, a) => { clickHandler(); };
            return grid;
        }

        private void HideOverlayLayer(FrameworkElement view) 
        {
            ((Grid)((C1HeaderedContentControl) view).Content).Children[1].Visibility = Visibility.Collapsed;
        }

        private void ShowOverlayLayer(FrameworkElement view)
        {
            ((Grid)((C1HeaderedContentControl)view).Content).Children[1].Visibility = Visibility.Visible;
        }

        public Page()
        {
            InitializeComponent();

            OnIsExpandedChanged();

            var clock = new Clock();
             //************************************************************
             //Olympic Games are over, data doesn´t change anymore...
             //************************************************************
            clock.TimeChanged += (s, a) => 
            {
                if ((DataBase.Data == null) && (a.Second % 30 == 0))
                {
                    UpdateOlympicData();
                }
            }; 
            panelClock.Children.Add(clock);

            hdrChart.Content = CreateOverlayLayer(ChartClick, new MedalsDistributionChart());
            hdrGrid.Content = CreateOverlayLayer(GridClick, new MedalsGrid());
            hdrMap.Content = CreateOverlayLayer(MapClick, new MedalsMap());

            Loaded += (s, a) =>
            {
                // initialize View
                _orderedElements.Add(hdrGrid);
                _orderedElements.Add(hdrMap);
                _orderedElements.Add(hdrChart);

                _front = hdrMap;
                HideOverlayLayer(hdrMap);
                BringToFront(hdrMap);
            };

            DataBase.DataUpdated += new EventHandler(DataBase_DataBaseChanged);
            UpdateOlympicData();
        }

        // Invoke the web service and update the data
        private void UpdateOlympicData()
        {
            txtUIStatus.Text = "Retrieving data from Olympics Gods...";
            DataBase.Load();
        }

        void DataBase_DataBaseChanged(object sender, EventArgs e)
        {
            txtUIStatus.Text = string.Empty;
        }

        private void MapClick()
        {
            BringToFront(hdrMap);
        }

        private void ChartClick()
        {
            BringToFront(hdrChart);
        }

        private void GridClick()
        {
            BringToFront(hdrGrid);
        }

        public const double _reduceScale = 0.25;
        private Transform _reduceTransformation = new ScaleTransform() { ScaleX = _reduceScale, ScaleY = _reduceScale };
        FrameworkElement _front;
        List<FrameworkElement> _orderedElements = new List<FrameworkElement>();

        private void BringToFront(FrameworkElement element) 
        {
            lock (this)
            {
                if (isMoving) return;

                var frontTran = (TranslateTransform)(_front.RenderTransform as TransformGroup).Children[1];
                var elemTran = (TranslateTransform)(element.RenderTransform as TransformGroup).Children[1];

                if (element != _front)
                {
                    Canvas.SetZIndex(_front, 0);
                    Canvas.SetZIndex(element, 1);
                    ShowOverlayLayer(_front);
                    HideOverlayLayer(element);

                    double seconds = 2;

                    Storyboard st = new Storyboard();
                    if (frontTran.X < elemTran.X)
                    {
                        // put RenderTransformOrigin in the oppposite side
                        element.RenderTransformOrigin = new Point(0, 0);
                        _front.RenderTransformOrigin = new Point(0, 0);

                        st.Children.Add(GetStoryboardTo(element, elemTran, frontTran, 1, seconds, true));
                        st.Children.Add(GetStoryboardTo(_front, frontTran, elemTran, _reduceScale, seconds, false));
                    }
                    else 
                    {
                        // put RenderTransformOrigin in the oppposite side
                        element.RenderTransformOrigin = new Point(0, 0);
                        _front.RenderTransformOrigin = new Point(0, 0);

                        st.Children.Add(GetStoryboardTo(element, elemTran, frontTran, 1, seconds, true));
                        st.Children.Add(GetStoryboardTo(_front, frontTran, elemTran, _reduceScale, seconds, false));
                    }

                    if (Resources.Contains("st")) Resources.Remove("st");
                    Resources.Add("st", st);
                    st.Completed += (s, a) => { isMoving = false; };
                    isMoving = true;
                    st.Begin();

                    int frontIndex = _orderedElements.IndexOf(_front);
                    int elementIndex = _orderedElements.IndexOf(element);
                    _orderedElements[frontIndex] = element;
                    _orderedElements[elementIndex] = _front;
                    _front = element;
                }
            }
        }

        private Storyboard GetStoryboardTo(FrameworkElement element, TranslateTransform oldTranslation, 
            TranslateTransform newTranslation, double scale, double seconds, bool below)
        {
            Storyboard st = new Storyboard();
            st.BeginTime = TimeSpan.FromSeconds(0);
            st.Duration = new Duration(TimeSpan.FromSeconds(seconds));
            Storyboard.SetTarget(st, element);

            // Translate X
            var animTranslationX = BuildAnimation(seconds, oldTranslation.X, newTranslation.X);
            Storyboard.SetTargetProperty(animTranslationX, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[1].(TranslateTransform.X)"));
            st.Children.Add(animTranslationX);

            // Translate Y
            var animTranslationY = BuildAnimation(seconds, oldTranslation.Y, newTranslation.Y);
            Storyboard.SetTargetProperty(animTranslationY, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[1].(TranslateTransform.Y)"));
            st.Children.Add(animTranslationY);

            // Scale X
            var animScaleX = new DoubleAnimation() { To = scale };
            Storyboard.SetTargetProperty(animScaleX, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"));
            st.Children.Add(animScaleX);

            // Scale Y
            var animScaleY = new DoubleAnimation() { To = scale };
            Storyboard.SetTargetProperty(animScaleY, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"));
            st.Children.Add(animScaleY);

            return st;
        }

        private static DoubleAnimationUsingKeyFrames BuildAnimation(double duration, params double[] values)
        {
            string splines = string.Empty;
            for (int i = 0; i < values.Length; i++)
			{
                splines += String.Format("<SplineDoubleKeyFrame Value=\"{0}\" KeyTime=\"0:0:{1}\" KeySpline=\"0, 0, 0.8, 0\" />", 
                    values[i].ToString().Replace(',', '.'), 
                    (duration / values.Length * i).ToString().Replace(',', '.'));
			}

            return (DoubleAnimationUsingKeyFrames) XamlReader.Load(String.Format(
                "<DoubleAnimationUsingKeyFrames xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" Duration=\"0:0:{0}\">" + 
                    splines + 
                "</DoubleAnimationUsingKeyFrames>", duration.ToString().Replace(',', '.')));
        }


        private bool _isExpanded = false;
        private bool _isExpanding = false;
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (_isExpanding) return;

            _isExpanded = !_isExpanded;
            OnIsExpandedChanged();
        }

        private void OnIsExpandedChanged()
        {
            double newHeight, newOpacity, newLettersOpacity;

            if (!_isExpanded)
            {
                newHeight = 0;
                newOpacity = 1;
                newLettersOpacity = 0.65;
                ((RotateTransform) btnExpand.RenderTransform).Angle = 0;
            }
            else
            {
                newHeight = 240;
                newOpacity = 0;
                newLettersOpacity = 0;
                ((RotateTransform)btnExpand.RenderTransform).Angle = 180;
            }

            double seconds = 2;

            Storyboard st = new Storyboard();
            st.BeginTime = TimeSpan.FromSeconds(0);
            st.Duration = new Duration(TimeSpan.FromSeconds(seconds));

            // Footer Height
            var animFooterHeight = BuildAnimation(seconds, footerC1.Height, newHeight);
            Storyboard.SetTargetProperty(animFooterHeight, new PropertyPath("Height"));
            Storyboard.SetTarget(animFooterHeight, footerC1);
            st.Children.Add(animFooterHeight);

            // Containers Opacity
            var animContainerOpacity = BuildAnimation(seconds, container.Opacity, newOpacity);
            Storyboard.SetTargetProperty(animContainerOpacity, new PropertyPath("Opacity"));
            Storyboard.SetTarget(animContainerOpacity, container);
            st.Children.Add(animContainerOpacity);

            // Letters Opacity
            var animLettersOpacity = BuildAnimation(seconds, letters.Opacity, newLettersOpacity);
            Storyboard.SetTargetProperty(animLettersOpacity, new PropertyPath("Opacity"));
            Storyboard.SetTarget(animLettersOpacity, letters);
            st.Children.Add(animLettersOpacity);

            if (Resources.Contains("exp")) Resources.Remove("exp");
            Resources.Add("exp", st);
            st.Completed += (s, a) => { _isExpanding = false; };
            _isExpanding = true;
            st.Begin();
        }

        private void btnDownload_Click(object sender, RoutedEventArgs e)
        {
            HtmlPage.Window.Navigate(new Uri("http://www.componentone.com/StudioSilverlight/Download"));
        }

        private void btnPurchase_Click(object sender, RoutedEventArgs e)
        {
            HtmlPage.Window.Navigate(new Uri("http://www.componentone.com/StudioSilverlight/Buy/"));
        }

        private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            HtmlPage.Window.Navigate(new Uri("http://www.componentone.com/SuperProducts/StudioSilverlight/"));
        }
    }
}
