using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using System.Diagnostics;
using System.Windows.Input;
using System.Data;

using Sched.CustomClasses;
using Sched.CustomDialogs;
using System.Collections.ObjectModel;
using System.Windows.Shapes;
using System.Windows.Data;

namespace Sched.CustomControls
{
    public class Timetable : Grid
    {
        private double _rowMinHeight = 24.0;
        private double _columnMinWidth = 60.0;
        private double _columnMaxWidth = 80.0;
        private double _lessonHeight = 40.0;
        private double _fontSize = 12.0;
        private int _periodColumnCount = 15; 

        Brush _borderBrush = Brushes.Black;
        double _borderThickness = 1.0;
        Pen _borderPen;
        Pen _outerBorderPen;
        Brush _background = Brushes.LightGray;

        //Days
        private List<string> _dayList = new List<string>() {
            "Str_Week_Monday",
            "Str_Week_Tuesday",
            "Str_Week_Wednesday",
            "Str_Week_Thursday",
            "Str_Week_Friday",
            "Str_Week_Saturday",
            "Str_Week_Sunday" };

        public Timetable()
        {
            this.CreateGrid();
        }
        public Timetable(double RowMinHeight = 24.0, double ColumnMinWidth = 60.0, double ColumnMaxWidth = 80.0, double FontSize = 12.0)
        {
            this._rowMinHeight = RowMinHeight;
            this._columnMinWidth = ColumnMinWidth;
            this._columnMaxWidth = ColumnMaxWidth;
            this._fontSize = FontSize;

            this.CreateGrid();
    }
        private void CreateGrid()
        {
            _borderPen = new Pen(_borderBrush, _borderThickness);
            _outerBorderPen = new Pen(_borderBrush, _borderThickness);

            HorizontalAlignment = HorizontalAlignment.Left;
            VerticalAlignment = VerticalAlignment.Top;
            Background = _background;

            // Define the Rows: Day label rows + Period row
            for (int i = 0; i < 8; i++)
            {
                RowDefinition rowDef = new RowDefinition();
                rowDef.MinHeight = this._rowMinHeight;
                rowDef.Height = GridLength.Auto;
                this.RowDefinitions.Add(rowDef);

                if (i > 0)  //add day label
                {
                    TextBlock TB = new TextBlock();
                    string s = _dayList[i - 1];
                    TB.SetResourceReference(TextBlock.TextProperty, s);

                    TB.TextAlignment = TextAlignment.Left;
                    TB.HorizontalAlignment = HorizontalAlignment.Center;
                    TB.VerticalAlignment = VerticalAlignment.Center;
                    TB.Padding = new Thickness(5);
                    TB.FontSize = this._fontSize;
                    Grid.SetRow(TB, i);
                    Grid.SetColumn(TB, 0);
                    this.Children.Add(TB);
                }
            }

            // Define the Columns: Day + Timeblocks
            for (int i = 0; i < 2; i++)
            {
                ColumnDefinition colDef = new ColumnDefinition();

                
                if (i == 0)
                {
                    colDef.MinWidth = this._columnMinWidth;
                    colDef.Width = GridLength.Auto;                      //The collumn will be big just enough to fit the controls.
                }
                else
                { 
                    colDef.MinWidth = this._columnMinWidth;
                    colDef.Width = new GridLength(1, GridUnitType.Star); //The column will strech to take up the rest of the available space.
                }                

                ColumnDefinitions.Add(colDef);
            }

            // Add subgrids
            for (int i = 0; i < 8; i++)
            {
                if (i == 0)
                {
                    //PeriodGrid
                    TimetableDayGrid subGrid = new TimetableDayGrid(true, this._rowMinHeight, this._columnMinWidth, this._lessonHeight, this._fontSize);
                    subGrid.Name = "Period";
                    Grid.SetRow(subGrid, i);
                    Grid.SetColumn(subGrid, 1);
                    this.Children.Add(subGrid);
                }
                else
                {
                    //DayGrid
                    TimetableDayGrid subGrid = new TimetableDayGrid(false, this._rowMinHeight, this._columnMinWidth, this._lessonHeight, this._fontSize);
                    subGrid.Name = _dayList[i - 1].Substring(9);
                    subGrid.Background = Brushes.White;
                    Grid.SetRow(subGrid, i);
                    Grid.SetColumn(subGrid, 1);
                    this.Children.Add(subGrid);
                }
            }

            this.SizeChanged += OnSizeChanged;
        }
        protected override void OnRender(DrawingContext dc)
        {
            base.OnRender(dc);

            //Inner borders
            for (int i = 0; i < this.RowDefinitions.Count; i++)
            {
                if (i != 0)
                {
                    RowDefinition rowDef = this.RowDefinitions[i];
                    Point pointStart = new Point(0, rowDef.Offset);
                    Point pointEnd = new Point(ActualWidth, rowDef.Offset);
                    dc.DrawLine(_borderPen, pointStart, pointEnd);
                }
            }

            for (int i = 0; i < this.ColumnDefinitions.Count; i++)
            {
                if (i != 0)
                {
                    ColumnDefinition colDef = this.ColumnDefinitions[i];
                    Point pointStart = new Point(colDef.Offset, 0);
                    Point pointEnd = new Point(colDef.Offset, ActualHeight);
                    dc.DrawLine(_borderPen, pointStart, pointEnd);
                }
            }

            //Outer border
            //Horizontal
            dc.DrawLine(_outerBorderPen, new Point(0, 0), new Point(ActualWidth, 0));   //top
            dc.DrawLine(_outerBorderPen, new Point(0, ActualHeight), new Point(ActualWidth, ActualHeight)); //bottom
            //Vertical
            dc.DrawLine(_outerBorderPen, new Point(0, 0), new Point(0, ActualHeight));  //left
            dc.DrawLine(_outerBorderPen, new Point(ActualWidth, 0), new Point(ActualWidth, ActualHeight));  //right
        }
        private void OnSizeChanged(object sender, SizeChangedEventArgs e)
        {
            double newWidth = e.NewSize.Width;
            //Debug.WriteLine("TT: " + e.PreviousSize + " " + e.NewSize);
            ResizePeriodColumn(newWidth);
        }

