using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using Bowin.Common.Linq;
using Bowin.Common.Linq.Entity;
using EMIS.ViewModel.EducationSchedule;
using EMIS.ViewModel;
using EMIS.DataLogic.EducationSchedule;
using EMIS.Entities;
using EMIS.ViewModel.CalendarManage;
using EMIS.DataLogic.Common.CalendarManage;
using EMIS.CommonLogic.CalendarManage;
using System.Globalization;


namespace EMIS.CommonLogic.EducationSchedule
{
    public class ClassroomExcessiveUseServices : BaseServices, IClassroomExcessiveUseServices
    {
        public ClassroomExcessiveUseDAL ClassroomExcessiveUseDAL { get; set; }

        public Lazy<IScheduleServices> ScheduleServices { get; set; }
        public Lazy<ISchoolYearServices> SchoolYearServices { get; set; }

        public CoursesTimeDAL coursesTimeDAL { get; set; }
        public ISchoolYearServices schoolYearServices { get; set; }
        public IGridResultSet<ClassroomExcessiveUseView> GetClassroomExcessiveUseViewList(ConfiguretView configuretView, Guid? schoolyearID,
            int? weekNum, int? weekday, Guid? courseTimeID, Guid? buildingID, Guid? classroomID, Guid? collegeID, int? pageIndex, int? pageSize)
        {
            Expression<Func<ES_ClassroomExcessiveUse, bool>> exp = (x => x.RecordStatus > (int)SYS_STATUS.UNUSABLE);
            Expression<Func<CF_Classroom, bool>> classroomExp = (x => true);

            if (schoolyearID.HasValue)
            {
                exp = exp.And(x => x.SchoolyearID == schoolyearID);
            }
            if (weekNum.HasValue)
            {
                exp = exp.And(x => x.ES_ClassroomExcessiveUseScheduling.Any(w => w.ES_ClassroomExcessiveUseSchedulingWeekNum.Any(n => n.WeekNum == weekNum)));
            }
            if (weekday.HasValue)
            {
                exp = exp.And(x => x.ES_ClassroomExcessiveUseScheduling.Any(w => w.Weekday == weekday));
            }
            if (courseTimeID.HasValue)
            {
                exp = exp.And(x => x.ES_ClassroomExcessiveUseScheduling.Any(w => w.CoursesTimeID == courseTimeID));
            }
            if (buildingID.HasValue)
            {
                classroomExp = classroomExp.And(x => x.BuildingsInfoID == buildingID);
            }
            if (classroomID.HasValue)
            {
                classroomExp = classroomExp.And(x => x.ClassroomID == classroomID);
            }
            if (collegeID.HasValue)
            {
                exp = exp.And(x => x.CollegeID == collegeID);
            }
            var query = ClassroomExcessiveUseDAL.GetClassroomExcessiveUseViewQueryable(exp, classroomExp);

            if (!string.IsNullOrEmpty(configuretView.ConditionValue))
            {
                query = query.DynamicWhere(configuretView.Attribute, configuretView.Condition, configuretView.ConditionValue);
            }
            query = this.GetQueryByDataRangeByCollege(query);

            var resultList = query.OrderByDescending(x => x.SchoolyearCode).ThenByDescending(x => x.CreateTime)
                .ToGridResultSet(pageIndex, pageSize);
            var resultIDList = resultList.rows.Select(x => x.ClassroomExcessiveUseID).ToList();
            var schedulingList = ClassroomExcessiveUseDAL.GetClassroomExcessiveUseSchedulingViewQueryable((x => resultIDList.Contains(x.ClassroomExcessiveUseID)), (x => true)).ToList();

            resultList.rows.ForEach(x => x.Scheduling = schedulingList.Where(w => w.ClassroomExcessiveUseID == x.ClassroomExcessiveUseID).ToList());

            return resultList;
        }

