using System;
using System.Collections.ObjectModel;
using System.Drawing;
using DevComponents.Schedule.Model;
namespace DevComponents.DotNetBar.Schedule
{
    /// 
    /// ViewDisplayCustomizations
    /// 
    public class ViewDisplayCustomizations
    {
        #region Events
        /// 
        /// Occurs when the ViewDisplayCustomizations have changed
        /// 
        public event EventHandler CollectionChanged;
        #endregion
        #region Private variables
        private CalendarView _CalendarView;
        private DaySlotBackgrounds _DaySlotBackgrounds;
        #endregion
        /// 
        /// ViewDisplayCustomizations
        /// 
        /// 
        public ViewDisplayCustomizations(CalendarView calendarView)
        {
            _CalendarView = calendarView;
        }
        #region Public properties
        /// 
        /// DaySlotBackgrounds
        /// 
        public DaySlotBackgrounds DaySlotBackgrounds
        {
            get
            {
                if (_DaySlotBackgrounds == null)
                {
                    _DaySlotBackgrounds = new DaySlotBackgrounds();
                    _DaySlotBackgrounds.CollectionChanged += _DaySlotBackgrounds_CollectionChanged;
                }
                return (_DaySlotBackgrounds);
            }
            set
            {
                if (_DaySlotBackgrounds != null)
                    _DaySlotBackgrounds.CollectionChanged -= _DaySlotBackgrounds_CollectionChanged;
                _DaySlotBackgrounds = value;
                if (_DaySlotBackgrounds != null)
                    _DaySlotBackgrounds.CollectionChanged += _DaySlotBackgrounds_CollectionChanged;
            }
        }
        