        public void ResizePeriodColumn(double tableWidth)
        {
            double width = tableWidth - this.ColumnDefinitions[0].ActualWidth;
            double colWidth = width / _periodColumnCount;
            for (int i = 7; i < this.Children.Count; i++)
            {
                var subgrid = this.Children[i] as TimetableDayGrid;
                subgrid.ResizeColumns(colWidth);
            }
        }

        public void LoadLessonsFromDB()
        {
            AssignmentData DA = DataContext as AssignmentData;
            if (DA != null)
            {
                //Clear subgrids of all lessons
                RemoveAllLessons();

                //Insert new Lessons from DB
                ObservableCollection<object> lessons = DBI.LoadCategoryLessons(DA.SemesterId, DA.CategoryName, DA.CategoryId); ;
                foreach(Lesson lsn in lessons)
                {
                    string dayRow = lsn.StartDateDT.DayOfWeek.ToString();
                    for(int i = 8; i < this.Children.Count; i++)    //TimetableDayGrid controls start from index 8 to 14
                    {
                        var subgrid = this.Children[i] as TimetableDayGrid;                        
                        if (subgrid.Name == dayRow)
                        {
                            subgrid.LessonAdd(lsn, lsn.PeriodStart, false);
                            break;  //no need to check rest of subgrids
                        }
                    }
                }           
            }
        }

        public void LoadLessons(ObservableCollection<object> lessons)
        {
            foreach (Lesson lsn in lessons)
            {
                string dayRow = lsn.StartDateDT.DayOfWeek.ToString();
                for (int i = 8; i < this.Children.Count; i++)    //TimetableDayGrid controls start from index 8 to 14
                {
                    var subgrid = this.Children[i] as TimetableDayGrid;
                    if (subgrid.Name == dayRow)
                    {
                        subgrid.LessonAdd(lsn, lsn.PeriodStart, false);
                        break;  //no need to check rest of subgrids
                    }
                }
            }
        }