        public List<ClassroomExcessiveUseView> GetClassroomExcessiveUseViewList(ConfiguretView configuretView, Guid? schoolyearID,
            int? weekNum, int? weekday, Guid? courseTimeID, Guid? buildingID, Guid? classroomID, Guid? collegeID)
        {
            Expression<Func<ES_ClassroomExcessiveUse, bool>> exp = (x => x.RecordStatus > (int)SYS_STATUS.UNUSABLE);
            Expression<Func<CF_Classroom, bool>> classroomExp = (x => true);

            if (schoolyearID.HasValue)
            {
                exp = exp.And(x => x.SchoolyearID == schoolyearID);
            }
            if (weekNum.HasValue)
            {
                exp = exp.And(x => x.ES_ClassroomExcessiveUseScheduling.Any(w => w.ES_ClassroomExcessiveUseSchedulingWeekNum.Any(n => n.WeekNum == weekNum)));
            }
            if (weekday.HasValue)
            {
                exp = exp.And(x => x.ES_ClassroomExcessiveUseScheduling.Any(w => w.Weekday == weekday));
            }
            if (courseTimeID.HasValue)
            {
                exp = exp.And(x => x.ES_ClassroomExcessiveUseScheduling.Any(w => w.CoursesTimeID == courseTimeID));
            }
            if (buildingID.HasValue)
            {
                classroomExp = classroomExp.And(x => x.BuildingsInfoID == buildingID);
            }
            if (classroomID.HasValue)
            {
                classroomExp = classroomExp.And(x => x.ClassroomID == classroomID);
            }
            if (collegeID.HasValue)
            {
                exp = exp.And(x => x.CollegeID == collegeID);
            }
            var query = ClassroomExcessiveUseDAL.GetClassroomExcessiveUseViewQueryable(exp, classroomExp);
            var schedulingQuery = ClassroomExcessiveUseDAL.GetClassroomExcessiveUseSchedulingViewQueryable(exp, classroomExp);

            if (!string.IsNullOrEmpty(configuretView.ConditionValue))
            {
                query = query.DynamicWhere(configuretView.Attribute, configuretView.Condition, configuretView.ConditionValue);
            }
            query = this.GetQueryByDataRangeByCollege(query);
            schedulingQuery = this.GetQueryByDataRangeByCollege(schedulingQuery);

            var resultList = query.OrderByDescending(x => x.SchoolyearCode).ThenByDescending(x => x.CreateTime)
                .ToList();
            var schedulingList = schedulingQuery.ToList();

            resultList.ForEach(x => x.Scheduling = schedulingList.Where(w => w.ClassroomExcessiveUseID == x.ClassroomExcessiveUseID).ToList());

            return resultList;
        }

        public void Delete(IList<Guid> classroomExcessiveUseIDList)
        {
            this.UnitOfWork.Delete<ES_ClassroomExcessiveUseSchedulingWeekNum>(x => classroomExcessiveUseIDList.Contains(x.ES_ClassroomExcessiveUseScheduling.ClassroomExcessiveUseID.Value));
            this.UnitOfWork.Delete<ES_ClassroomExcessiveUseScheduling>(x => classroomExcessiveUseIDList.Contains(x.ClassroomExcessiveUseID.Value));
            this.UnitOfWork.Delete<ES_ClassroomExcessiveUse>(x => classroomExcessiveUseIDList.Contains(x.ClassroomExcessiveUseID));
        }

        public ClassroomExcessiveUseView GetClassroomExcessiveUseView(Guid classroomExcessiveUseID)
        {
            var query = ClassroomExcessiveUseDAL.GetClassroomExcessiveUseViewQueryable((x => x.ClassroomExcessiveUseID == classroomExcessiveUseID), (x => true));

            var result = query.FirstOrDefault();
            return result;
        }

        public List<ClassroomExcessiveUseSchedulingView> GetClassroomExcessiveUseSchedulingViewList(Guid classroomExcessiveUseID)
        {
            return ClassroomExcessiveUseDAL.GetClassroomExcessiveUseSchedulingViewQueryable(x => x.ClassroomExcessiveUseID == classroomExcessiveUseID, (x => true)).ToList();
        }