        #endregion
        #region Event handling
        /// 
        /// Handles DaySlotBackgrounds CollectionChanged events
        /// 
        /// 
        /// 
        void _DaySlotBackgrounds_CollectionChanged(object sender, EventArgs e)
        {
            _CalendarView.Refresh();
            if (CollectionChanged != null)
                CollectionChanged(this, EventArgs.Empty);
        }
        #endregion
        #region GetDaySlotAppearance
        /// 
        /// Retrieves the DaySlotAppearance from the given criteris
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        internal DaySlotAppearance GetDaySlotAppearance(
            string ownerKey, DateTime dateTime, WorkTime wkStart, WorkTime wkEnd)
        {
            foreach (DaySlotBackground dsb in DaySlotBackgrounds)
            {
                if (IsValidSlot(dsb, dateTime, wkStart, wkEnd) == true)
                {
                    if (IsValidOwner(dsb, ownerKey) == true)
                        return (dsb.Appearance);
                }
            }
            return (null);
        }
        #endregion
        #region IsValidSlot
        /// 
        /// Determines if the given slot is a valid
        /// day and time slot
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        private bool IsValidSlot(DaySlotBackground dsb,
            DateTime dateTime, WorkTime wkStart, WorkTime wkEnd)
        {
            if (IsValidDaySlot(dsb, dateTime) == true)
                return (IsValidTimeSlot(dsb, wkStart, wkEnd));
            return (false);
        }
        #endregion
        #region IsValidTimeSlot
        /// 
        /// Determines if the given slot is a valid time slot
        /// 
        /// 
        /// 
        /// 
        /// 
        private bool IsValidTimeSlot(DaySlotBackground dsb, WorkTime wkStart, WorkTime wkEnd)
        {
            return (wkStart < dsb.Appearance.EndTime && wkEnd > dsb.Appearance.StartTime);
        }
        #endregion
        #region IsValidDaySlot
        /// 
        /// Determines if the given slot is a valid time slot
        /// 
        /// 
        /// 
        /// 
        private bool IsValidDaySlot(DaySlotBackground dsb, DateTime dateTime)
        {
            if (dsb.DateTime == DateTime.MinValue)
                return (dsb.DayOfWeek == dateTime.DayOfWeek);
            return (dsb.DateTime.Date == dateTime.Date);
        }
        #endregion
        #region IsValidOwner
        /// 
        /// Determines if the given owner key is valid for the slot
        /// 
        /// 
        /// 
        /// 
        private bool IsValidOwner(DaySlotBackground dsb, string ownerKey)
        {
            if (dsb.HasOwnerKeys == true)
            {
                if (dsb.OwnerKeys.Contains("") == true)
                    return (true);
                if (dsb.OwnerKeys.Contains(ownerKey) == false)
                    return (false);
            }
            return (true);
        }
        #endregion
    }
    /// 
    /// DaySlotBackgrounds
    /// 
    public class DaySlotBackgrounds : Collection
    {
        #region Events
        /// 
        /// Occurs when the DaySlotBackgrounds collection changes
        /// 
        public event EventHandler CollectionChanged;
        #endregion
        #region Private variables
        private bool _IsRangeSet;
        private bool _SuspendUpdate;
        #endregion
        #region Internal properties
        /// 
        /// Gets and sets the SuspendUpdate state
        /// 
        internal bool SuspendUpdate
        {
            get { return (_SuspendUpdate); }
            set { _SuspendUpdate = value; }
        }
        #endregion
        #region Remove
        /// 
        /// Removes the DaySlotBackground for the given DateTime
        /// 
        /// 
        public void Remove(DateTime dateTime)
        {
            int n = Items.Count;
            try
            {
                SuspendUpdate = true;
                for (int i = Items.Count - 1; i >= 0; i--)
                {
                    DaySlotBackground dsb = Items[i];
                    if (dsb.DateTime.Equals(dateTime) == true)
                        RemoveAt(i);
                }
            }
            finally
            {
                SuspendUpdate = false;
                if (Items.Count != n)
                    OnCollectionChanged();
            }
        }
        /// 
        /// Removes the DaySlotBackground for the given DayOfWeek
        /// 
        /// 
        public void Remove(DayOfWeek dayOfWeek)
        {
            int n = Items.Count;
            try
            {
                SuspendUpdate = true;
                for (int i = Items.Count - 1; i >= 0; i--)
                {
                    DaySlotBackground dsb = Items[i];
                    if (dsb.DateTime.Equals(DateTime.MinValue) == true)
                    {
                        if (dsb.DayOfWeek == dayOfWeek)
                            RemoveAt(i);
                    }
                }
            }
            finally
            {
                SuspendUpdate = false;
                if (Items.Count != n)
                    OnCollectionChanged();
            }
        }
        #endregion
        #region AddRange
        /// 
        /// Adds a range of DaySlotBackgrounds
        /// 
        /// 
        public void AddRange(DaySlotBackgrounds daySlotBackgrounds)
        {
            try
            {
                _IsRangeSet = true;
                foreach (DaySlotBackground dsb in daySlotBackgrounds)
                    Add(dsb);
            }
            finally
            {
                _IsRangeSet = false;
                OnCollectionChanged();
            }
        }
        #endregion
        #region RemoveItem
        /// 
        /// Processes list RemoveItem calls
        /// 
        /// Index to remove
        protected override void RemoveItem(int index)
        {
            base.RemoveItem(index);
            OnCollectionChanged();
        }
        #endregion
        #region InsertItem
        /// 
        /// Processes list InsertItem calls
        /// 
        /// Index to add
        /// Text to add
        protected override void InsertItem(int index, DaySlotBackground item)
        {
            if (item != null)
            {
                base.InsertItem(index, item);
                item.DaySlotBackgrounds = this;
                OnCollectionChanged();
            }
        }
        #endregion
        #region SetItem
        /// 
        /// Processes list SetItem calls (e.g. replace)
        /// 
        /// Index to replace
        /// Text to replace
        protected override void SetItem(int index, DaySlotBackground newItem)
        {
            base.SetItem(index, newItem);
            newItem.DaySlotBackgrounds = this;
            OnCollectionChanged();
        }
        #endregion
        #region ClearItems
        /// 
        /// Processes list Clear calls (e.g. remove all)
        /// 
        protected override void ClearItems()
        {
            if (Count > 0)
            {
                base.ClearItems();
                OnCollectionChanged();
            }
        }
        #endregion
        #region OnCollectionChanged
        /// 
        /// Handles collection change notification
        /// 
        private void OnCollectionChanged()
        {
            if (_SuspendUpdate == false && _IsRangeSet == false)
            {
                if (CollectionChanged != null)
                    CollectionChanged(this, EventArgs.Empty);
            }
        }
        #endregion
    }
    /// 
    /// DaySlotBackground
    /// 
    public class DaySlotBackground
    {
        #region Events
        /// 
        /// Occurs when the DaySlotBackground collection changes
        /// 
        public event EventHandler CollectionChanged;
        #endregion
        #region Private variables
        private DayOfWeek _DayOfWeek;
        private DateTime _DateTime = DateTime.MinValue;
        private DaySlotAppearance _Appearance;
        private DaySlotBackgrounds _DaySlotBackgrounds;
        private OwnerKeyCollection _OwnerKeys;
        #endregion
        #region Constructors
        public DaySlotBackground(DateTime dateTime, DaySlotAppearance appearance)
        {
            _DateTime = dateTime;
            _Appearance = appearance;
        }
        public DaySlotBackground(DayOfWeek dayOfWeek, DaySlotAppearance appearance)
        {
            _DayOfWeek = dayOfWeek;
            _DateTime = DateTime.MinValue;
            _Appearance = appearance;
        }
        #endregion
        #region Public properties
        #region Appearance
        /// 
        /// Gets or sets the Appearance
        /// 
        public DaySlotAppearance Appearance
        {
            get { return (_Appearance); }
            set
            {
                _Appearance = value;
                OnCollectionChanged();
            }
        }
        #endregion
        #region DateTime
        /// 
        /// Gets or sets the DateTime
        /// 
        public DateTime DateTime
        {
            get { return (_DateTime); }
            set
            {
                if (_DateTime != value)
                {
                    _DateTime = value;
                    OnCollectionChanged();
                }
            }
        }
        #endregion
        #region DayOfWeek
        /// 
        /// Gets or sets the DayOfWeek
        /// 
        public DayOfWeek DayOfWeek
        {
            get { return (_DayOfWeek); }
            set
            {
                if (_DayOfWeek != value)
                {
                    _DayOfWeek = value;
                    OnCollectionChanged();
                }
            }
        }
        #endregion
        #region OwnerKeys
        /// 
        /// Gets or sets the OwnerKeyCollection
        /// 
        public OwnerKeyCollection OwnerKeys
        {
            get
            {
                if (_OwnerKeys == null)
                {
                    _OwnerKeys = new OwnerKeyCollection();
                    _OwnerKeys.CollectionChanged += OwnerKeys_CollectionChanged;
                }
                return (_OwnerKeys);
            }
            set
            {
                if (_OwnerKeys != null)
                    _OwnerKeys.CollectionChanged -= OwnerKeys_CollectionChanged;
                _OwnerKeys = value;
                if (_OwnerKeys != null)
                    _OwnerKeys.CollectionChanged += OwnerKeys_CollectionChanged;
            }
        }
        #endregion
        #endregion
        #region Internal properties
        #region DaySlotBackgrounds
        /// 
        /// Gets or sets the DaySlotBackgrounds
        /// 
        internal DaySlotBackgrounds DaySlotBackgrounds
        {
            get { return (_DaySlotBackgrounds); }
            set
            {
                _DaySlotBackgrounds = value;
                OnCollectionChanged();
            }
        }
        #endregion
        #region HasOwnerKeys
        /// 
        /// HasOwnerKeys
        /// 
        internal bool HasOwnerKeys
        {
            get { return (_OwnerKeys != null && _OwnerKeys.Count > 0); }
        }
        #endregion
        #endregion
        #region Event processing
        /// 
        /// Processes OwnerKeys_CollectionChanged events
        /// 
        /// 
        /// 
        private void OwnerKeys_CollectionChanged(object sender, EventArgs e)
        {
            OnCollectionChanged();
        } 
        #endregion
        #region OnCollectionChanged
        /// 
        /// Handles collection change notification
        /// 
        private void OnCollectionChanged()
        {
            if (CollectionChanged != null)
                CollectionChanged(this, EventArgs.Empty);
        }
        #endregion
    }
    /// 
    /// DaySlotAppearance
    /// 
    public class DaySlotAppearance
    {
        #region Private variables
        private WorkTime _StartTime;
        private WorkTime _EndTime;
        private Color _BackColor;
        private Color _HourBorderColor;
        private Color _HalfHourBorderColor;
        private string _Text;
        private ContentAlignment _TextAlignment;
        private Color _TextColor;
        private Color _SelectedTextColor;
        private Font _Font;
        private bool _OnTop;
        private bool _ShowTextWhenSelected = true;
        #endregion
        #region Constructors
        public DaySlotAppearance(WorkTime startTime, WorkTime endTime,
            Color backColor, Color hourBorderColor, Color halfHourBorderColor)
        {
            _StartTime = startTime;
            _EndTime = endTime;
            _BackColor = backColor;
            _HourBorderColor = hourBorderColor;
            _HalfHourBorderColor = halfHourBorderColor;
        }
        public DaySlotAppearance(int startHour, int startMinute,
            int endHour, int endMinute, Color backColor, Color hourBorderColor, Color halfHourBorderColor)
            : this(new WorkTime(startHour, startMinute), new WorkTime(endHour, endMinute), backColor, hourBorderColor, halfHourBorderColor)
        {
        }
        #endregion
        #region Public properties
        #region BackColor
        /// 
        /// Gets or sets the BackColor
        /// 
        public Color BackColor
        {
            get { return (_BackColor); }
            set { _BackColor = value; }
        }
        #endregion
        #region EndTime
        /// 
        /// Gets or sets the Appearance end time
        /// 
        public WorkTime EndTime
        {
            get { return (_EndTime); }
            set { _EndTime = value; }
        }
        #endregion
        #region Font
        /// 
        /// Gets or sets the DaySlot Font
        /// 
        public Font Font
        {
            get { return (_Font); }
            set { _Font = value; }
        }
        #endregion
        #region HalfHourBorderColor
        /// 
        /// Gets or sets the HalfHourBorderColor
        /// 
        public Color HalfHourBorderColor
        {
            get { return (_HalfHourBorderColor); }
            set { _HalfHourBorderColor = value; }
        }
        #endregion
        #region HourBorderColor
        /// 
        /// Gets or sets the HourBorderColor
        /// 
        public Color HourBorderColor
        {
            get { return (_HourBorderColor); }
            set { _HourBorderColor = value; }
        }
        #endregion
        #region OnTop
        /// 
        /// Gets or sets whether the Text is on top of the borders
        /// 
        public bool OnTop
        {
            get { return (_OnTop); }
            set { _OnTop = value; }
        }
        #endregion
        #region StartTime
        /// 
        /// Gets or sets the Appearance start time
        /// 
        public WorkTime StartTime
        {
            get { return (_StartTime); }
            set { _StartTime = value; }
        }
        #endregion
        #region Text
        /// 
        /// Gets or sets the Text
        /// 
        public string Text
        {
            get { return (_Text); }
            set { _Text = value; }
        }
        #endregion
        #region TextAlignment
        /// 
        /// Gets or sets the Text Alignment
        /// 
        public ContentAlignment TextAlignment
        {
            get { return (_TextAlignment); }
            set { _TextAlignment = value; }
        }
        #endregion
        #region TextColor
        /// 
        /// Gets or sets the Text Color
        /// 
        public Color TextColor
        {
            get { return (_TextColor); }
            set { _TextColor = value; }
        }
        #endregion
        #region SelectedTextColor
        /// 
        /// Gets or sets the Selected Text Color
        /// 
        public Color SelectedTextColor
        {
            get { return (_SelectedTextColor); }
            set { _SelectedTextColor = value; }
        }
        #endregion
        #region ShowTextWhenSelected
        /// 
        /// Gets or sets wheter the Text is displayed when cells are selected
        /// 
        public bool ShowTextWhenSelected
        {
            get { return (_ShowTextWhenSelected); }
            set { _ShowTextWhenSelected = value; }
        }
        #endregion
        #endregion
    }
    /// 
    /// OwnerKeyCollection
    /// 
    public class OwnerKeyCollection : Collection
    {
        #region Events
        /// 
        /// Occurs when the OwnerKeyCollection changes
        /// 
        public event EventHandler CollectionChanged;
        #endregion
        #region RemoveItem
        /// 
        /// Processes list RemoveItem calls
        /// 
        /// Index to remove
        protected override void RemoveItem(int index)
        {
            base.RemoveItem(index);
            OnCollectionChanged();
        }
        #endregion
        #region InsertItem
        /// 
        /// Processes list InsertItem calls
        /// 
        /// Index to add
        /// Text to add
        protected override void InsertItem(int index, string item)
        {
            if (item != null)
            {
                base.InsertItem(index, item);
                OnCollectionChanged();
            }
        }
        #endregion
        #region SetItem
        /// 
        /// Processes list SetItem calls (e.g. replace)
        /// 
        /// Index to replace
        /// Text to replace
        protected override void SetItem(int index, string newItem)
        {
            base.SetItem(index, newItem);
            OnCollectionChanged();
        }
        #endregion
        #region ClearItems
        /// 
        /// Processes list Clear calls (e.g. remove all)
        /// 
        protected override void ClearItems()
        {
            if (Count > 0)
            {
                base.ClearItems();
                OnCollectionChanged();
            }
        }
        #endregion
        #region OnCollectionChanged
        /// 
        /// Handles collection change notification
        /// 
        private void OnCollectionChanged()
        {
            if (CollectionChanged != null)
                CollectionChanged(this, EventArgs.Empty);
        }
        #endregion
    }
}