        public void RemoveAllLessons()
        {
            for (int i = 8; i < this.Children.Count; i++)    //TimetableDayGrid controls are at index 8 to 14
            {
                var subgrid = this.Children[i] as TimetableDayGrid;
                subgrid.Children.Clear();
                subgrid.LessonReorder();
            }
        }

        public string FullInternalCheckForCollisions()
        {
            string collisionLessons = string.Empty;
            for (int i=8; i < this.Children.Count; i++)
            {
                var subgrid = this.Children[i] as TimetableDayGrid;
                var subgridTBlock = this.Children[i-8] as TextBlock;
                
                collisionLessons += "\n--------------------------------\n";
                collisionLessons += subgridTBlock.Text;
                collisionLessons += "\n--------------------------------\n";
                collisionLessons += subgrid.InternalCheckForCollisions();
            }

            return collisionLessons;
        }
        public string FullExternalCheckForCollisions()
        {
            string collisionLessons = string.Empty;
            for (int i = 8; i < this.Children.Count; i++)
            {
                var subgrid = this.Children[i] as TimetableDayGrid;
                var subgridTBlock = this.Children[i - 8] as TextBlock;

                collisionLessons += "\n--------------------------------\n";
                collisionLessons += subgridTBlock.Text;
                collisionLessons += "\n--------------------------------\n";
                collisionLessons += subgrid.ExternalCheckForCollisions();
            }

            return collisionLessons;
        }

    }

    public class TimetableDayGrid : Grid
    {
        public static RoutedEvent TimetableLessonAddedEvent = EventManager.RegisterRoutedEvent("TimetableLessonAdded", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TimetableDayGrid));
        public event RoutedEventHandler TimetableLessonAdded
        {
            add { AddHandler(TimetableLessonAddedEvent, value); }
            remove { RemoveHandler(TimetableLessonAddedEvent, value); }
        }

        private double _rowMinHeight = 20.0;
        private double _columnWidth = 90.0;
        private double _lessonHeight = 40.0;
        private double _fontSize = 12.0;

        Brush _borderBrush = Brushes.Black;
        double _borderThickness = 1.0;
        Pen _borderPen;
        Pen _outerBorderPen;
        Brush _periodBackground = Brushes.Gray;

        public TimetableDayGrid(bool isPeriodsGrid, double RowMinHeight, double ColumnWidth, double LessonHeight, double FontSize)
        {
            this._rowMinHeight = RowMinHeight;
            this._columnWidth = ColumnWidth;
            this._lessonHeight = LessonHeight;
            this._fontSize = FontSize;

            CreateGrid();

            if (isPeriodsGrid)
            {
                CreatePeriodLabels();
                Background = _periodBackground;
            }
            else
            {
                AddAllHandlers();
            }   
        }
        private void CreateGrid()
        {
            _borderPen = new Pen(_borderBrush, _borderThickness);
            _outerBorderPen = new Pen(_borderBrush, _borderThickness);

            //SetIsSharedSizeScope(this, true);
            Background = Brushes.Transparent;  //must declare, otherwise cannot capture clicks
            //ShowGridLines = true;

            RowDefinition rowDef = new RowDefinition();
            rowDef.MinHeight = this._rowMinHeight;
            rowDef.Height = new GridLength(1, GridUnitType.Star);
            RowDefinitions.Add(rowDef);

            for (int j = 0; j < 15; j++)
            {
                ColumnDefinition colDef = new ColumnDefinition();
                colDef.Width = new GridLength(this._columnWidth);
                //colDef.Width = new GridLength(1, GridUnitType.Star);
                //colDef.Width = new GridLength(_columnMaxWidth);
                //System.Windows.Data.BindingBase bindingBase = new System.Windows.Data.BindingBase();

                //colDef.SharedSizeGroup = "UniformColumn";
                //colDef.MaxWidth = this.ColumnMaxWidth;
                ColumnDefinitions.Add(colDef);
            } 
        }
        public void ResizeColumns(double colWidth)
        {
            this._columnWidth = colWidth;
            for (int i = 0; i < this.ColumnDefinitions.Count; i++)
            {
                this.ColumnDefinitions[i].Width = new GridLength(this._columnWidth);
            }
        }