        public void Save(ClassroomExcessiveUseView classroomExcessiveUseView, List<ClassroomExcessiveUseSchedulingView> classroomExcessiveUseSchedulingViewList)
        {
            ES_ClassroomExcessiveUse classroomExcessiveUse = new ES_ClassroomExcessiveUse();

            if (!classroomExcessiveUseView.SchoolyearID.HasValue)
            {
                throw new Exception("学年学期不能为空。");
            }
            if (!classroomExcessiveUseView.ClassroomID.HasValue)
            {
                throw new Exception("教室不能为空。");
            }
            if (classroomExcessiveUseSchedulingViewList.Any(x => !x.Weekday.HasValue))
            {
                throw new Exception("星期不能为空。");
            }
            //if (classroomExcessiveUseSchedulingViewList.Any(x => !x.CoursesTimeID.HasValue))
            //{
            //    throw new Exception("节次不能为空。");
            //}

            if (classroomExcessiveUseView.ClassroomExcessiveUseID == null || classroomExcessiveUseView.ClassroomExcessiveUseID == Guid.Empty)
            {
                classroomExcessiveUse = new ES_ClassroomExcessiveUse();
                classroomExcessiveUse.ClassroomExcessiveUseID = Guid.NewGuid();
                SetNewStatus(classroomExcessiveUse);
                UnitOfWork.Add(classroomExcessiveUse);
            }
            else
            {
                classroomExcessiveUse = ClassroomExcessiveUseDAL.ClassroomExcessiveUseRepository
                        .GetSingle(x => x.ClassroomExcessiveUseID == classroomExcessiveUseView.ClassroomExcessiveUseID, (x => x.ES_ClassroomExcessiveUseScheduling.Select(w => w.ES_ClassroomExcessiveUseSchedulingWeekNum)));
                SetModifyStatus(classroomExcessiveUse);

                if (classroomExcessiveUse == null)
                {
                    throw new Exception("数据有误,请核查。");
                }

                classroomExcessiveUse.ES_ClassroomExcessiveUseScheduling.SelectMany(x => x.ES_ClassroomExcessiveUseSchedulingWeekNum).ToList()
                    .ForEach(x => UnitOfWork.Remove(x));
                classroomExcessiveUse.ES_ClassroomExcessiveUseScheduling.ToList()
                    .ForEach(x => UnitOfWork.Remove(x));
            }

            classroomExcessiveUse.ClassroomID = classroomExcessiveUseView.ClassroomID;
            classroomExcessiveUse.SchoolyearID = classroomExcessiveUseView.SchoolyearID;
            classroomExcessiveUse.CollegeID = classroomExcessiveUseView.CollegeID;
            classroomExcessiveUse.UserID = classroomExcessiveUseView.UserID;
            classroomExcessiveUse.Content = classroomExcessiveUseView.Content;
            var coursesTimeList = ClassroomExcessiveUseDAL.CoursesTimeRepository.GetList(x => x.RecordStatus == (int)SYS_STATUS.USABLE).ToList();
            var ClassroomConflictList = ClassroomExcessiveUseDAL.GetExaminationPlanViewByClassroom(classroomExcessiveUseView.SchoolyearID, classroomExcessiveUseView.ClassroomID).ToList();
            var schoolYearView = schoolYearServices.GetSchoolYear(classroomExcessiveUseView.SchoolyearID);
            classroomExcessiveUseSchedulingViewList.ForEach(x => {
                if (x.CoursesTimeID == null)
                {
                    foreach (var courseTime in coursesTimeList)
                    {
                        //排考冲突判断
                        foreach (var classroomConflict in ClassroomConflictList)
                        {
                            var weekday = (int)classroomConflict.ExaminationDate.Value.DayOfWeek;
                            var days = (classroomConflict.ExaminationDate.Value - schoolYearView.FirstWeek).Days + 1;
                            var firstWeekday = (int)schoolYearView.FirstWeek.DayOfWeek;
                            var weekNum = 0;
                            if ((days - firstWeekday) % 7 == 0)
                            {
                                weekNum = (days - (8 - firstWeekday)) / 7 + 1;
                            }
                            else {
                                weekNum = (days - (8 - firstWeekday)) / 7 + 2;
                            }

                            if (x.WeekNumList.Contains(weekNum) && x.Weekday == weekday)
                            {
                                throw new Exception("教室已被排考占用。");
                            }
                        }
                        if (!ClassroomExcessiveUseDAL.GetAvailableClassroom(classroomExcessiveUse.SchoolyearID.Value,
                        x.WeekNumList.ToList(), x.Weekday.Value, courseTime.CoursesTimeID, classroomExcessiveUse.ClassroomID.Value, x.ClassroomExcessiveUseID).Any())
                        {
                            throw new Exception("教室已被占用或预留。");
                        }

                        ES_ClassroomExcessiveUseScheduling scheduling = new ES_ClassroomExcessiveUseScheduling();
                        scheduling.ClassroomExcessiveUseSchedulingID = Guid.NewGuid();
                        scheduling.ClassroomExcessiveUseID = classroomExcessiveUse.ClassroomExcessiveUseID;
                        scheduling.Weekday = x.Weekday;
                        scheduling.CoursesTimeID = courseTime.CoursesTimeID;
                        this.SetNewStatus(scheduling);
                        UnitOfWork.Add(scheduling);

                        foreach (var weekNum in x.WeekNumList)
                        {
                            ES_ClassroomExcessiveUseSchedulingWeekNum weekNumSet = new ES_ClassroomExcessiveUseSchedulingWeekNum();
                            weekNumSet.ClassroomExcessiveUseSchedulingWeekNumID = Guid.NewGuid();
                            weekNumSet.ClassroomExcessiveUseSchedulingID = scheduling.ClassroomExcessiveUseSchedulingID;
                            weekNumSet.WeekNum = weekNum;
                            this.SetNewStatus(weekNumSet);
                            UnitOfWork.Add(weekNumSet);
                        }
                    }
                }
                else
                {
                    //排考冲突判断
                    //var coursesTime = coursesTimeList.Where(y => y.c)
                    foreach (var classroomConflict in ClassroomConflictList)
                    {
                        var weekday = (int)classroomConflict.ExaminationDate.Value.DayOfWeek;
                        var days = (classroomConflict.ExaminationDate.Value - schoolYearView.FirstWeek).Days + 1;
                        var firstWeekday = (int)schoolYearView.FirstWeek.DayOfWeek;
                        var weekNum = 0;
                        if ((days - firstWeekday) % 7 == 0)
                        {
                            weekNum = (days - (8 - firstWeekday)) / 7 + 1;
                        }
                        else
                        {
                            weekNum = (days - (8 - firstWeekday)) / 7 + 2;
                        }
                        //将时间段都转换成当天的时间进行比较
                        var startTimeStr = x.StartHour.ToString() + ":" + x.StartMinute.ToString();
                        var startTime = DateTime.Parse(startTimeStr);
                        var endTimeStr = x.EndHour.ToString() + ":" + x.EndMinute.ToString();
                        var endTime = DateTime.Parse(endTimeStr);
                        DateTime start = DateTime.Now.Date;
                        DateTime constartTime = start.Add(classroomConflict.StartTime.Value);
                        DateTime conendTime = start.Add(classroomConflict.EndTime.Value);
                        if (x.WeekNumList.Contains(weekNum) && x.Weekday == weekday && ((startTime >= Convert.ToDateTime(constartTime) && startTime < Convert.ToDateTime(conendTime)) || (endTime > Convert.ToDateTime(constartTime) && endTime <= Convert.ToDateTime(conendTime)) || (startTime <= Convert.ToDateTime(constartTime) && endTime >= Convert.ToDateTime(conendTime))))
                        {
                            throw new Exception("教室已被排考占用,占用情况请参考考场安排表。");
                        }
                        
                    }
                    //这个检测暂时不支持批量,由于这类数据估计也就一两条,暂时用循环顶着,后续如果有处理量大的影响性能再优化
                    if (!ClassroomExcessiveUseDAL.GetAvailableClassroom(classroomExcessiveUse.SchoolyearID.Value,
                        x.WeekNumList.ToList(), x.Weekday.Value, x.CoursesTimeID.Value, classroomExcessiveUse.ClassroomID.Value, x.ClassroomExcessiveUseID).Any())
                    {
                        throw new Exception("教室已被占用或预留。");
                    }

                    ES_ClassroomExcessiveUseScheduling scheduling = new ES_ClassroomExcessiveUseScheduling();
                    scheduling.ClassroomExcessiveUseSchedulingID = Guid.NewGuid();
                    scheduling.ClassroomExcessiveUseID = classroomExcessiveUse.ClassroomExcessiveUseID;
                    scheduling.Weekday = x.Weekday;
                    scheduling.CoursesTimeID = x.CoursesTimeID;
                    this.SetNewStatus(scheduling);
                    UnitOfWork.Add(scheduling);

                    foreach (var weekNum in x.WeekNumList)
                    {
                        ES_ClassroomExcessiveUseSchedulingWeekNum weekNumSet = new ES_ClassroomExcessiveUseSchedulingWeekNum();
                        weekNumSet.ClassroomExcessiveUseSchedulingWeekNumID = Guid.NewGuid();
                        weekNumSet.ClassroomExcessiveUseSchedulingID = scheduling.ClassroomExcessiveUseSchedulingID;
                        weekNumSet.WeekNum = weekNum;
                        this.SetNewStatus(weekNumSet);
                        UnitOfWork.Add(weekNumSet);
                    }
                }
            });

            UnitOfWork.Commit();
        }

