using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media.Animation;

namespace BeWo.Controls
{
    [TemplatePart(Name = "PART_Border", Type = typeof(Border))]
    [TemplatePart(Name = "PART_Header", Type = typeof(Grid))]
    [TemplatePart(Name = "PART_Content", Type = typeof(Grid))]
    [ContentProperty("Content")]
    [DefaultProperty("Content")]
    public class ExpanderPanel : Control
    {
        private Border mBorder;

        private UIElement mContent;

        private Grid mContentGrid;

        private bool mExpanded;

        private UIElement mHeader;

        private Grid mHeaderGrid;

        private double mHeight;

        private double mMinHeight = 30;

        static ExpanderPanel()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ExpanderPanel), new FrameworkPropertyMetadata(typeof(ExpanderPanel)));
        }

        public ExpanderPanel()
        {
            this.Loaded += this.ExpanderPanel_Loaded;
        }

        [Bindable(true)]
        public UIElement Content
        {
            get
            {
                return this.mContent;
            }

            set
            {
                this.mContent = value;
                this.ApplyContent();
            }
        }

        [Bindable(true)]
        public UIElement Header
        {
            get
            {
                return this.mHeader;
            }

            set
            {
                this.mHeader = value;
                this.ApplyHeader();
            }
        }

        [Bindable(true)]
        public bool IsExpanded
        {
            get
            {
                return this.mExpanded;
            }

            set
            {
                this.UpdateExpander();
                this.mExpanded = value;
            }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this.mHeaderGrid = this.GetTemplateChild("PART_Header") as Grid;
            this.mContentGrid = this.GetTemplateChild("PART_Content") as Grid;
            this.mBorder = this.GetTemplateChild("PART_Border") as Border;

            this.ApplyContent();
            this.ApplyHeader();
        }

        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);
        }

        private void ApplyContent()
        {
            if (this.mContentGrid != null)
            {
                this.mContentGrid.Children.Clear();
                if (this.mContent != null)
                {
                    this.mContentGrid.Children.Add(this.mContent);
                }
            }
        }

        private void ApplyHeader()
        {
            if (this.mHeaderGrid != null)
            {
                this.mHeaderGrid.Children.Clear();
                if (this.mHeader != null)
                {
                    this.mHeaderGrid.Children.Add(this.mHeader);
                }
            }
        }

        private void CollapsePanel()
        {
            if (this.mBorder != null)
            {
                DoubleAnimationUsingKeyFrames animation = new DoubleAnimationUsingKeyFrames();
                animation.KeyFrames.Add(new SplineDoubleKeyFrame(this.mMinHeight, KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0, 300)), new KeySpline(1, 0, 1, 1)));

                this.mBorder.BeginAnimation(HeightProperty, animation);
            }
        }

        private void ExpandPanel()
        {
            if (this.mBorder != null)
            {
                DoubleAnimationUsingKeyFrames animation = new DoubleAnimationUsingKeyFrames();
                animation.KeyFrames.Add(new SplineDoubleKeyFrame(this.mHeight, KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0, 300)), new KeySpline(1, 0, 1, 1)));

                this.mBorder.BeginAnimation(HeightProperty, animation);
            }
        }

        private void ExpanderPanel_Loaded(object sender, RoutedEventArgs e)
        {
            if (this.mBorder != null && this.mHeight == 0)
            {
                this.mHeight = this.mBorder.ActualHeight;
                if (this.mHeight > 0)
                {
                    this.mBorder.Height = this.mHeight;
                }
            }
        }

        private void UpdateExpander()
        {
            if (this.mExpanded)
            {
                this.ExpandPanel();
            }
            else
            {
                this.CollapsePanel();
            }
        }
    }
}