        private void CreatePeriodLabels()
        {
            for (int j = 0; j < this.ColumnDefinitions.Count; j++)
            {
                TextBlock txt = new TextBlock();
                int hour = j + 7;
                if (hour < 10)
                {
                    txt.Text = $"{j + 1}\n0{hour}:00\n0{hour}:50";
                }
                else
                {
                    txt.Text = $"{j + 1}\n{hour}:00\n{hour}:50";
                }
                txt.TextAlignment = TextAlignment.Center;
                txt.HorizontalAlignment = HorizontalAlignment.Center;
                txt.VerticalAlignment = VerticalAlignment.Center;
                txt.FontSize = this._fontSize;
                Grid.SetRow(txt, 0);
                Grid.SetColumn(txt, j);
                Children.Add(txt);
            }
        }
        public void AddAllHandlers()
        {
            AddHandler(LessonBox.LessonBoxDeleteEvent, new RoutedEventHandler(LessonDelete));
            AddHandler(LessonBox.LessonBoxEditEvent, new RoutedEventHandler(LessonEdit));
            AddHandler(MouseLeftButtonDownEvent, new MouseButtonEventHandler(OnLeftDoubleClickAddLesson), true);
        }
        public void RemoveAllHandlers()
        {
            RemoveHandler(LessonBox.LessonBoxDeleteEvent, (RoutedEventHandler)LessonDelete);
            RemoveHandler(LessonBox.LessonBoxEditEvent, (RoutedEventHandler)LessonEdit);
            RemoveHandler(MouseLeftButtonDownEvent, (MouseButtonEventHandler)OnLeftDoubleClickAddLesson);
        }
        protected override void OnRender(DrawingContext dc)
        {
            base.OnRender(dc);

            /*
            for (int i = 0; i < this.RowDefinitions.Count; i++)
            {
                if (i != 0)
                {
                    RowDefinition rowDef = this.RowDefinitions[i];
                    Point pointStart = new Point(0, rowDef.Offset);
                    Point pointEnd = new Point(ActualWidth, rowDef.Offset);
                    dc.DrawLine(_borderPen, pointStart, pointEnd);
                }
            }
            */

            for (int i = 0; i < this.ColumnDefinitions.Count; i++)
            {
                if (i != 0)
                {
                    ColumnDefinition colDef = this.ColumnDefinitions[i];
                    Point pointStart = new Point(colDef.Offset, 0);
                    Point pointEnd = new Point(colDef.Offset, ActualHeight);
                    dc.DrawLine(_borderPen, pointStart, pointEnd);
                }
            }

            //Horizontal
            dc.DrawLine(_outerBorderPen, new Point(0, 0), new Point(ActualWidth, 0));
            dc.DrawLine(_outerBorderPen, new Point(0, ActualHeight), new Point(ActualWidth, ActualHeight));
            //Vertical
            dc.DrawLine(_outerBorderPen, new Point(0, 0), new Point(0, ActualHeight));
            dc.DrawLine(_outerBorderPen, new Point(ActualWidth, 0), new Point(ActualWidth, ActualHeight));
        }