        public IGridResultSet<CoursesTimeView> GetCoursesTimeViewGrid(ConfiguretView configuretView, Guid schoolYearID, 
            List<int?> schedulingWeekList, int weekday, Guid classroomID, int pageIndex, int pageSize)
        {
            var usedCoursesTime = ClassroomExcessiveUseDAL.GetUsedCourseTime(schoolYearID, schedulingWeekList, weekday, classroomID);


            var query = coursesTimeDAL.GetCoursesTimeQueryable(x => x.RecordStatus > (int)SYS_STATUS.UNUSABLE && !usedCoursesTime.Contains(x.CoursesTimeID));

            if (!string.IsNullOrEmpty(configuretView.ConditionValue))
                return query.DynamicWhere(configuretView.Attribute, configuretView.Condition, configuretView.ConditionValue).OrderByDescending(x => x.CreateTime).ToGridResultSet<CoursesTimeView>(pageIndex, pageSize);
            return query.OrderBy(x => x.StartTimes).ToGridResultSet<CoursesTimeView>(pageIndex, pageSize);
        }

        public List<ClassroomExcessiveUseWeekNumView> GetClassroomExcessiveUseWeekNumViewByDateTimeList(Guid schoolyearID, IList<StartEndTimeView> dateTimeList)
        {
            var fullCoursesTimeList = this.SchoolYearServices.Value.GetCoursesTimeByDateTime(schoolyearID, dateTimeList);
            var coursesTimeList = fullCoursesTimeList.Select(x => new { x.WeekNum, x.Weekday, x.CoursesTimeID }).ToList();

            var classroomExcessiveUseViewList = this.ClassroomExcessiveUseDAL.GetClassroomExcessiveUseWeekNumViewQueryable(x => x.SchoolyearID == schoolyearID, x => true)
                                              .SelectByKeys(coursesTimeList).ToList();

            classroomExcessiveUseViewList.ForEach(x =>
            {
                var fullCoursesTime = fullCoursesTimeList.FirstOrDefault(w => w.WeekNum == x.WeekNum && w.Weekday == x.Weekday && w.CoursesTimeID == x.CoursesTimeID);
                x.Date = fullCoursesTime.Date;
                x.StartTime = new TimeSpan(fullCoursesTime.StartHour ?? 0, fullCoursesTime.StartMinute ?? 0, 0);
                x.EndTime = new TimeSpan(fullCoursesTime.EndHour ?? 0, fullCoursesTime.EndMinute ?? 0, 0);
            });
            return classroomExcessiveUseViewList;
        }
    }
}