using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;

using BS.Shared.Core;
using BS.Shared.Extensions;

namespace BeWo.Controls.Calendar
{
    public class CalendarContentGrid : Grid
    {
        private readonly Dictionary<UIElement, int> _ChildsToPositions = new Dictionary<UIElement, int>();

        private Orientation _Orientation;

        public CalendarContentGrid()
        {
            this.Orientation = Orientation.Horizontal;
        }

        public event EventHandler<EventArgs<int>> ParallelCountChanged;

        public Orientation Orientation
        {
            get
            {
                return this._Orientation;
            }

            set
            {
                this._Orientation = value;
            }
        }

        public void Add(UIElement pElement, int pIndex, int pSpan, int pPosition)
        {
            if (this._Orientation == Orientation.Horizontal)
            {
                SetRow(pElement, pIndex);
                SetRowSpan(pElement, pSpan);
            }
            else
            {
                SetColumn(pElement, pIndex);
                SetColumnSpan(pElement, pSpan);
            }

            this.Children.Add(pElement);
            this._ChildsToPositions.Add(pElement, pPosition);
            this.ReArrange();
        }

        public void Remove(UIElement pElement)
        {
            this.Children.Remove(pElement);
            bool l = this._ChildsToPositions.Remove(pElement);
            this.ReArrange();
        }

        private void ReArrange()
        {
            var lChilds = this._ChildsToPositions.OrderBy(entry => entry.Value).GroupBy(entry => entry.Value);
            int lDifferentPositionCount = lChilds.Count();

            int lDifferentPositionCountBak = 0;

            if (this._Orientation == Orientation.Horizontal)
            {
                lDifferentPositionCountBak = this.ColumnDefinitions.Count;

                for (int iCol = 0; iCol < lDifferentPositionCount; iCol++)
                {
                    lChilds.ElementAt(iCol).DoForEach(iEntry => SetColumn(iEntry.Key, iCol));
                }

                while (this.ColumnDefinitions.Count > lDifferentPositionCount)
                {
                    this.ColumnDefinitions.RemoveAt(this.ColumnDefinitions.Count - 1);
                }

                while (this.ColumnDefinitions.Count < lDifferentPositionCount)
                {
                    this.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
                }
            }
            else
            {
                lDifferentPositionCountBak = this.RowDefinitions.Count;

                for (int iCol = 0; iCol < lDifferentPositionCount; iCol++)
                {
                    lChilds.ElementAt(iCol).DoForEach(iEntry => SetRow(iEntry.Key, iCol));
                }

                while (this.RowDefinitions.Count > lDifferentPositionCount)
                {
                    this.RowDefinitions.RemoveAt(this.RowDefinitions.Count - 1);
                }

                while (this.RowDefinitions.Count < lDifferentPositionCount)
                {
                    this.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
                }
            }

            if (this.ParallelCountChanged != null && lDifferentPositionCountBak != lDifferentPositionCount)
            {
                this.ParallelCountChanged(this, new EventArgs<int>(lDifferentPositionCount));
            }
        }
    }
}