        public void AddRow()
        {
            RowDefinition rowDef = new RowDefinition();
            rowDef.MinHeight = this._rowMinHeight;
            rowDef.Height = GridLength.Auto;
            this.RowDefinitions.Add(rowDef);
        }
        private void OnLeftDoubleClickAddLesson(object sender, MouseButtonEventArgs e)
        {
            var grid = sender as Grid;
            Point mousePos = e.GetPosition(grid);   //mousepos is relative to the grid

            if ((grid != null)&&(this.IsEnabled)&&(e.ClickCount == 2))
            {
                //Must check which column was clicked
                int curCol = 0;
                double width = 0;
                for (int i = 0; i < grid.ColumnDefinitions.Count; i++)
                {
                    width += grid.ColumnDefinitions[i].ActualWidth;
                    if (width > mousePos.X)
                    {
                        curCol = i;
                        break;
                    }
                }

                var AD = DataContext as AssignmentData;
                if (AD != null)
                {
                    //Check day and row match
                    string dayRow = this.Name;
                    string dayStart = AD.Lssn.StartDateDT.DayOfWeek.ToString();
                    if (dayRow != dayStart)
                    {
                        string title = (string)Application.Current.Resources.MergedDictionaries[App._languageResDictIndex]["Timetable_Msg_DayMismatch_Title"];
                        string msg = (string)Application.Current.Resources.MergedDictionaries[App._languageResDictIndex]["Timetable_Msg_DayMismatch_Msg"];
                        //msg: "Day of the week of StartDate ({dayStart}) and chosen row ({dayRow}) do not match."
                        msg = msg.Replace("dayStart", (string)Application.Current.Resources.MergedDictionaries[App._languageResDictIndex][$"Str_Week_{dayStart}"]);
                        msg = msg.Replace("dayRow", (string)Application.Current.Resources.MergedDictionaries[App._languageResDictIndex][$"Str_Week_{dayRow}"]);

                        MessageBox.Show(msg, title);
                        return;
                    }

                    //Check hours are not exceeded
                    AD.Lssn.PeriodStart = curCol;
                    int StartT = curCol;
                    int Hours = AD.Lssn.Hours;
                    int EndT = StartT + Hours;

                    if (EndT > 15)     //lesson would last past allowed timeslots
                    {
                        string title = (string)Application.Current.Resources.MergedDictionaries[App._languageResDictIndex]["Timetable_Msg_IncompatibleTimeslot_Title"];
                        string msg = (string)Application.Current.Resources.MergedDictionaries[App._languageResDictIndex]["Timetable_Msg_IncompatibleTimeslot_Msg"];

                        MessageBox.Show(msg, title);
                        return;
                    }

                    LessonAdd(AD.Lssn, curCol);
                }
            }
        }
        public void LessonAdd(Lesson lsn, int col, bool addedByUser = true)
        {
            //Lesson values
            int StartT = col;
            int Hours = lsn.Hours;
            int EndT = StartT + Hours;

            //New lesson is automatically placed on the row 0
            //If there's already something there, it will be moved to the next row
            int row = 0;
            for (int r = 0; r < RowDefinitions.Count; r++)
            {
                foreach (var child in Children)
                {
                    var childUI = child as UIElement;
                    int childRow = Grid.GetRow(childUI);
                    if ((r == childRow) && (row == childRow))     //Only lessons in the same row are relevant for checking
                    {
                        int bStartT = Grid.GetColumn(childUI);
                        int bEndT = bStartT + Grid.GetColumnSpan(childUI);
                        if (IsOverlapped(StartT, EndT, bStartT, bEndT))
                        {
                            row += 1;
                            break;  //no need to check rest of children in that row
                        }
                    }
                }
            }
            if (!(row < RowDefinitions.Count)) //if there's not enough rows, new one must be added.
            {
                AddRow();
            }

            //New Lesson
            LessonBox lBox = new LessonBox();
            lBox.Lssn = new Lesson(lsn);

            //Place LessonBox at appropriate position
            //lBox.Width = ((this.ActualWidth / 15.0) * lBox.Lssn.Hours) - 10.0;
            lBox.HorizontalAlignment = HorizontalAlignment.Stretch;
            lBox.VerticalAlignment = VerticalAlignment.Stretch;
            Grid.SetRow(lBox, row);
            Grid.SetColumn(lBox, col);
            Grid.SetColumnSpan(lBox, lBox.Lssn.Hours);
            this.Children.Add(lBox);

            if (addedByUser)
            {
                int Id = DBI.InsertLesson(lBox.Lssn);
                lBox.Lssn.Id = Id;
                RaiseEvent(new RoutedEventArgs(TimetableLessonAddedEvent, this));
            }
            

        }
        public void LessonAddNoDescNoNewRow(Lesson lssn, int col, bool isTopmost = false)
        {
            LessonBox lBox = new LessonBox();
            lBox.Lssn = new Lesson(lssn);
            lBox.txtB.Text = "";
            lBox.HorizontalAlignment = HorizontalAlignment.Stretch;
            lBox.VerticalAlignment = VerticalAlignment.Stretch;
            lBox.ContextMenu = null;

            int pr = lssn.Periodicity; //0 - irregular, 1 - weekly, 2-biweekly aka 

            if (pr == 1)
            {
                Grid.SetZIndex(lBox, 2);    //ZIndex shows visual stacking priority, 2-topmost, 0-bottommost
                lBox.txtB.Background = Brushes.LawnGreen;
            }
            else if (pr == 0)
            {
                Grid.SetZIndex(lBox, 0);
                lBox.txtB.Background = Brushes.Gray;
            }
            else{       //pr == 2
                Grid.SetZIndex(lBox, 1);
                lBox.txtB.Background = Brushes.CornflowerBlue;
            }

            if (isTopmost)
            {
                Grid.SetZIndex(lBox, 4);
            }

            Grid.SetRow(lBox, 0);
            Grid.SetColumn(lBox, col);
            Grid.SetColumnSpan(lBox, lssn.Hours);
            
            this.Children.Add(lBox);
        }

        private void LessonEdit(object sender, RoutedEventArgs e)
        {
            var lB = e.OriginalSource as LessonBox;
            if (lB != null)
            {
                var DA = DataContext as AssignmentData;
                if (DA != null)
                {
                    AssignmentData ad = new AssignmentData();
                    ad.SemesterId = DA.SemesterId;
                    ad.CategoryName = DA.CategoryName;
                    ad.CategoryId = DA.CategoryId;
                    ad.Lssn = new Lesson(lB.Lssn);
                    LessonBoxDialog dlg = new LessonBoxDialog(ad);

                    if ((bool)dlg.ShowDialog()) //Ok
                    {
                        lB.Lssn = new Lesson(ad.Lssn);
                        DBI.UpdateLesson(lB.Lssn);
                    }
                }
            }
        }
        private void LessonDelete(object sender, RoutedEventArgs e)
        {
            var grid = sender as Grid;
            var lB = e.OriginalSource as LessonBox;
            if ((grid != null)&&(lB != null))
            {
                DBI.DeleteLesson(lB.Lssn);
                grid.Children.Remove(lB);
                LessonReorder();
            } 
        }
        public void LessonReorder()
        {
            //Find empty spots in the grid and reorder the children if possible
            int[,] OccupiedArray = new int[RowDefinitions.Count, ColumnDefinitions.Count];
            foreach (LessonBox child in Children)
            {
                int row = Grid.GetRow(child);
                int col = Grid.GetColumn(child);
                int colSpan = Grid.GetColumnSpan(child);

                for (int j = col; j < (col + colSpan); j++)
                {
                    OccupiedArray[row, j] = 1;      //0 - empty, 1 - already occupied
                }
            }

            foreach (LessonBox child in Children)
            {
                int row = Grid.GetRow(child);
                if (row != 0)   //r==0 children are already at best possible position
                {
                    int col = Grid.GetColumn(child);
                    int colSpan = Grid.GetColumnSpan(child);

                    for (int r = 0; r < RowDefinitions.Count; r++)
                    {
                        if (r < row)
                        {
                            int nCollisions = 0;
                            for (int j = col; j < (col + colSpan); j++)
                            {
                                nCollisions += OccupiedArray[r, j];
                            }
                            if (nCollisions == 0)   //no collision found
                            {
                                for (int j = col; j < (col + colSpan); j++)
                                {
                                    OccupiedArray[r, j] = 1;    //The new place is now occupied
                                    OccupiedArray[row, j] = 0;  //The old place is now empty
                                }

                                Grid.SetRow(child, r);
                                row = r;
                                break;
                            }
                        }
                        else
                        {
                            break;  //better row cannot be found
                        }

                    }
                }

            }

            //Remove empty rows
            for (int r = (RowDefinitions.Count - 1); r > 0; r--)      //at least row 0 must always be left
            {
                int nCellsOccupied = 0;
                for (int c = 0; c < ColumnDefinitions.Count; c++)
                {
                    nCellsOccupied += OccupiedArray[r, c];
                }

                if (nCellsOccupied == 0)    //there is nothing in that row
                {
                    RowDefinitions.RemoveAt(r);
                }
            }
        }
        
        public bool IsOverlapped(int aStart, int aEnd, int bStart, int bEnd)
        {
            int result = Math.Max(0, Math.Min(aEnd, bEnd) - Math.Max(aStart, bStart));
            if (result > 0) //if true -> there is an overlap of intervals
            {
                return true;
            }

            return false;
        }

        public string SingleCheckForCollisions(Lesson lssn)
        {
            var DA = DataContext as AssignmentData;
            Semester sem = DBI.GetItemById("Semester", DA.SemesterId) as Semester; //Semester is needed to evaluate lesson overlap through time

            for (int j = 0; j < this.Children.Count; j++)
            {
                var lBox = this.Children[j] as LessonBox;
                if (lssn.Id != lBox.Lssn.Id)
                {
                    //if (sem.IsInCollision(lBox.Lssn.StartDateDT, lBox.Lssn.Periodicity, lBox.Lssn.Hours, lBox.Lssn.PeriodStart, lssn.StartDateDT, lssn.Periodicity, lssn.Hours, lssn.PeriodStart))
                    if (sem.IsInCollision(lBox.Lssn,lssn))
                    {
                        string collisionMSG = "\n\n" + lBox.GetLessonInfoExtended();
                        return collisionMSG;
                    }
                }
            }

            return string.Empty;
        }
        public string InternalCheckForCollisions()
        {
            var DA = DataContext as AssignmentData;
            Semester sem = DBI.GetItemById("Semester", DA.SemesterId) as Semester; //Semester is needed to evaluate lesson overlap through time

            string collisionMSG = string.Empty;
            for (int i = 0; i < this.Children.Count; i++)
            {
                var lBox = this.Children[i] as LessonBox;
                for (int j = i; j < this.Children.Count; j++)
                {
                    var lBox_2 = this.Children[j] as LessonBox;
                    if(i != j)
                    {
                        //if (sem.IsInCollision(lBox.Lssn.StartDateDT, lBox.Lssn.Periodicity, lBox.Lssn.Hours, lBox.Lssn.PeriodStart, lBox_2.Lssn.StartDateDT, lBox_2.Lssn.Periodicity, lBox_2.Lssn.Hours, lBox_2.Lssn.PeriodStart))
                        if (sem.IsInCollision(lBox.Lssn, lBox_2.Lssn))
                        {                          
                            if (collisionMSG.Length > 0)
                            {
                                collisionMSG += "\n-------\n";
                            }
                            collisionMSG += lBox.GetLessonInfoExtended();
                            collisionMSG += "\n+\n";
                            collisionMSG += lBox_2.GetLessonInfoExtended();
                        }
                    }
                }
            }

            //return lessonIdList;
            return collisionMSG;
        }
        public string ExternalCheckForCollisions()
        {
            var DA = DataContext as AssignmentData;
            Semester sem = DBI.GetItemById("Semester", DA.SemesterId) as Semester; //Semester is needed to evaluate lesson overlap through time

            string collisionMSG = string.Empty;
            for (int i = 0; i < this.Children.Count; i++)
            {
                var lBox = this.Children[i] as LessonBox;

                List<string> dateList = sem.GetAllDatesOfDayOfWeek(lBox.Lssn.StartDateDT);
                string dateString = string.Empty;
                foreach (string date in dateList)
                {
                    if (dateString.Length > 0)
                    {
                        dateString += ",";
                    }
                    dateString += $"'{date}'";
                }
                ObservableCollection<object> lessons = DBI.LoadPossibleCollisionLessonsOnlyForDays(lBox.Lssn, dateString);

                foreach (Lesson lssn in lessons)
                {
                    //if (sem.IsInCollision(lBox.Lssn.StartDateDT, lBox.Lssn.Periodicity, lBox.Lssn.Hours, lBox.Lssn.PeriodStart, lssn.StartDateDT, lssn.Periodicity, lssn.Hours, lssn.PeriodStart))
                    if (sem.IsInCollision(lBox.Lssn, lssn))
                    {
                        if (collisionMSG.Length > 0)
                        {
                            collisionMSG += "\n-------\n";
                        }
                        collisionMSG += lBox.GetLessonInfoExtended();
                        collisionMSG += "\n+\n";
                        collisionMSG += LessonBox.TranslateInfoText(lssn.GetInfoStringExtended());
                    }

                }

            }

            //return lessonIdList;
            return collisionMSG;
        }

    }
}
